Merge pull request #1332 from kijin/next-db

DB 접속 방법 변경 및 XML 문법 확장
This commit is contained in:
Kijin Sung 2020-07-02 12:11:49 +09:00 committed by GitHub
commit 3e41832930
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
129 changed files with 3422 additions and 14205 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,749 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts
* @version 0.1
*/
class Query extends BaseObject
{
/**
* Query id, defined in query xml file
* @var string
*/
var $queryID;
/**
* DML type, ex) INSERT, DELETE, UPDATE, SELECT
* @var string
*/
var $action;
/**
* priority level ex)LOW_PRIORITY, HIGHT_PRIORITY
* @var string
*/
var $priority;
/**
* column list
* @var string|array
*/
var $columns;
/**
* table list
* @var string|array
*/
var $tables;
/**
* condition list
* @var string|array
*/
var $conditions;
/**
* group list
* @var string|array
*/
var $groups;
/**
* having list
* @var string|array
*/
var $having;
/**
* order list
* @var array
*/
var $orderby;
/**
* limit count
* @var int
*/
var $limit;
/**
* argument list
* @var array
*/
var $arguments = NULL;
/**
* column list
* @var array
*/
var $columnList = NULL;
/**
* order by text
* @var string
*/
var $_orderByString;
/**
* constructor
* @param string $queryID
* @param string $action
* @param string|array $columns
* @param string|array $tables
* @param string|array $conditions
* @param string|array $groups
* @param string|array $orderby
* @param int $limit
* @param string $priority
* @return void
*/
function __construct($queryID = NULL
, $action = NULL
, $columns = NULL
, $tables = NULL
, $conditions = NULL
, $groups = NULL
, $orderby = NULL
, $limit = NULL
, $priority = NULL)
{
$this->queryID = $queryID;
$this->action = $action;
$this->priority = $priority;
if(!isset($tables))
{
return;
}
$this->columns = $this->setColumns($columns);
$this->tables = $this->setTables($tables);
$this->conditions = $this->setConditions($conditions);
$this->groups = $this->setGroups($groups);
$this->orderby = $this->setOrder($orderby);
$this->limit = $this->setLimit($limit);
}
function show()
{
return TRUE;
}
function setQueryId($queryID)
{
$this->queryID = $queryID;
}
function setAction($action)
{
$this->action = $action;
}
function setPriority($priority)
{
$this->priority = $priority;
}
function setColumnList($columnList)
{
if (!is_array($this->columnList)) return;
$this->columnList = $columnList;
if(count($this->columnList) > 0)
{
$selectColumns = array();
$dbParser = DB::getParser();
foreach($this->columnList as $columnName)
{
$columnName = $dbParser->escapeColumnExpression($columnName);
$selectColumns[] = new SelectExpression($columnName);
}
unset($this->columns);
$this->columns = $selectColumns;
}
}
function setColumns($columns)
{
if(!isset($columns) || count($columns) === 0)
{
$this->columns = array(new StarExpression());
return;
}
if(!is_array($columns))
{
$columns = array($columns);
}
$this->columns = $columns;
}
function setTables($tables)
{
if(!isset($tables) || count($tables) === 0)
{
$this->setError(TRUE);
$this->setMessage("You must provide at least one table for the query.");
return;
}
if(!is_array($tables))
{
$tables = array($tables);
}
$this->tables = $tables;
}
function setSubquery($subquery)
{
$this->subquery = $subquery;
}
function setConditions($conditions)
{
$this->conditions = array();
if(!isset($conditions) || count($conditions) === 0)
{
return;
}
if(!is_array($conditions))
{
$conditions = array($conditions);
}
foreach($conditions as $conditionGroup)
{
if($conditionGroup->show())
{
$this->conditions[] = $conditionGroup;
}
}
}
function setGroups($groups)
{
if(!isset($groups) || count($groups) === 0)
{
return;
}
if(!is_array($groups))
{
$groups = array($groups);
}
$this->groups = $groups;
}
function setHaving($conditions)
{
$this->having = array();
if(!isset($conditions) || count($conditions) === 0)
{
return;
}
if(!is_array($conditions))
{
$conditions = array($conditions);
}
foreach($conditions as $conditionGroup)
{
if($conditionGroup->show())
{
$this->having[] = $conditionGroup;
}
}
}
function setOrder($order)
{
if(!isset($order) || count($order) === 0)
{
return;
}
if(!is_array($order))
{
$order = array($order);
}
$this->orderby = $order;
}
function getOrder()
{
return $this->orderby;
}
function setLimit($limit = NULL)
{
if(!isset($limit))
{
return;
}
$this->limit = $limit;
}
// START Fluent interface
/**
* seleect set
* @param string|array $columns
* @return Query return Query instance
*/
function select($columns = NULL)
{
$this->action = 'select';
$this->setColumns($columns);
return $this;
}
/**
* from set
* @param string|array $tables
* @return Query return Query instance
*/
function from($tables)
{
$this->setTables($tables);
return $this;
}
/**
* where set
* @param string|array $conditions
* @return Query return Query instance
*/
function where($conditions)
{
$this->setConditions($conditions);
return $this;
}
/**
* groupBy set
* @param string|array $groups
* @return Query return Query instance
*/
function groupBy($groups)
{
$this->setGroups($groups);
return $this;
}
/**
* orderBy set
* @param string|array $order
* @return Query return Query instance
*/
function orderBy($order)
{
$this->setOrder($order);
return $this;
}
/**
* limit set
* @param int $limit
* @return Query return Query instance
*/
function limit($limit)
{
$this->setLimit($limit);
return $this;
}
// END Fluent interface
function getAction()
{
return $this->action;
}
function getPriority()
{
return $this->priority ? 'LOW_PRIORITY' : '';
}
/**
* Check if current query uses the click count attribute
* For CUBRID, this statement uses the click count feature.
* For the other databases, using this attribute causes a query
* to produce both a select and an update
*/
function usesClickCount()
{
return count($this->getClickCountColumns()) > 0;
}
function getClickCountColumns()
{
$click_count_columns = array();
foreach($this->columns as $column)
{
if($column->show() && is_a($column, 'ClickCountExpression'))
{
$click_count_columns[] = $column;
}
}
return $click_count_columns;
}
/**
* Return select sql
* @param boolean $with_values
* @return string
*/
function getSelectString($with_values = TRUE)
{
foreach($this->columns as $column)
{
if($column->show())
{
if($column->isSubquery())
{
$select[] = $column->toString($with_values) . ' as ' . $column->getAlias();
}
else
{
$select[] = $column->getExpression($with_values);
}
}
}
return trim(implode($select, ', '));
}
/**
* Return update sql
* @param boolean $with_values
* @return string
*/
function getUpdateString($with_values = TRUE)
{
foreach($this->columns as $column)
{
if($column->show())
{
$update[] = $column->getExpression($with_values);
}
}
if(!$update) return;
return trim(implode($update, ', '));
}
/**
* Return insert sql
* @param boolean $with_values
* @return string
*/
function getInsertString($with_values = TRUE)
{
$columnsList = '';
// means we have insert-select
if($this->subquery)
{
foreach($this->columns as $column)
{
$columnsList .= $column->getColumnName() . ', ';
}
$columnsList = substr($columnsList, 0, -2);
$selectStatement = $this->subquery->toString($with_values);
$selectStatement = substr($selectStatement, 1, -1);
return "($columnsList) \n $selectStatement";
}
$valuesList = '';
foreach($this->columns as $column)
{
if($column->show())
{
$columnsList .= $column->getColumnName() . ', ';
$valuesList .= $column->getValue($with_values) . ', ';
}
}
$columnsList = substr($columnsList, 0, -2);
$valuesList = substr($valuesList, 0, -2);
return "($columnsList) \n VALUES ($valuesList)";
}
function getTables()
{
return $this->tables;
}
/**
* from table_a
* from table_a inner join table_b on x=y
* from (select * from table a) as x
* from (select * from table t) as x inner join table y on y.x
* @param boolean $with_values
* @return string
*/
function getFromString($with_values = TRUE)
{
$from = '';
$simple_table_count = 0;
foreach($this->tables as $table)
{
if($table->isJoinTable() || !$simple_table_count)
{
$from .= $table->toString($with_values) . ' ';
}
else
{
$from .= ', ' . $table->toString($with_values) . ' ';
}
if(is_a($table, 'Subquery'))
{
$from .= $table->getAlias() ? ' as ' . $table->getAlias() . ' ' : ' ';
}
$simple_table_count++;
}
if(trim($from) == '')
{
return '';
}
return $from;
}
/**
* Return where sql
* @param boolean $with_values
* @param boolean $with_optimization
* @return string
*/
function getWhereString($with_values = TRUE, $with_optimization = TRUE)
{
$where = '';
$condition_count = 0;
foreach($this->conditions as $conditionGroup)
{
if($condition_count === 0)
{
$conditionGroup->setPipe("");
}
$condition_string = $conditionGroup->toString($with_values);
$where .= $condition_string;
$condition_count++;
}
if($with_optimization &&
(strstr($this->getOrderByString(), 'list_order') || strstr($this->getOrderByString(), 'update_order')))
{
if($condition_count !== 0)
{
$where = '(' . $where . ') ';
}
foreach($this->orderby as $order)
{
$colName = $order->getColumnName();
if(strstr($colName, 'list_order') || strstr($colName, 'update_order'))
{
$opt_condition = new ConditionWithoutArgument($colName, 2100000000, 'less', 'and');
if($condition_count === 0)
{
$opt_condition->setPipe("");
}
$where .= $opt_condition->toString($with_values) . ' ';
$condition_count++;
}
}
}
return trim($where);
}
/**
* Return groupby sql
* @return string
*/
function getGroupByString()
{
$groupBy = '';
if($this->groups)
{
if($this->groups[0] !== "")
{
$groupBy = implode(', ', $this->groups);
}
}
return $groupBy;
}
/**
* Return having sql
* @param boolean $with_values
* @return string
*/
function getHavingString($with_values = TRUE)
{
if(!is_array($this->having))
{
return '';
}
$having = '';
$condition_count = 0;
foreach($this->having as $conditionGroup)
{
if($condition_count === 0)
{
$conditionGroup->setPipe("");
}
$condition_string = $conditionGroup->toString($with_values);
$having .= $condition_string;
$condition_count++;
}
return trim($having);
}
/**
* Return orderby sql
* @return string
*/
function getOrderByString()
{
if(!$this->_orderByString)
{
if(countobj($this->orderby) === 0)
{
return '';
}
$orderBy = '';
foreach($this->orderby as $order)
{
$orderBy .= $order->toString() . ', ';
}
$orderBy = substr($orderBy, 0, -2);
$this->_orderByString = $orderBy;
}
return $this->_orderByString;
}
function getLimit()
{
return $this->limit;
}
/**
* Return limit sql
* @return string
*/
function getLimitString()
{
$limit = '';
if(countobj($this->limit) > 0)
{
$limit = '';
$limit .= $this->limit->toString();
}
return $limit;
}
function getFirstTableName()
{
return $this->tables[0]->getName();
}
/**
* Return argument list
* @return array
*/
function getArguments()
{
if(!isset($this->arguments))
{
$this->arguments = array();
// Join table arguments
if(countobj($this->tables) > 0)
{
foreach($this->tables as $table)
{
if($table->isJoinTable() || is_a($table, 'Subquery'))
{
$args = $table->getArguments();
if($args)
{
$this->arguments = array_merge($this->arguments, $args);
}
}
}
}
// Column arguments
// The if is for delete statements, all others must have columns
if(countobj($this->columns) > 0)
{
foreach($this->columns as $column)
{
if($column->show())
{
$args = $column->getArguments();
if($args)
{
$this->arguments = array_merge($this->arguments, $args);
}
}
}
}
// Condition arguments
if(countobj($this->conditions) > 0)
{
foreach($this->conditions as $conditionGroup)
{
$args = $conditionGroup->getArguments();
if(countobj($args) > 0)
{
$this->arguments = array_merge($this->arguments, $args);
}
}
}
// Having arguments
if(countobj($this->having) > 0)
{
foreach($this->having as $conditionGroup)
{
$args = $conditionGroup->getArguments();
if(countobj($args) > 0)
{
$this->arguments = array_merge($this->arguments, $args);
}
}
}
// Navigation arguments
if(countobj($this->orderby) > 0)
{
foreach($this->orderby as $order)
{
$args = $order->getArguments();
if(countobj($args) > 0)
{
$this->arguments = array_merge($this->arguments, $args);
}
}
}
}
return $this->arguments;
}
}
/* End of file Query.class.php */
/* Location: ./classes/db/queryparts/Query.class.php */

View file

@ -1,80 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts
* @version 0.1
*/
class Subquery extends Query
{
/**
* table alias
* @var string
*/
var $alias;
/**
* join type
* @var string
*/
var $join_type;
/**
* constructor
* @param string $alias
* @param string|array $columns
* @param string|array $tables
* @param string|array $conditions
* @param string|array $groups
* @param string|array $orderby
* @param int $limit
* @param string $join_type
* @return void
*/
function __construct($alias, $columns, $tables, $conditions, $groups, $orderby, $limit, $join_type = null)
{
$this->alias = $alias;
$this->queryID = null;
$this->action = "select";
$this->columns = $columns;
$this->tables = $tables;
$this->conditions = $conditions;
$this->groups = $groups;
$this->orderby = $orderby;
$this->limit = $limit;
$this->join_type = $join_type;
}
function getAlias()
{
return $this->alias;
}
function isJoinTable()
{
if($this->join_type)
{
return true;
}
return false;
}
function toString($with_values = true)
{
$oDB = &DB::getInstance();
return '(' . $oDB->getSelectSql($this, $with_values) . ')';
}
function isSubquery()
{
return true;
}
}
/* End of file Subquery.class.php */
/* Location: ./classes/db/queryparts/Subquery.class.php */

View file

@ -1,277 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/condition
* @version 0.1
*/
class Condition
{
/**
* column name
* @var string
*/
var $column_name;
var $argument;
/**
* operation can use 'equal', 'more', 'excess', 'less', 'below', 'like_tail', 'like_prefix', 'like', 'notlike_tail',
* 'notlike_prefix', 'notlike', 'in', 'notin', 'not_in', 'and', 'or', 'xor', 'not', 'notequal', 'between'
* 'null', 'notnull'
* @var string
*/
var $operation;
/**
* pipe can use 'and', 'or'...
* @var string
*/
var $pipe;
var $_value;
var $_show;
var $_value_to_string;
/**
* constructor
* @param string $column_name
* @param mixed $argument
* @param string $operation
* @param string $pipe
* @return void
*/
function __construct($column_name, $argument, $operation, $pipe = 'and')
{
$this->column_name = $column_name;
$this->argument = $argument;
$this->operation = $operation;
$this->pipe = $pipe;
}
function getArgument()
{
return null;
}
/**
* value to string
* @param boolean $withValue
* @return string
*/
function toString($withValue = true)
{
if(!isset($this->_value_to_string))
{
if(!$this->show())
{
$this->_value_to_string = '';
}
else if($withValue)
{
$this->_value_to_string = $this->toStringWithValue();
}
else
{
$this->_value_to_string = $this->toStringWithoutValue();
}
}
return $this->_value_to_string;
}
/**
* change string without value
* @return string
*/
function toStringWithoutValue()
{
return strtoupper($this->pipe) . ' ' . $this->getConditionPart($this->_value);
}
/**
* change string with value
* @return string
*/
function toStringWithValue()
{
return strtoupper($this->pipe) . ' ' . $this->getConditionPart($this->_value);
}
function setPipe($pipe)
{
$this->pipe = $pipe;
}
/**
* @return boolean
*/
function show()
{
if(!isset($this->_show))
{
if(is_array($this->_value) && count($this->_value) === 1 && $this->_value[0] === '')
{
$this->_show = false;
}
else
{
$this->_show = true;
switch($this->operation)
{
case 'equal' :
case 'more' :
case 'excess' :
case 'less' :
case 'below' :
case 'gte' :
case 'gt' :
case 'lte' :
case 'lt' :
case 'like_tail' :
case 'like_prefix' :
case 'like' :
case 'notlike_tail' :
case 'notlike_prefix' :
case 'notlike' :
case 'not_like' :
case 'regexp' :
case 'notregexp' :
case 'not_regexp' :
case 'in' :
case 'notin' :
case 'not_in' :
case 'and':
case 'or':
case 'xor':
case 'not':
case 'notequal' :
case 'not_equal' :
// if variable is not set or is not string or number, return
if(!isset($this->_value))
{
$this->_show = false;
break;
}
if($this->_value === '')
{
$this->_show = false;
break;
}
$tmpArray = array('string' => 1, 'integer' => 1);
if(!isset($tmpArray[gettype($this->_value)]))
{
$this->_show = false;
break;
}
break;
case 'between' :
if(!is_array($this->_value))
{
$this->_show = false;
break;
}
if(count($this->_value) != 2)
{
$this->_show = false;
break;
}
case 'null':
case 'notnull':
case 'not_null':
break;
default:
// If operation is not one of the above, means the condition is invalid
$this->_show = false;
}
}
}
return $this->_show;
}
/**
* Return condition string
* @param int|string|array $value
* @return string
*/
function getConditionPart($value)
{
$name = $this->column_name;
$operation = $this->operation;
switch($operation)
{
case 'equal' :
return $name . ' = ' . $value;
break;
case 'more' :
case 'gte' :
return $name . ' >= ' . $value;
break;
case 'excess' :
case 'gt' :
return $name . ' > ' . $value;
break;
case 'less' :
case 'lte' :
return $name . ' <= ' . $value;
break;
case 'below' :
case 'lt' :
return $name . ' < ' . $value;
break;
case 'like_tail' :
case 'like_prefix' :
case 'like' :
return $name . ' LIKE ' . $value;
case 'notlike_tail' :
case 'notlike_prefix' :
case 'notlike' :
case 'not_like' :
return $name . ' NOT LIKE ' . $value;
break;
case 'regexp' :
return $name . ' REGEXP ' . $value;
break;
case 'notregexp' :
case 'not_regexp' :
return $name . ' NOT REGEXP ' . $value;
break;
case 'in' :
return $name . ' IN ' . $value;
break;
case 'notin' :
case 'not_in' :
return $name . ' NOT IN ' . $value;
break;
case 'notequal' :
case 'not_equal' :
return $name . ' <> ' . $value;
break;
case 'notnull' :
case 'not_null' :
return $name . ' IS NOT NULL ';
break;
case 'null' :
return $name . ' IS NULL ';
break;
case 'and' :
return $name . ' & ' . $value;
break;
case 'or' :
return $name . ' | ' . $value;
break;
case 'xor' :
return $name . ' ^ ' . $value;
break;
case 'not' :
return $name . ' ~ ' . $value;
break;
case 'between' :
return $name . ' BETWEEN ' . $value[0] . ' AND ' . $value[1];
break;
}
}
}
/* End of file Condition.class.php */
/* Location: ./classes/db/queryparts/condition/Condition.class.php */

View file

@ -1,133 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/condition
* @version 0.1
*/
class ConditionGroup
{
/**
* condition list
* @var array
*/
var $conditions;
/**
* pipe can use 'and', 'or'...
* @var string
*/
var $pipe;
var $_group;
var $_show;
/**
* constructor
* @param array $conditions
* @param string $pipe
* @return void
*/
function __construct($conditions, $pipe = 'and')
{
$this->conditions = array();
foreach($conditions as $condition)
{
if($condition->show())
{
$this->conditions[] = $condition;
}
}
if(count($this->conditions) === 0)
{
$this->_show = false;
}
else
{
$this->_show = true;
}
$this->pipe = $pipe;
}
function show()
{
return $this->_show;
}
function setPipe($pipe)
{
if($this->pipe !== $pipe)
{
$this->_group = null;
}
$this->pipe = $pipe;
}
/**
* value to string
* @param boolean $with_value
* @return string
*/
function toString($with_value = true)
{
if(!isset($this->_group))
{
$cond_indx = 0;
$group = '';
foreach($this->conditions as $condition)
{
if($cond_indx === 0)
{
$condition->setPipe("");
}
$group .= $condition->toString($with_value) . ' ';
$cond_indx++;
}
if($this->pipe !== "" && trim($group) !== '')
{
$group = strtoupper($this->pipe) . ' (' . $group . ')';
}
$this->_group = $group;
}
return $this->_group;
}
/**
* return argument list
* @return array
*/
function getArguments()
{
$args = array();
foreach($this->conditions as $condition)
{
if($condition instanceof ConditionGroup)
{
foreach($condition->getArguments() as $arg)
{
if($arg)
{
$args[] = $arg;
}
}
}
else
{
$arg = $condition->getArgument();
if($arg)
{
$args[] = $arg;
}
}
}
return $args;
}
}
/* End of file ConditionGroup.class.php */
/* Location: ./classes/db/queryparts/condition/ConditionGroup.class.php */

View file

@ -1,28 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/condition
* @version 0.1
*/
class ConditionSubquery extends Condition
{
/**
* constructor
* @param string $column_name
* @param mixed $argument
* @param string $operation
* @param string $pipe
* @return void
*/
function __construct($column_name, $argument, $operation, $pipe = "")
{
parent::__construct($column_name, $argument, $operation, $pipe);
$this->_value = $this->argument->toString();
}
}
/* End of file ConditionSubquery.class.php */
/* Location: ./classes/db/queryparts/condition/ConditionSubquery.class.php */

View file

@ -1,99 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/condition
* @version 0.1
*/
class ConditionWithArgument extends Condition
{
/**
* constructor
* @param string $column_name
* @param mixed $argument
* @param string $operation
* @param string $pipe
* @return void
*/
function __construct($column_name, $argument, $operation, $pipe = "")
{
if($argument === null)
{
$this->_show = false;
return;
}
parent::__construct($column_name, $argument, $operation, $pipe);
$this->_value = $argument->getValue();
}
function getArgument()
{
if(!$this->show())
return;
return $this->argument;
}
/**
* change string without value
* @return string
*/
function toStringWithoutValue()
{
$value = $this->argument->getUnescapedValue();
if(is_array($value))
{
$q = '';
foreach($value as $v)
{
$q .= '?,';
}
if($q !== '')
{
$q = substr($q, 0, -1);
}
$q = '(' . $q . ')';
}
else
{
// Prepared statements: column names should not be sent as query arguments, but instead concatenated to query string
if($this->argument->isColumnName())
{
$q = $value;
}
else
{
$q = '?';
}
}
return strtoupper($this->pipe) . ' ' . $this->getConditionPart($q);
}
/**
* @return boolean
*/
function show()
{
if(!isset($this->_show))
{
if(!$this->argument->isValid())
{
$this->_show = false;
}
if($this->_value === '\'\'')
{
$this->_show = false;
}
if(!isset($this->_show))
{
return parent::show();
}
}
return $this->_show;
}
}
/* End of file ConditionWithArgument.class.php */
/* Location: ./classes/db/queryparts/condition/ConditionWithArgument.class.php */

View file

@ -1,40 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/condition
* @version 0.1
*/
class ConditionWithoutArgument extends Condition
{
/**
* constructor
* @param string $column_name
* @param mixed $argument
* @param string $operation
* @param string $pipe
* @return void
*/
function __construct($column_name, $argument, $operation, $pipe = "")
{
parent::__construct($column_name, $argument, $operation, $pipe);
$tmpArray = array('in' => 1, 'notin' => 1, 'not_in' => 1);
if(isset($tmpArray[$operation]))
{
if(is_array($argument))
{
$argument = implode($argument, ',');
}
$this->_value = '(' . $argument . ')';
}
else
{
$this->_value = $argument;
}
}
}
/* End of file ConditionWithoutArgument.class.php */
/* Location: ./classes/db/queryparts/condition/ConditionWithoutArgument.class.php */

View file

@ -1,62 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* ClickCountExpression
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class ClickCountExpression extends SelectExpression
{
/**
* click count
* @var bool
*/
var $click_count;
/**
* constructor
* @param string $column_name
* @param string $alias
* @param bool $click_count
* @return void
*/
function __construct($column_name, $alias = NULL, $click_count = false)
{
parent::__construct($column_name, $alias);
if(!is_bool($click_count))
{
// error_log("Click_count value for $column_name was not boolean", 0);
$this->click_count = false;
}
$this->click_count = $click_count;
}
function show()
{
return $this->click_count;
}
/**
* Return column expression, ex) column = column + 1
* @return string
*/
function getExpression()
{
$db_type = Context::getDBType();
if($db_type == 'cubrid')
{
return "INCR($this->column_name)";
}
else
{
return "$this->column_name";
}
}
}
/* End of file ClickCountExpression.class.php */
/* Location: ./classes/db/queryparts/expression/ClickCountExpression.class.php */

View file

@ -1,63 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* DeleteExpression
*
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
* @todo Fix this class
*/
class DeleteExpression extends Expression
{
/**
* column value
* @var mixed
*/
var $value;
/**
* constructor
* @param string $column_name
* @param mixed $value
* @return void
*/
function __construct($column_name, $value)
{
parent::__construct($column_name);
$this->value = $value;
}
/**
* Return column expression, ex) column = value
* @return string
*/
function getExpression()
{
return "$this->column_name = $this->value";
}
function getValue()
{
// TODO Escape value according to column type instead of variable type
if(!is_numeric($this->value))
{
return "'" . $this->value . "'";
}
return $this->value;
}
function show()
{
if(!$this->value)
{
return false;
}
return true;
}
}
/* End of file DeleteExpression.class.php */
/* Location: ./classes/db/queryparts/expression/DeleteExpression.class.php */

View file

@ -1,56 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Expression
* Represents an expression used in select/update/insert/delete statements
*
* Examples (expressions are inside double square brackets):
* select [[columnA]], [[columnB as aliasB]] from tableA
* update tableA set [[columnA = valueA]] where columnB = something
*
* @author Corina
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class Expression
{
/**
* column name
* @var string
*/
var $column_name;
/**
* constructor
* @param string $column_name
* @return void
*/
function __construct($column_name)
{
$this->column_name = $column_name;
}
function getColumnName()
{
return $this->column_name;
}
function show()
{
return false;
}
/**
* Return column expression, ex) column as alias
* @return string
*/
function getExpression()
{
}
}
/* End of file Expression.class.php */
/* Location: ./classes/db/queryparts/expression/Expression.class.php */

View file

@ -1,74 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* InsertExpression
*
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class InsertExpression extends Expression
{
/**
* argument
* @var object
*/
var $argument;
/**
* constructor
* @param string $column_name
* @param object $argument
* @return void
*/
function __construct($column_name, $argument)
{
parent::__construct($column_name);
$this->argument = $argument;
}
function getValue($with_values = true)
{
if($with_values)
{
return $this->argument->getValue();
}
return '?';
}
function show()
{
if(!$this->argument)
{
return false;
}
$value = $this->argument->getValue();
if(!isset($value))
{
return false;
}
return true;
}
function getArgument()
{
return $this->argument;
}
function getArguments()
{
if($this->argument)
{
return array($this->argument);
}
else
{
return array();
}
}
}
/* End of file InsertExpression.class.php */
/* Location: ./classes/db/queryparts/expression/InsertExpression.class.php */

View file

@ -1,70 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* SelectExpression
* Represents an expresion that appears in the select clause
*
* $column_name can be:
* - a table column name
* - an sql function - like count(*)
* - an sql expression - substr(column_name, 1, 8) or score1 + score2
* $column_name is already escaped
*
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class SelectExpression extends Expression
{
/**
* column alias name
* @var string
*/
var $column_alias;
/**
* constructor
* @param string $column_name
* @param string $alias
* @return void
*/
function __construct($column_name, $alias = NULL)
{
parent::__construct($column_name);
$this->column_alias = $alias;
}
/**
* Return column expression, ex) column as alias
* @return string
*/
function getExpression()
{
return sprintf("%s%s", $this->column_name, $this->column_alias ? (' AS ' . $this->column_alias) : "");
}
function show()
{
return true;
}
function getArgument()
{
return null;
}
function getArguments()
{
return array();
}
function isSubquery()
{
return false;
}
}
/* End of file SelectExpression.class.php */
/* Location: ./classes/db/queryparts/expression/SelectExpression.class.php */

View file

@ -1,37 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* StarExpression
* Represents the * in 'select * from ...' statements
*
* @author Corina
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class StarExpression extends SelectExpression
{
/**
* constructor, set the column to asterisk
* @return void
*/
function __construct()
{
parent::__construct("*");
}
function getArgument()
{
return null;
}
function getArguments()
{
// StarExpression has no arguments
return array();
}
}
/* End of file StarExpression.class.php */
/* Location: ./classes/db/queryparts/expression/StarExpression.class.php */

View file

@ -1,119 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* UpdateExpression
*
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class UpdateExpression extends Expression
{
/**
* argument
* @var object
*/
var $argument;
/**
* constructor
* @param string $column_name
* @param object $argument
* @return void
*/
function __construct($column_name, $argument)
{
parent::__construct($column_name);
$this->argument = $argument;
}
/**
* Return column expression, ex) column = value
* @return string
*/
function getExpression($with_value = true)
{
if($with_value)
{
return $this->getExpressionWithValue();
}
return $this->getExpressionWithoutValue();
}
/**
* Return column expression, ex) column = value
* @return string
*/
function getExpressionWithValue()
{
$value = $this->argument->getValue();
$operation = $this->argument->getColumnOperation();
if(isset($operation))
{
return "$this->column_name = $this->column_name $operation $value";
}
return "$this->column_name = $value";
}
/**
* Return column expression, ex) column = ?
* Can use prepare statement
* @return string
*/
function getExpressionWithoutValue()
{
$operation = $this->argument->getColumnOperation();
if(isset($operation))
{
return "$this->column_name = $this->column_name $operation ?";
}
return "$this->column_name = ?";
}
function getValue()
{
// TODO Escape value according to column type instead of variable type
$value = $this->argument->getValue();
if(!is_numeric($value))
{
return "'" . $value . "'";
}
return $value;
}
function show()
{
if(!$this->argument)
{
return false;
}
$value = $this->argument->getValue();
if(!isset($value))
{
return false;
}
return true;
}
function getArgument()
{
return $this->argument;
}
function getArguments()
{
if($this->argument)
{
return array($this->argument);
}
else
{
return array();
}
}
}
/* End of file UpdateExpression.class.php */
/* Location: ./classes/db/queryparts/expression/UpdateExpression.class.php */

View file

@ -1,74 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* UpdateExpression
*
* @author Arnia Software
* @package /classes/db/queryparts/expression
* @version 0.1
*/
class UpdateExpressionWithoutArgument extends UpdateExpression
{
/**
* argument
* @var object
*/
var $argument;
/**
* constructor
* @param string $column_name
* @param object $argument
* @return void
*/
function __construct($column_name, $argument)
{
parent::__construct($column_name, $argument);
$this->argument = $argument;
}
function getExpression($with_value = true)
{
return "$this->column_name = $this->argument";
}
function getValue()
{
// TODO Escape value according to column type instead of variable type
$value = $this->argument;
if(!is_numeric($value))
{
return "'" . $value . "'";
}
return $value;
}
function show()
{
if(!$this->argument)
{
return false;
}
$value = $this->argument;
if(!isset($value))
{
return false;
}
return true;
}
function getArgument()
{
return null;
}
function getArguments()
{
return array();
}
}
/* End of file UpdateExpressionWithoutArgument.class.php */
/* Location: ./classes/db/queryparts/expression/UpdateExpressionWithoutArgument.class.php */

View file

@ -1,101 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/limit
* @version 0.1
*/
class Limit
{
/**
* start number
* @var int
*/
var $start;
/**
* list count
* @var int
*/
var $list_count;
/**
* page count
* @var int
*/
var $page_count;
/**
* current page
* @var int
*/
var $page;
/**
* constructor
* @param int $list_count
* @param int $page
* @param int $page_count
* @param int $offset
* @return void
*/
function __construct($list_count, $page = NULL, $page_count = NULL, $offset = NULL)
{
$this->list_count = $list_count;
if($list_count->getValue())
{
if($page && $page->getValue())
{
$this->start = ($page->getValue() - 1) * $list_count->getValue();
$this->page_count = $page_count;
$this->page = $page;
}
elseif($offset)
{
$this->start = $offset->getValue();
}
}
}
/**
* In case you choose to use query limit in other cases than page select
* @return boolean
*/
function isPageHandler()
{
if($this->page)
{
return true;
}
else
{
return false;
}
}
function getOffset()
{
return $this->start;
}
function getLimit()
{
return $this->list_count->getValue();
}
function toString()
{
if($this->start)
{
return $this->start . ' , ' . $this->list_count->getValue();
}
else
{
return $this->list_count->getValue() ?: '';
}
}
}
/* End of file Limit.class.php */
/* Location: ./classes/db/limit/Limit.class.php */

View file

@ -1,74 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/order
* @version 0.1
*/
class OrderByColumn
{
/**
* column name
* @var string
*/
var $column_name;
/**
* sort order
* @var string
*/
var $sort_order;
/**
* constructor
* @param string $column_name
* @param string $sort_order
* @return void
*/
function __construct($column_name, $sort_order)
{
$this->column_name = $column_name;
$this->sort_order = $sort_order;
}
function toString()
{
$result = $this->getColumnName();
$result .= ' ';
$result .= is_a($this->sort_order, 'Argument') ? $this->sort_order->getValue() : strtoupper($this->sort_order);
return $result;
}
function getColumnName()
{
return is_a($this->column_name, 'Argument') ? $this->column_name->getValue() : $this->column_name;
}
function getPureColumnName()
{
return is_a($this->column_name, 'Argument') ? $this->column_name->getPureValue() : $this->column_name;
}
function getPureSortOrder()
{
return is_a($this->sort_order, 'Argument') ? $this->sort_order->getPureValue() : $this->sort_order;
}
function getArguments()
{
$args = array();
if(is_a($this->column_name, 'Argument'))
{
$args[] = $this->column_name;
}
if(is_a($this->sort_order, 'Argument'))
{
$args[] = $this->sort_order;
}
}
}
/* End of file OrderByColumn.class.php */
/* Location: ./classes/db/order/OrderByColumn.class.php */

View file

@ -1,48 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/table
* @version 0.1
*/
class IndexHint
{
/**
* index name
* @var string
*/
var $index_name;
/**
* index hint type, ex) IGNORE, FORCE, USE...
* @var string
*/
var $index_hint_type;
/**
* constructor
* @param string $index_name
* @param string $index_hint_type
* @return void
*/
function __construct($index_name, $index_hint_type)
{
$this->index_name = $index_name;
$this->index_hint_type = $index_hint_type;
}
function getIndexName()
{
return $this->index_name;
}
function getIndexHintType()
{
return $this->index_hint_type;
}
}
/* End of file IndexHint.class.php */
/* Location: ./classes/db/queryparts/table/IndexHint.class.php */

View file

@ -1,78 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* class JoinTable
* $conditions in an array of Condition objects
*
* @author Arnia Software
* @package /classes/db/queryparts/table
* @version 0.1
*/
class JoinTable extends Table
{
/**
* join type
* @var string
*/
var $join_type;
/**
* condition list
* @var array
*/
var $conditions;
/**
* constructor
* @param string $name
* @param string $alias
* @param string $join_type
* @param array $conditions
* @return void
*/
function __construct($name, $alias, $join_type, $conditions)
{
parent::__construct($name, $alias);
$this->join_type = $join_type;
$this->conditions = $conditions;
}
function toString($with_value = true)
{
$part = strtoupper($this->join_type) . ' ' . $this->name;
$part .= $this->alias ? (' AS ' . $this->alias) : '';
$part .= ' ON ';
$condition_count = 0;
foreach($this->conditions as $conditionGroup)
{
if($condition_count === 0)
{
$conditionGroup->setPipe("");
}
$part .= $conditionGroup->toString($with_value);
$condition_count++;
}
return $part;
}
function isJoinTable()
{
return true;
}
function getArguments()
{
$args = array();
foreach($this->conditions as $conditionGroup)
{
$args = array_merge($args, $conditionGroup->getArguments());
}
return $args;
}
}
/* End of file JoinTable.class.php */
/* Location: ./classes/db/queryparts/table/JoinTable.class.php */

View file

@ -1,83 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/table
* @version 0.1
*/
class MysqlTableWithHint extends Table
{
/**
* table name
* @var string
*/
var $name;
/**
* table alias
* @var string
*/
var $alias;
/**
* index hint type, ex) IGNORE, FORCE, USE...
* @var array
*/
var $index_hints_list;
/**
* constructor
* @param string $name
* @param string $alias
* @param string $index_hints_list
* @return void
*/
function __construct($name, $alias = NULL, $index_hints_list)
{
parent::__construct($name, $alias);
$this->index_hints_list = $index_hints_list;
}
function toString()
{
$result = parent::toString();
$use_index_hint = '';
$force_index_hint = '';
$ignore_index_hint = '';
foreach($this->index_hints_list as $index_hint)
{
$index_hint_type = $index_hint->getIndexHintType();
if($index_hint_type == 'USE')
{
$use_index_hint .= $index_hint->getIndexName() . ', ';
}
else if($index_hint_type == 'FORCE')
{
$force_index_hint .= $index_hint->getIndexName() . ', ';
}
else if($index_hint_type == 'IGNORE')
{
$ignore_index_hint .= $index_hint->getIndexName() . ', ';
}
}
if($use_index_hint != '')
{
$result .= ' USE INDEX (' . substr($use_index_hint, 0, -2) . ') ';
}
if($force_index_hint != '')
{
$result .= ' FORCE INDEX (' . substr($force_index_hint, 0, -2) . ') ';
}
if($ignore_index_hint != '')
{
$result .= ' IGNORE INDEX (' . substr($ignore_index_hint, 0, -2) . ') ';
}
return $result;
}
}
/* End of file MysqlTableWithHint.class.php */
/* Location: ./classes/db/queryparts/table/MysqlTableWithHint.class.php */

View file

@ -1,59 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* @author NAVER (developers@xpressengine.com)
* @package /classes/db/queryparts/table
* @version 0.1
*/
class Table
{
/**
* table name
* @var string
*/
var $name;
/**
* table alias
* @var string
*/
var $alias;
/**
* constructor
* @param string $name
* @param string $alias
* @return void
*/
function __construct($name, $alias = NULL)
{
$this->name = $name;
$this->alias = $alias;
}
function toString()
{
//return $this->name;
return sprintf("%s%s", $this->name, $this->alias ? (' AS ' . $this->alias) : '');
}
function getName()
{
return $this->name;
}
function getAlias()
{
return $this->alias;
}
function isJoinTable()
{
return false;
}
}
/* End of file Table.class.php */
/* Location: ./classes/db/queryparts/table/Table.class.php */

View file

@ -1,114 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* File containing the XE 1.5 XmlQueryParserClass
*/
if(!defined('__XE_LOADED_XML_CLASS__'))
{
define('__XE_LOADED_XML_CLASS__', 1);
}
/**
* New XmlQueryParser class <br />
* Parses XE XML query files
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml
* @version 0.1
*/
class XmlQueryParser extends XmlParser
{
/**
* constructor
* @return void
*/
function __construct()
{
}
/**
* Create XmlQueryParser instance for Singleton
*
* @return XmlQueryParser object
*/
function &getInstance()
{
static $theInstance = NULL;
if(!isset($theInstance))
{
$theInstance = new XmlQueryParser();
}
return $theInstance;
}
/**
* Parses an XML query file
*
* 1. Read xml file<br />
* 2. Check the action<br />
* 3. Parse and write cache file <br />
*
* @param $query_id
* @param $xml_file
* @param $cache_file
*
* @return QueryParser object
*/
function &parse_xml_query($query_id, $xml_file, $cache_file)
{
// Read xml file
$xml_obj = $this->getXmlFileContent($xml_file);
// insert, update, delete, select action
$action = strtolower($xml_obj->query->attrs->action);
if(!$action)
{
return;
}
// Write query cache file
$parser = new QueryParser($xml_obj->query);
FileHandler::writeFile($cache_file, $parser->toString());
return $parser;
}
/**
* Override for parent "parse" method
*
* @param null $query_id
* @param null $xml_file
* @param null $cache_file
*
* @return void
*/
function parse($query_id = NULL, $xml_file = NULL, $cache_file = NULL)
{
$this->parse_xml_query($query_id, $xml_file, $cache_file);
}
/**
* Returns XML file contents as an object
* or NULL in case of error
*
* @param $xml_file
* @return array|NULL
*/
function getXmlFileContent($xml_file)
{
$buff = FileHandler::readFile($xml_file);
$xml_obj = parent::parse($buff);
if(!$xml_obj)
{
return;
}
unset($buff);
return $xml_obj;
}
}
/* End of file XmlQueryParser.class.php */
/* Location: ./classes/xml/XmlQueryParser.class.php */

View file

@ -1,333 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* File containing the DBParser class
*/
/**
* Escapes query statements: <br />
* - column names: member.member_srl =&gt; "member"."member_srl" <br />
* - expressions: SUM(member.member_srl) =&gt; SUM("member"."member_srl") <br />
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery
* @version 0.1
*/
class DBParser
{
/**
* Character for escape target value on the left
*
* For example, in CUBRID left and right escape
* chars are the same, the double quote - " <br />
* But for SQL Server, the escape is made with
* [double brackets], so the left and right char differ
*
*
* @var string
*/
var $escape_char_left;
/**
* Character for escape target value on the right
*
* For example, in CUBRID left and right escape
* chars are the same, the double quote - " <br />
* But for SQL Server, the escape is made with
* [double brackets], so the left and right char differ
*
* @var string
*/
var $escape_char_right;
/**
* Table prefix string
*
* Default is "xe_"
*
* @var string
*/
var $table_prefix;
/**
* Constructor
*
* @param string $escape_char_left
* @param string $escape_char_right
* @param string $table_prefix
*
* @return void
*/
function __construct($escape_char_left, $escape_char_right = "", $table_prefix = "xe_")
{
$this->escape_char_left = $escape_char_left;
if($escape_char_right !== "")
{
$this->escape_char_right = $escape_char_right;
}
else
{
$this->escape_char_right = $escape_char_left;
}
$this->table_prefix = $table_prefix;
}
/**
* Get escape character
*
* @param string $leftOrRight left or right
* @return string
*/
function getEscapeChar($leftOrRight)
{
if($leftOrRight === 'left')
{
return $this->escape_char_left;
}
else
{
return $this->escape_char_right;
}
}
/**
* Escape the value
*
* @param mixed $name
* @return string
*/
function escape($name)
{
return $this->escape_char_left . $name . $this->escape_char_right;
}
/**
* Escape the string value
*
* @param string $name
* @return string
*/
function escapeString($name)
{
return "'" . $this->escapeStringValue($name) . "'";
}
/**
* Escape the string value
*
* @param string $value
* @return string
*/
function escapeStringValue($value)
{
if($value == "*")
{
return $value;
}
if(is_string($value))
{
return $value = str_replace("'", "''", $value);
}
return $value;
}
/**
* Return table full name
*
* @param string $name table name without table prefix
*
* @return string table full name with table prefix
*/
function parseTableName($name)
{
return $this->table_prefix . $name;
}
/**
* Return column name after escape
*
* @param string $name column name before escape
*
* @return string column name after escape
*/
function parseColumnName($name)
{
return $this->escapeColumn($name);
}
/**
* Escape column name
*
* @param string $column_name
* @return string column name with db name
*/
function escapeColumn($column_name)
{
if($this->isUnqualifiedColumnName($column_name))
{
return $this->escape($column_name);
}
if($this->isQualifiedColumnName($column_name))
{
list($table, $column) = explode('.', $column_name);
// $table can also be an alias, so the prefix should not be added
return $this->escape($table) . '.' . $this->escape($column);
//return $this->escape($this->parseTableName($table)).'.'.$this->escape($column);
}
}
/**
* Checks to see if a given column name is unqualified
*
* Ex: "member_srl" -> unqualified <br />
* "member"."member_srl" -> qualified
*
* @param string $column_name
* @return bool
*/
function isUnqualifiedColumnName($column_name)
{
if(strpos($column_name, '.') === FALSE && strpos($column_name, '(') === FALSE)
{
return TRUE;
}
return FALSE;
}
/**
* Checks to see if a given column name is qualified
*
* Ex: "member_srl" -> unqualified <br />
* "member"."member_srl" -> qualified
*
* @param string $column_name
* @return bool
*/
function isQualifiedColumnName($column_name)
{
if(strpos($column_name, '.') !== FALSE && strpos($column_name, '(') === FALSE)
{
return TRUE;
}
return FALSE;
}
/**
* Escapes a query expression
*
* An expression can be: <br />
* <ul>
* <li> a column name: "member_srl" or "xe_member"."member_srl"
* <li> an expression:
* <ul>
* <li> LEFT(UPPER("content")) <br />
* <li> readed_count + voted_count <br />
* <li> CAST(regdate as DATE) </li>
* </ul>
* </li>
* </ul>
*
* @param $column_name
* @return string
*/
function parseExpression($column_name)
{
$functions = preg_split('/([\+\-\*\/\ ])/', $column_name, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($functions as $k => $v)
{
$function = &$functions[$k];
if(strlen($function) == 1)
{
continue; // skip delimiters
}
$pos = strrpos("(", $function);
$matches = preg_split('/([a-zA-Z0-9_*]+)/', $function, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$total_brackets = substr_count($function, "(");
$brackets = 0;
foreach($matches as $i => $j)
{
$match = &$matches[$i];
if($match == '(')
{
$brackets++;
continue;
}
if(strpos($match, ')') !== FALSE)
{
continue;
}
if(in_array($match, array(',', '.')))
{
continue;
}
if($brackets == $total_brackets)
{
if(!is_numeric($match) && !in_array(strtoupper($match), array('UNSIGNED', 'INTEGER', 'AS')) && !preg_match('/^[A-Z]+$/', $match))
{
$match = $this->escapeColumnExpression($match);
}
}
}
$function = implode('', $matches);
}
return implode('', $functions);
}
/**
* Checks if a given argument is an asterisk
*
* @param string $column_name
* @return bool
*/
function isStar($column_name)
{
if(substr($column_name, -1) == '*')
{
return TRUE;
}
return FALSE;
}
/**
* Checks to see if expression is an aggregate star function
* like count(*)
*
* @param string $column_name
* @return bool
*/
function isStarFunction($column_name)
{
if(strpos($column_name, "(*)") !== FALSE)
{
return TRUE;
}
return FALSE;
}
/**
* Return column name after escape
* @param string $column_name
* @return string
*/
function escapeColumnExpression($column_name)
{
if($this->isStar($column_name))
{
return $column_name;
}
if($this->isStarFunction($column_name))
{
return $column_name;
}
if(stripos($column_name, 'distinct') !== FALSE)
{
return $column_name;
}
return $this->escapeColumn($column_name);
}
}
/* End of file DBParser.class.php */
/* Location: ./classes/xml/xmlquery/DBParser.class.php */

View file

@ -1,127 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* File containing the QueryParser class
*/
/**
* Parses an XML Object and returns a string used for generating the PHP cache file <br />
* The XML Object structure must be the one defined in the XmlParser class
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery
* @version 0.1
*/
class QueryParser
{
/**
* Property containing the associated QueryTag object
*
* @var QueryTag object
*/
var $queryTag;
/**
* Constructor
*
* @param object $query XML object obtained after reading the XML Query file
* @param bool $isSubQuery
* @return void
*/
function __construct($query = NULL, $isSubQuery = FALSE)
{
if($query)
{
$this->queryTag = new QueryTag($query, $isSubQuery);
}
}
/**
* Returns table information
*
* Used for finding column type info (string/numeric) <br />
* Obtains the table info from XE's XML schema files
*
* @param object $query_id
* @param bool $table_name
* @return array
*/
function getTableInfo($query_id, $table_name)
{
$column_type = array();
$module = '';
$id_args = explode('.', $query_id);
if(count($id_args) == 2)
{
$target = 'modules';
$module = $id_args[0];
$id = $id_args[1];
}
else if(count($id_args) == 3)
{
$target = $id_args[0];
$targetList = array('modules' => 1, 'addons' => 1, 'widgets' => 1);
if(!isset($targetList[$target]))
{
return;
}
$module = $id_args[1];
$id = $id_args[2];
}
// get column properties from the table
$table_file = sprintf('%s%s/%s/schemas/%s.xml', _XE_PATH_, 'modules', $module, $table_name);
if(!file_exists($table_file))
{
$searched_list = FileHandler::readDir(_XE_PATH_ . 'modules');
$searched_count = count($searched_list);
for($i = 0; $i < $searched_count; $i++)
{
$table_file = sprintf('%s%s/%s/schemas/%s.xml', _XE_PATH_, 'modules', $searched_list[$i], $table_name);
if(file_exists($table_file))
{
break;
}
}
}
if(file_exists($table_file))
{
$table_xml = FileHandler::readFile($table_file);
$xml_parser = new XmlParser();
$table_obj = $xml_parser->parse($table_xml);
if($table_obj->table)
{
if(isset($table_obj->table->column) && !is_array($table_obj->table->column))
{
$table_obj->table->column = array($table_obj->table->column);
}
foreach($table_obj->table->column as $k => $v)
{
$column_type[$v->attrs->name] = $v->attrs->type;
}
}
}
return $column_type;
}
/**
* Returns the contents for the query cache file
*
* @return string
*/
function toString()
{
return "<?php if(!defined('__XE__')) exit();\n"
. $this->queryTag->toString()
. 'return $query; ?>';
}
}
/* End of file QueryParser.class.php */
/* Location: ./classes/xml/xmlquery/QueryParser.class.php */

View file

@ -1,396 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Argument class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/argument
* @version 0.1
*/
class Argument
{
/**
* argument value
* @var mixed
*/
var $value;
/**
* argument name
* @var string
*/
var $name;
/**
* argument type
* @var string
*/
var $type;
/**
* result of argument type check
* @var bool
*/
var $isValid;
/**
* error message
* @var BaseObject
*/
var $errorMessage;
/**
* column operation
*/
var $column_operation;
/**
* Check if arg value is user submnitted or default
* @var mixed
*/
var $uses_default_value;
/**
* Caches escaped and toString value so that the parsing won't happen multiple times
* @var mixed
*/
var $_value; //
/**
* constructor
* @param string $name
* @param mixed $value
* @return void
*/
function __construct($name, $value)
{
$this->value = $value;
$this->name = $name;
$this->isValid = TRUE;
}
function getType()
{
if(isset($this->type))
{
return $this->type;
}
if(is_string($this->value))
{
return 'column_name';
}
return 'number';
}
function setColumnType($value)
{
$this->type = $value;
}
function setColumnOperation($operation)
{
$this->column_operation = $operation;
}
function getName()
{
return $this->name;
}
function getValue()
{
if(!isset($this->_value))
{
$value = $this->getEscapedValue();
$this->_value = $this->toString($value);
}
return $this->_value;
}
function getPureValue()
{
return $this->value;
}
function getColumnOperation()
{
return $this->column_operation;
}
function getEscapedValue()
{
return $this->escapeValue($this->value);
}
function getUnescapedValue()
{
if($this->value === 'null')
{
return null;
}
return $this->value;
}
/**
* mixed value to string
* @param mixed $value
* @return string
*/
function toString($value)
{
if(is_array($value))
{
if(count($value) === 0)
{
return '';
}
if(count($value) === 1 && $value[0] === '')
{
return '';
}
return '(' . implode(',', $value) . ')';
}
return $value;
}
/**
* escape value
* @param mixed $value
* @return mixed
*/
function escapeValue($value)
{
$column_type = $this->getType();
if($column_type == 'column_name')
{
$dbParser = DB::getParser();
return $dbParser->parseExpression($value);
}
if(!isset($value))
{
return null;
}
$columnTypeList = array('date' => 1, 'varchar' => 1, 'char' => 1, 'text' => 1, 'bigtext' => 1);
if(isset($columnTypeList[$column_type]))
{
if(!is_array($value))
{
$value = $this->_escapeStringValue($value);
}
else
{
foreach($value as $key=>$val)
{
$value[$key] = $this->_escapeStringValue($val);
}
}
}
if($this->uses_default_value)
{
return $value;
}
if($column_type == 'number')
{
if(is_array($value))
{
foreach($value AS $key => $val)
{
if(isset($val) && $val !== '')
{
$value[$key] = (int) $val;
}
}
}
else
{
$value = (int) $value;
}
}
return $value;
}
/**
* escape string value
* @param string $value
* @return string
*/
function _escapeStringValue($value)
{
// Remove non-utf8 chars.
$regex = '@((?:[\x00-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}){1,100})|([\xF0-\xF7][\x80-\xBF]{3})|([\x80-\xBF])|([\xC0-\xFF])@x';
$value = preg_replace_callback($regex, array($this, 'utf8Replacer'), $value);
$db = DB::getInstance();
$value = $db->addQuotes($value);
return '\'' . $value . '\'';
}
function utf8Replacer($captures)
{
if(strlen($captures[1]))
{
// Valid byte sequence. Return unmodified.
return $captures[1];
}
else if(strlen($captures[2]))
{
// Remove user defined area
if("\xF3\xB0\x80\x80" <= $captures[2])
{
return;
}
return $captures[2];
}
else
{
return;
}
}
function isValid()
{
return $this->isValid;
}
function isColumnName()
{
$type = $this->getType();
$value = $this->getUnescapedValue();
if($type == 'column_name')
{
return TRUE;
}
if($type == 'number' && is_null($value))
{
return FALSE;
}
if($type == 'number' && !is_numeric($value) && $this->uses_default_value)
{
return TRUE;
}
return FALSE;
}
function getErrorMessage()
{
return $this->errorMessage;
}
function ensureDefaultValue($default_value)
{
if($this->value === NULL || $this->value === '')
{
$this->value = $default_value;
$this->uses_default_value = TRUE;
}
}
/**
* check filter by filter type
* @param string $filter_type
* @return void
*/
function checkFilter($filter_type)
{
if(isset($this->value) && $this->value != '')
{
global $lang;
$val = $this->value;
$key = $this->name;
switch($filter_type)
{
case 'email' :
case 'email_address' :
if(!preg_match('/^[\w-]+((?:\.|\+|\~)[\w-]+)*@[\w-]+(\.[\w-]+)+$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_email, $lang->{$key} ? $lang->{$key} : $key));
}
break;
case 'homepage' :
if(!preg_match('/^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_homepage, $lang->{$key} ? $lang->{$key} : $key));
}
break;
case 'userid' :
case 'user_id' :
if(!preg_match('/^[a-zA-Z]+([_0-9a-zA-Z]+)*$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_userid, $lang->{$key} ? $lang->{$key} : $key));
}
break;
case 'number' :
case 'numbers' :
if(is_array($val))
{
$val = join(',', $val);
}
if(!preg_match('/^(-?)[0-9]+(,\-?[0-9]+)*$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_number, $lang->{$key} ? $lang->{$key} : $key));
}
break;
case 'alpha' :
if(!preg_match('/^[a-z]+$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_alpha, $lang->{$key} ? $lang->{$key} : $key));
}
break;
case 'alpha_number' :
if(!preg_match('/^[0-9a-z]+$/is', $val))
{
$this->isValid = FALSE;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->invalid_alpha_number, $lang->{$key} ? $lang->{$key} : $key));
}
break;
}
}
}
function checkMaxLength($length)
{
if($this->value && (strlen($this->value) > $length))
{
global $lang;
$this->isValid = FALSE;
$key = $this->name;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->outofrange, $lang->{$key} ? $lang->{$key} : $key));
}
}
function checkMinLength($length)
{
if($this->value && (strlen($this->value) < $length))
{
global $lang;
$this->isValid = FALSE;
$key = $this->name;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->outofrange, $lang->{$key} ? $lang->{$key} : $key));
}
}
function checkNotNull()
{
if(!isset($this->value))
{
global $lang;
$this->isValid = FALSE;
$key = $this->name;
$this->errorMessage = new BaseObject(-1, sprintf($lang->filter->isnull, $lang->{$key} ? $lang->{$key} : $key));
}
}
}
/* End of file Argument.class.php */
/* Location: ./classes/xml/xmlquery/argument/Argument.class.php */

View file

@ -1,153 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* ConditionArgument class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/argument
* @version 0.1
*/
class ConditionArgument extends Argument
{
/**
* Operator keyword. for example 'in', 'notint', 'between'
* @var string
*/
var $operation;
/**
* constructor
* @param string $name
* @param mixed $value
* @param string $operation
* @return void
*/
function __construct($name, $value, $operation)
{
$operationList = array('in' => 1, 'notin' => 1, 'not_in' => 1, 'between' => 1);
if(isset($value) && isset($operationList[$operation]) && !is_array($value) && $value != '')
{
$value = str_replace(' ', '', $value);
$value = str_replace('\'', '', $value);
$value = explode(',', $value);
}
parent::__construct($name, $value);
$this->operation = $operation;
}
/**
* create condition value. set $this->value
* @return void
*/
function createConditionValue()
{
if(!isset($this->value))
{
return;
}
$operation = $this->operation;
$value = $this->value;
switch($operation)
{
case 'like_prefix' :
if(defined('__CUBRID_VERSION__') && __CUBRID_VERSION__ >= '8.4.1')
{
$this->value = '^' . str_replace('%', '(.*)', preg_quote($value));
}
else
{
$this->value = $value . '%';
}
break;
case 'like_tail' :
if(defined('__CUBRID_VERSION__') && __CUBRID_VERSION__ >= '8.4.1')
{
$this->value = str_replace('%', '(.*)', preg_quote($value)) . '$';
}
else
{
$this->value = '%' . $value;
}
break;
case 'like' :
if(defined('__CUBRID_VERSION__') && __CUBRID_VERSION__ >= '8.4.1')
{
$this->value = str_replace('%', '(.*)', preg_quote($value));
}
else
{
$this->value = '%' . $value . '%';
}
break;
case 'notlike' :
$this->value = '%' . $value . '%';
break;
case 'notlike_prefix' :
$this->value = $value . '%';
break;
case 'notlike_tail' :
$this->value = '%' . $value;
break;
case 'in':
if(!is_array($value))
{
$this->value = array($value);
}
break;
case 'notin':
case 'not_in':
if(!is_array($value))
{
$this->value = array($value);
}
break;
}
}
/**
* Since ConditionArgument is used in WHERE clause,
* where the argument value is compared to a table column,
* it is assumed that all arguments have type. There are cases though
* where the column does not have any type - if it was removed from
* the XML schema for example - see the is_secret column in xe_documents table.
* In this case, the column type is retrieved according to argument
* value type (using the PHP function is_numeric).
*
* @return type string
*/
function getType()
{
if($this->type)
{
return $this->type;
}
else if(!is_numeric($this->value))
{
return 'varchar';
}
else
{
return '';
}
}
function setColumnType($column_type)
{
if(!isset($this->value))
{
return;
}
if($column_type === '')
{
return;
}
$this->type = $column_type;
}
}
/* End of file ConditionArgument.class.php */
/* Location: ./classes/xml/xmlquery/argument/ConditionArgument.class.php */

View file

@ -1,20 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* SortArgument class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/argument
* @version 0.1
*/
class SortArgument extends Argument
{
function getValue()
{
return $this->getUnescapedValue();
}
}
/* End of file SortArgument.class.php */
/* Location: ./classes/xml/xmlquery/argument/SortArgument.class.php */

View file

@ -1,177 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* DefaultValue class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/queryargument
* @version 0.1
*/
class DefaultValue
{
/**
* Column name
* @var string
*/
var $column_name;
/**
* Value
* @var mixed
*/
var $value;
/**
* sequnence status
* @var bool
*/
var $is_sequence = FALSE;
/**
* operation status
* @var bool
*/
var $is_operation = FALSE;
/**
* operation
* @var string
*/
var $operation = '';
/**
* Checks if value is plain string or name of XE function (ipaddress, plus, etc).
* @var bool
*/
var $_is_string = FALSE;
/**
* Checks if value is string resulted from evaluating a piece of PHP code (see $_SERVER[REMOTE_ADDR])
* @var bool
*/
var $_is_string_from_function = FALSE;
/**
* constructor
* @param string $column_name column name
* @param mixed $value value
* @return void
*/
function __construct($column_name, $value)
{
$dbParser = DB::getParser();
$this->column_name = $dbParser->parseColumnName($column_name);
$this->value = $value;
$this->value = $this->_setValue();
}
function isString()
{
return $this->_is_string;
$str_pos = strpos($this->value, '(');
if($str_pos === false)
{
return TRUE;
}
return FALSE;
}
function isStringFromFunction()
{
return $this->_is_string_from_function;
}
function isSequence()
{
return $this->is_sequence;
}
function isOperation()
{
return $this->is_operation;
}
function getOperation()
{
return $this->operation;
}
function _setValue()
{
if(!isset($this->value))
{
return;
}
// If value contains comma separated values and does not contain paranthesis
// -> default value is an array
if(strpos($this->value, ',') !== FALSE && strpos($this->value, '(') === FALSE)
{
return sprintf('array(%s)', $this->value);
}
$str_pos = strpos($this->value, '(');
// // TODO Replace this with parseExpression
if($str_pos === FALSE)
{
$this->_is_string = TRUE;
return '\'' . $this->value . '\'';
}
//if($str_pos===false) return $this->value;
$func_name = substr($this->value, 0, $str_pos);
$args = substr($this->value, $str_pos + 1, -1);
switch($func_name)
{
case 'ipaddress' :
$val = '\\RX_CLIENT_IP';
$this->_is_string_from_function = TRUE;
break;
case 'unixtime' :
$val = '\\RX_TIME';
$this->_is_string_from_function = TRUE;
break;
case 'curdate' :
$val = 'getInternalDateTime()';
$this->_is_string_from_function = TRUE;
break;
case 'sequence' :
$this->is_sequence = TRUE;
$val = '$sequence';
break;
case 'plus' :
$args = abs($args);
$this->is_operation = TRUE;
$this->operation = '+';
$val = sprintf('%d', $args);
break;
case 'minus' :
$args = abs($args);
$this->is_operation = TRUE;
$this->operation = '-';
$val = sprintf('%d', $args);
break;
case 'multiply' :
$args = intval($args);
$this->is_operation = TRUE;
$this->operation = '*';
$val = sprintf('%d', $args);
break;
default :
$val = '\'' . $this->value . '\'';
//$val = $this->value;
}
return $val;
}
function toString()
{
return $this->value;
}
}
/* End of file DefaultValue.class.php */
/* Location: ./classes/xml/xmlquery/queryargument/DefaultValue.class.php */

View file

@ -1,191 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* QueryArgument class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/queryargument
* @version 0.1
*/
class QueryArgument
{
/**
* Argument name
* @var string
*/
var $argument_name;
/**
* Variable name
* @var string
*/
var $variable_name;
/**
* Argument validator
* @var QueryArgumentValidator
*/
var $argument_validator;
/**
* Column name
* @var string
*/
var $column_name;
/**
* Table name
* @var string
*/
var $table_name;
/**
* Operation
* @var string
*/
var $operation;
/**
* Ignore value
* @var bool
*/
var $ignore_value;
/**
* constructor
* @param object $tag tag object
* @param bool $ignore_value
* @return void
*/
function __construct($tag, $ignore_value = FALSE)
{
static $number_of_arguments = 0;
$this->argument_name = $tag->attrs->var;
if(!$this->argument_name)
{
$this->argument_name = str_replace('.', '_', $tag->attrs->name);
}
if(!$this->argument_name)
{
$this->argument_name = str_replace('.', '_', $tag->attrs->column);
}
$this->variable_name = $this->argument_name;
$number_of_arguments++;
$this->argument_name .= $number_of_arguments;
$name = $tag->attrs->name;
if(!$name)
{
$name = $tag->attrs->column;
}
if(strpos($name, '.') === FALSE)
{
$this->column_name = $name;
}
else
{
list($prefix, $name) = explode('.', $name);
$this->column_name = $name;
$this->table_name = $prefix;
}
if($tag->attrs->operation)
{
$this->operation = $tag->attrs->operation;
}
$this->argument_validator = new QueryArgumentValidator($tag, $this);
$this->ignore_value = $ignore_value;
}
function getArgumentName()
{
return $this->argument_name;
}
function getColumnName()
{
return $this->column_name;
}
function getTableName()
{
return $this->table_name;
}
function getValidatorString()
{
return $this->argument_validator->toString();
}
function isConditionArgument()
{
if($this->operation)
{
return TRUE;
}
return FALSE;
}
/**
* Change QueryArgument object to string
* @return string
*/
function toString()
{
if($this->isConditionArgument())
{
// Instantiation
$arg = sprintf("\n" . '${\'%s_argument\'} = new ConditionArgument(\'%s\', %s, \'%s\');' . "\n"
, $this->argument_name
, $this->variable_name
, '$args->' . $this->variable_name
, $this->operation
);
// Call methods to validate argument and ensure default value
$arg .= $this->argument_validator->toString();
// Prepare condition string
$arg .= sprintf('${\'%s_argument\'}->createConditionValue();' . "\n"
, $this->argument_name
);
// Check that argument passed validation, else return
$arg .= sprintf('if(!${\'%s_argument\'}->isValid()) return ${\'%s_argument\'}->getErrorMessage();' . "\n"
, $this->argument_name
, $this->argument_name
);
}
else
{
$arg = sprintf("\n" . '${\'%s_argument\'} = new Argument(\'%s\', %s);' . "\n"
, $this->argument_name
, $this->variable_name
, $this->ignore_value ? 'NULL' : '$args->{\'' . $this->variable_name . '\'}');
$arg .= $this->argument_validator->toString();
$arg .= sprintf('if(!${\'%s_argument\'}->isValid()) return ${\'%s_argument\'}->getErrorMessage();' . "\n"
, $this->argument_name
, $this->argument_name
);
}
// If the argument is null, skip it
if($this->argument_validator->isIgnorable())
{
$arg = sprintf("if(isset(%s)) {", '$args->' . $this->variable_name)
. $arg
. sprintf("} else\n" . '${\'%s_argument\'} = NULL;', $this->argument_name);
}
return $arg;
}
}
/* End of file QueryArgument.class.php */
/* Location: ./classes/xml/xmlquery/queryargument/QueryArgument.class.php */

View file

@ -1,34 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* SortQueryArgument class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/queryargument
* @version 0.1
*/
class SortQueryArgument extends QueryArgument
{
/**
* Change SortQueryArgument object to string
* @return string
*/
function toString()
{
$arg = sprintf("\n" . '${\'%s_argument\'} = new SortArgument(\'%s\', %s);' . "\n"
, $this->argument_name
, $this->argument_name
, '$args->' . $this->variable_name);
$arg .= $this->argument_validator->toString();
$arg .= sprintf('if(!${\'%s_argument\'}->isValid()) return ${\'%s_argument\'}->getErrorMessage();' . "\n"
, $this->argument_name
, $this->argument_name
);
return $arg;
}
}
/* End of file DefaultValue.class.php */
/* Location: ./classes/xml/xmlquery/queryargument/DefaultValue.class.php */

View file

@ -1,135 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* QueryArgumentValidator class
* @author NAVER (developers@xpressengine.com)
* @package /classes/xml/xmlquery/queryargument/validator
* @version 0.1
*/
class QueryArgumentValidator
{
/**
* Argument name
* @var string
*/
var $argument_name;
/**
* Default value
* @var string
*/
var $default_value;
/**
* Notnull status setting, if value should be not null, this value is 'notnull'
* @var string
*/
var $notnull;
/**
* Filter for value type, for example number
* @var string
*/
var $filter;
/**
* Minimum length for value
* @var int
*/
var $min_length;
/**
* Maximum length for value
* @var int
*/
var $max_length;
var $validator_string;
/**
* Query argument for validate
* @var QueryArgument object
*/
var $argument;
/**
* constructor
* @param Xml_Node_ $tag tag object by Query xml file parse
* @param QueryArgument $argument
* @return void
*/
function __construct($tag, $argument)
{
$this->argument = $argument;
$this->argument_name = $this->argument->getArgumentName();
$this->default_value = $tag->attrs->default;
$this->notnull = $tag->attrs->notnull;
$this->filter = $tag->attrs->filter;
$this->min_length = $tag->attrs->min_length;
$this->max_length = $tag->attrs->max_length;
}
function isIgnorable()
{
if(isset($this->default_value) || isset($this->notnull))
{
return FALSE;
}
return TRUE;
}
function toString()
{
$validator = '';
if($this->filter)
{
$validator .= sprintf('${\'%s_argument\'}->checkFilter(\'%s\');' . "\n"
, $this->argument_name
, $this->filter
);
}
if($this->min_length)
{
$validator .= sprintf('${\'%s_argument\'}->checkMinLength(%s);' . "\n"
, $this->argument_name
, $this->min_length
);
}
if($this->max_length)
{
$validator .= sprintf('${\'%s_argument\'}->checkMaxLength(%s);' . "\n"
, $this->argument_name
, $this->max_length
);
}
if(isset($this->default_value))
{
$this->default_value = new DefaultValue($this->argument_name, $this->default_value);
if($this->default_value->isSequence())
$validator .= '$db = DB::getInstance(); $sequence = $db->getNextSequence(); ';
if($this->default_value->isOperation())
{
$validator .= sprintf('${\'%s_argument\'}->setColumnOperation(\'%s\');' . "\n"
, $this->argument_name
, $this->default_value->getOperation()
);
}
$validator .= sprintf('${\'%s_argument\'}->ensureDefaultValue(%s);' . "\n"
, $this->argument_name
, $this->default_value->toString()
);
}
if($this->notnull)
{
$validator .= sprintf('${\'%s_argument\'}->checkNotNull();' . "\n"
, $this->argument_name
);
}
return $validator;
}
}
/* End of file QueryArgumentValidator.class.php */
/* Location: ./classes/xml/xmlquery/queryargument/validator/QueryArgumentValidator.class.php */

View file

@ -1,35 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;column&gt; tag inside an XML Query file <br />
* Since the &lt;column&gt; tag supports different attributes depending on
* the type of query (select, update, insert, delete) this is only
* the base class for the classes that will model each type <column> tag.
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class ColumnTag
{
/**
* Column name
* @var string
*/
var $name;
/**
* Constructor
* @param string $name
* @return void
*/
function __construct($name)
{
$this->name = $name;
}
}
/* End of file ColumnTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/ColumnTag.class.php */

View file

@ -1,62 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;column&gt; tag inside an XML Query file whose action is 'insert'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class InsertColumnTag extends ColumnTag
{
/**
* Argument
*
* @var QueryArgument object
*/
var $argument;
/**
* Constructor
*
* @param object $column
*
* @return void
*/
function __construct($column)
{
parent::__construct($column->attrs->name);
$dbParser = DB::getParser();
$this->name = $dbParser->parseColumnName($this->name);
$this->argument = new QueryArgument($column);
}
/**
* Returns the string to be output in the cache file
* used for instantiating an InsertExpression when a
* query is executed
*
* @return string
*/
function getExpressionString()
{
return sprintf('new InsertExpression(\'%s\', ${\'%s_argument\'})'
, $this->name
, $this->argument->argument_name);
}
/**
* Returns the QueryArgument object associated with this INSERT statement
*
* @return QueryArgument
*/
function getArgument()
{
return $this->argument;
}
}
/* End of file InsertColumnTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/InsertColumnTag.class.php */

View file

@ -1,49 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;column&gt; tag inside an XML Query file whose action is 'insert-select'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class InsertColumnTagWithoutArgument extends ColumnTag
{
/**
* Constructor
*
* @param object $column
* @return void
*/
function __construct($column)
{
parent::__construct($column->attrs->name);
$dbParser = DB::getParser();
$this->name = $dbParser->parseColumnName($this->name);
}
/**
* Returns the string to be output in the cache file
*
* @return string
*/
function getExpressionString()
{
return sprintf('new Expression(\'%s\')', $this->name);
}
/**
* Returns the QueryArgument object associated with this INSERT statement
*
* @return null
*/
function getArgument()
{
return NULL;
}
}
/* End of file InsertColumnTagWithoutArgument.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/InsertColumnTagWithoutArgument.class.php */

View file

@ -1,92 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;columns&gt; tag inside an XML Query file whose action is 'insert'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class InsertColumnsTag
{
/**
* Column list
*
* @var array value is InsertColumnTag object
*/
var $columns;
/**
* Constructor
*
* @param array|string $xml_columns
* @return void
*/
function __construct($xml_columns)
{
$this->columns = array();
if(!$xml_columns)
{
return;
}
if(!is_array($xml_columns))
{
$xml_columns = array($xml_columns);
}
foreach($xml_columns as $column)
{
if($column->name === 'query')
{
$this->columns[] = new QueryTag($column, TRUE);
}
else if(!isset($column->attrs->var) && !isset($column->attrs->default))
{
$this->columns[] = new InsertColumnTagWithoutArgument($column);
}
else
{
$this->columns[] = new InsertColumnTag($column);
}
}
}
/**
* InsertColumnTag object to string
*
* @return string
*/
function toString()
{
$output_columns = 'array(' . PHP_EOL;
foreach($this->columns as $column)
{
$output_columns .= $column->getExpressionString() . PHP_EOL . ',';
}
$output_columns = substr($output_columns, 0, -1);
$output_columns .= ')';
return $output_columns;
}
/**
* Return argument list
*
* @return array
*/
function getArguments()
{
$arguments = array();
foreach($this->columns as $column)
{
$arguments[] = $column->getArgument();
}
return $arguments;
}
}
/* End of file InsertColumnsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/InsertColumnsTag.class.php */

View file

@ -1,84 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;column&gt; tag inside an XML Query file whose action is 'select'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class SelectColumnTag extends ColumnTag
{
/**
* Column alias
*
* @var string
*/
var $alias;
/**
* Click count status
*
* @var bool
*/
var $click_count;
/**
* Constructor
*
* @param string|object $column
* @return void
*/
function __construct($column)
{
if($column == "*" || $column->attrs->name == '*')
{
parent::__construct(NULL);
$this->name = "*";
}
else
{
parent::__construct($column->attrs->name);
$dbParser = DB::getParser();
$this->name = $dbParser->parseExpression($this->name);
$this->alias = $column->attrs->alias;
$this->click_count = $column->attrs->click_count;
}
}
/**
* Returns the string to be output in the cache file
*
* A select column tag in an XML query can be used for:
* <ul>
* <li> a star expression: SELECT *
* <li> a click count expression: SELECT + UPDATE
* <li> any other select expression (column name, function call etc). </li>
* </ul>
*
* @return string
*/
function getExpressionString()
{
if($this->name == '*')
{
return "new StarExpression()";
}
if($this->click_count)
{
return sprintf('new ClickCountExpression(\'%s\', %s, $args->%s)', $this->name, $this->alias ? '\'' . $this->alias . '\'' : "''", $this->click_count);
}
if(strpos($this->name, '$') === 0)
{
return sprintf('new SelectExpression($args->%s)', substr($this->name, 1));
}
$dbParser = DB::getParser();
return sprintf('new SelectExpression(\'%s\'%s)', $this->name, $this->alias ? ', \'' . $dbParser->escape($this->alias) . '\'' : '');
}
}
/* End of file SelectColumnTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/SelectColumnTag.class.php */

View file

@ -1,117 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;columns&gt; tag inside an XML Query file whose action is 'select'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class SelectColumnsTag
{
/**
* Column list
*
* @var array value is SelectColumnTag object
*/
var $columns;
/**
* Constructor
*
* @param $xml_columns_tag
* @internal param \Xml_Node_ $xml_columns
* @return void
*/
function __construct($xml_columns_tag)
{
if(!$xml_columns_tag)
{
$xml_columns_tag = new Xml_Node_();
}
$xml_columns = $xml_columns_tag->column;
$xml_queries = $xml_columns_tag->query;
$this->columns = array();
if(!$xml_columns)
{
$this->columns[] = new SelectColumnTag("*");
return;
}
if(!is_array($xml_columns))
{
$xml_columns = array($xml_columns);
}
foreach($xml_columns as $column)
{
$this->columns[] = new SelectColumnTag($column);
}
if(!$xml_queries)
{
return;
}
if(!is_array($xml_queries))
{
$xml_queries = array($xml_queries);
}
foreach($xml_queries as $column)
{
$this->columns[] = new QueryTag($column, TRUE);
}
}
/**
* Returns the string to be output in the cache file
*
* @return string
*/
function toString()
{
$output_columns = 'array(' . PHP_EOL;
foreach($this->columns as $column)
{
if(is_a($column, 'QueryTag'))
{
$output_columns .= $column->toString() . PHP_EOL . ',';
}
else
{
$output_columns .= $column->getExpressionString() . PHP_EOL . ',';
}
}
$output_columns = substr($output_columns, 0, -1);
$output_columns .= ')';
return $output_columns;
}
/**
* Return argument list
*
* @return array
*/
function getArguments()
{
$arguments = array();
foreach($this->columns as $column)
{
if(is_a($column, 'QueryTag'))
{
$arguments = array_merge($arguments, $column->getArguments());
}
}
return $arguments;
}
}
/* End of file SelectColumnsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/SelectColumnsTag.class.php */

View file

@ -1,108 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;column&gt; tag inside an XML Query file whose action is 'update'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class UpdateColumnTag extends ColumnTag
{
/**
* Argument
*
* @var QueryArgument object
*/
var $argument;
/**
* Default value
*
* @var string
*/
var $default_value;
/**
* Constructor
*
* @param object $column
* @return void
*/
function __construct($column)
{
parent::__construct($column->attrs->name);
$dbParser = DB::getParser();
$this->name = $dbParser->parseColumnName($this->name);
if($column->attrs->var)
{
$this->argument = new QueryArgument($column);
}
else
{
if(strpos($column->attrs->default, '.') !== FALSE)
{
$this->default_value = "'" . $dbParser->parseColumnName($column->attrs->default) . "'";
}
else
{
$default_value = new DefaultValue($this->name, $column->attrs->default);
if($default_value->isOperation())
{
$this->argument = new QueryArgument($column, TRUE);
}
//else $this->default_value = $dbParser->parseColumnName($column->attrs->default);
else
{
$this->default_value = $default_value->toString();
if($default_value->isStringFromFunction())
{
$this->default_value = '"\'".' . $this->default_value . '."\'"';
}
if($default_value->isString())
{
$this->default_value = '"' . $this->default_value . '"';
}
}
}
}
}
/**
* Returns the string to be output in the cache file
*
* @return string
*/
function getExpressionString()
{
if($this->argument)
{
return sprintf('new UpdateExpression(\'%s\', ${\'%s_argument\'})'
, $this->name
, $this->argument->argument_name);
}
else
{
return sprintf('new UpdateExpressionWithoutArgument(\'%s\', %s)'
, $this->name
, $this->default_value);
}
}
/**
* Returns the Argument associated with this update statement
*
* @return QueryArgument
*/
function getArgument()
{
return $this->argument;
}
}
/* End of file UpdateColumnTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/UpdateColumnTag.class.php */

View file

@ -1,83 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* Models the &lt;columns&gt; tag inside an XML Query file whose action is 'update'
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package classes\xml\xmlquery\tags\column
* @version 0.1
*/
class UpdateColumnsTag
{
/**
* Column list
*
* @var array value is UpdateColumnTag object
*/
var $columns;
/**
* Constructor
*
* @param array|object $xml_columns
* @return void
*/
function __construct($xml_columns)
{
$this->columns = array();
if(!is_array($xml_columns))
{
$xml_columns = array($xml_columns);
}
foreach($xml_columns as $column)
{
if($column->name === 'query')
{
$this->columns[] = new QueryTag($column, true);
}
else
{
$this->columns[] = new UpdateColumnTag($column);
}
}
}
/**
* Returns the string to be output in the cache file
*
* @return string
*/
function toString()
{
$output_columns = 'array(' . PHP_EOL;
foreach($this->columns as $column)
{
$output_columns .= $column->getExpressionString() . PHP_EOL . ',';
}
$output_columns = substr($output_columns, 0, -1);
$output_columns .= ')';
return $output_columns;
}
/**
* Return argument list
*
* @return array
*/
function getArguments()
{
$arguments = array();
foreach($this->columns as $column)
{
$arguments[] = $column->getArgument();
}
return $arguments;
}
}
/* End of file UpdateColumnsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/column/UpdateColumnsTag.class.php */

View file

@ -1,99 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* ConditionGroupTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/condition
* @version 0.1
*/
class ConditionGroupTag
{
/**
* condition list
* @var string|array value is ConditionTag object
*/
var $conditions;
/**
* pipe
* @var string
*/
var $pipe;
/**
* constructor
* @param string|array $conditions
* @param string $pipe
* @return void
*/
function __construct($conditions, $pipe = 'and')
{
$this->pipe = $pipe;
if(!is_array($conditions))
{
$conditions = array($conditions);
}
foreach($conditions as $condition)
{
if($condition->node_name === 'group')
{
$subconditions = $condition->condition;
$subgroups = $condition->group;
$subconditions = $subconditions ? (is_array($subconditions) ? $subconditions : [$subconditions]) : [];
$subgroups = $subgroups ? (is_array($subgroups) ? $subgroups : [$subgroups]) : [];
$this->conditions[] = new ConditionGroupTag(array_merge($subconditions, $subgroups), $condition->attrs->pipe);
}
else
{
$this->conditions[] = new ConditionTag($condition);
}
}
}
function getConditions()
{
return $this->conditions;
}
/**
* ConditionTag object to string
* @return string
*/
function getConditionGroupString()
{
$conditions_string = 'array(' . PHP_EOL;
foreach($this->conditions as $condition)
{
if($condition instanceof ConditionGroupTag)
{
$conditions_string .= $condition->getConditionGroupString() . PHP_EOL . ',';
}
else
{
$conditions_string .= $condition->getConditionString() . PHP_EOL . ',';
}
}
$conditions_string = substr($conditions_string, 0, -2); //remove ','
$conditions_string .= ')';
return sprintf("new ConditionGroup(%s%s)", $conditions_string, $this->pipe ? ',\'' . $this->pipe . '\'' : '');
}
function getArguments()
{
$arguments = array();
foreach($this->conditions as $condition)
{
$arguments = array_merge($arguments, $condition->getArguments());
}
return $arguments;
}
}
/* End of file ConditionGroupTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php */

View file

@ -1,187 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* ConditionTag
* Models the <condition> tag inside an XML Query file. Base class.
*
* @author Corina
* @package /classes/xml/xmlquery/tags/condition
* @version 0.1
*/
class ConditionTag
{
/**
* operation for example 'in', 'between', 'not in'...
* @var string
*/
var $operation;
/**
* Column name
* @var string
*/
var $column_name;
/**
* Pipe
* @var string
*/
var $pipe;
/**
* Argument name
* @var string
*/
var $argument_name;
/**
* QueryArgument object
* @var QueryArgument
*/
var $argument;
/**
* Default column
* @var string
*/
var $default_column;
/**
* QueryTag object
* @var QueryTag
*/
var $query;
/**
* constructor
* @param object $condition
* @return void
*/
function __construct($condition)
{
$this->operation = $condition->attrs->operation;
$this->pipe = $condition->attrs->pipe ?: 'and';
$dbParser = DB::getParser();
$this->column_name = $dbParser->parseExpression($condition->attrs->column);
// If default value is column name, it should be escaped
if($isColumnName = (strpos($condition->attrs->default, '.') !== FALSE
&& strpos($condition->attrs->default, '.') !== 0
&& strpos($condition->attrs->default, '%') === FALSE ))
{
$condition->attrs->default = $dbParser->parseExpression($condition->attrs->default);
}
if($condition->node_name == 'query')
{
$this->query = new QueryTag($condition, TRUE);
$this->default_column = $this->query->toString();
}
else if($condition->attrs->var && !strpos($condition->attrs->var, '.'))
{
$this->argument = new QueryArgument($condition);
$this->argument_name = $this->argument->getArgumentName();
}
else
{
if(isset($condition->attrs->default))
{
$operationList = array('in' => 1, 'between' => 1, 'notin' => 1, 'not_in' => 1);
if(isset($operationList[$this->operation]))
{
$default_value = $condition->attrs->default;
if(strpos($default_value, "'") !== FALSE)
{
$default_value = "\"" . $default_value . "\"";
}
else
{
$default_value = "'" . $default_value . "'";
}
}
else
{
$default_value_object = new DefaultValue($this->column_name, $condition->attrs->default);
$default_value = $default_value_object->toString();
if($default_value_object->isStringFromFunction())
{
$default_value = '"\'".' . $default_value . '."\'"';
}
if($default_value_object->isString() && !$isColumnName && !is_numeric($condition->attrs->default))
{
if(strpos($default_value, "'") !== FALSE)
{
$default_value = "\"" . $default_value . "\"";
}
else
{
$default_value = "'" . $default_value . "'";
}
}
}
$this->default_column = $default_value;
}
else
{
$this->default_column = "'" . $dbParser->parseColumnName($condition->attrs->var) . "'";
}
}
}
function setPipe($pipe)
{
$this->pipe = $pipe;
}
function getArguments()
{
$arguments = array();
if($this->query)
{
$arguments = array_merge($arguments, $this->query->getArguments());
}
if($this->argument)
{
$arguments[] = $this->argument;
}
return $arguments;
}
function getConditionString()
{
if($this->query)
{
return sprintf("new ConditionSubquery('%s',%s,%s%s)"
, $this->column_name
, $this->default_column
, '"' . $this->operation . '"'
, $this->pipe ? ", '" . $this->pipe . "'" : ''
);
}
else if(isset($this->default_column))
{
return sprintf("new ConditionWithoutArgument('%s',%s,%s%s)"
, $this->column_name
, $this->default_column
, '"' . $this->operation . '"'
, $this->pipe ? ", '" . $this->pipe . "'" : ''
);
}
else
{
return sprintf("new ConditionWithArgument('%s',%s,%s%s)"
, $this->column_name
, '$' . $this->argument_name . '_argument'
, '"' . $this->operation . '"'
, $this->pipe ? ", '" . $this->pipe . "'" : ''
);
}
}
}
/* End of file ConditionTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/condition/ConditionTag.class.php */

View file

@ -1,102 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* ConditionsTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/condition
* @version 0.1
*/
class ConditionsTag
{
/**
* ConditionGroupTag list
* @var array value is ConditionGroupTag object
*/
var $condition_groups;
/**
* constructor
* @param object $xml_conditions
* @return void
*/
function __construct($xml_conditions)
{
$this->condition_groups = array();
if(!$xml_conditions)
{
return;
}
$xml_condition_list = array();
if($xml_conditions->condition)
{
$xml_condition_list = $xml_conditions->condition;
}
if($xml_conditions->query)
{
if(!is_array($xml_condition_list))
{
$xml_condition_list = array($xml_condition_list);
}
if(!is_array($xml_conditions->query))
{
$xml_conditions->query = array($xml_conditions->query);
}
$xml_condition_list = array_merge($xml_condition_list, $xml_conditions->query);
}
if($xml_condition_list)
{
$this->condition_groups[] = new ConditionGroupTag($xml_condition_list);
}
$xml_groups = $xml_conditions->group;
if($xml_groups)
{
if(!is_array($xml_groups))
{
$xml_groups = array($xml_groups);
}
foreach($xml_groups as $group)
{
$subconditions = $group->condition;
$subgroups = $group->group;
$subconditions = $subconditions ? (is_array($subconditions) ? $subconditions : [$subconditions]) : [];
$subgroups = $subgroups ? (is_array($subgroups) ? $subgroups : [$subgroups]) : [];
$this->condition_groups[] = new ConditionGroupTag(array_merge($subconditions, $subgroups), $group->attrs->pipe);
}
}
}
/**
* ConditionGroupTag object to string
* @return string
*/
function toString()
{
$output_conditions = 'array(' . PHP_EOL;
foreach($this->condition_groups as $condition)
{
$output_conditions .= $condition->getConditionGroupString() . PHP_EOL . ',';
}
$output_conditions = substr($output_conditions, 0, -1);
$output_conditions .= ')';
return $output_conditions;
}
function getArguments()
{
$arguments = array();
foreach($this->condition_groups as $condition)
{
$arguments = array_merge($arguments, $condition->getArguments());
}
return $arguments;
}
}
/* End of file ConditionsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/condition/ConditionsTag.class.php */

View file

@ -1,27 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* JoinConditionsTag class
*
* @author Corina
* @package /classes/xml/xmlquery/tags/condition
* @version 0.1
*/
class JoinConditionsTag extends ConditionsTag
{
/**
* constructor
* @param object $xml_conditions
* @return void
*/
function __construct($xml_conditions)
{
parent::__construct($xml_conditions);
$this->condition_groups[0]->conditions[0]->setPipe("");
}
}
/* End of file JoinConditionsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/condition/JoinConditionsTag.class.php */

View file

@ -1,66 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* GroupsTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/group
* @version 0.1
*/
class GroupsTag
{
/**
* column list
* @var array
*/
var $groups;
/**
* constructor
* @param array|string $xml_groups
* @return void
*/
function __construct($xml_groups)
{
$this->groups = array();
if($xml_groups)
{
if(!is_array($xml_groups))
{
$xml_groups = array($xml_groups);
}
$dbParser = &DB::getParser();
for($i = 0; $i < count($xml_groups); $i++)
{
$group = $xml_groups[$i];
$column = trim($group->attrs->column);
if(!$column)
{
continue;
}
$column = $dbParser->parseExpression($column);
$this->groups[] = $column;
}
}
}
function toString()
{
$output = 'array(' . PHP_EOL;
foreach($this->groups as $group)
{
$output .= "'" . $group . "' ,";
}
$output = substr($output, 0, -1);
$output .= ')';
return $output;
}
}
/* End of file GroupsTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/group/GroupsTag.class.php */

View file

@ -1,95 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* IndexTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/navigation
* @version 0.1
*/
class IndexTag
{
/**
* argument name
* @var string
*/
var $argument_name;
/**
* QueryArgument object
* @var QueryArgument
*/
var $argument;
/**
* Default value
* @var string
*/
var $default;
/**
* Sort order
* @var string
*/
var $sort_order;
/**
* Sort order argument
* @var SortQueryArgument object
*/
var $sort_order_argument;
/**
* constructor
* @param object $index
* @return void
*/
function __construct($index)
{
$this->argument_name = $index->attrs->var;
// Sort index - column by which to sort
//$dbParser = new DB(); $dbParser = &$dbParser->getParser();
//$index->attrs->default = $dbParser->parseExpression($index->attrs->default);
$this->default = $index->attrs->default;
$this->argument = new QueryArgument($index);
// Sort order - asc / desc
$this->sort_order = $index->attrs->order;
$sortList = array('asc' => 1, 'desc' => 1);
if(!isset($sortList[$this->sort_order]))
{
$arg = new Xml_Node_();
$arg->attrs = new Xml_Node_();
$arg->attrs->var = $this->sort_order;
$arg->attrs->default = 'asc';
$this->sort_order_argument = new SortQueryArgument($arg);
$this->sort_order = '$' . $this->sort_order_argument->getArgumentName() . '_argument';
}
else
{
$this->sort_order = '"' . $this->sort_order . '"';
}
}
function toString()
{
return sprintf('new OrderByColumn(${\'%s_argument\'}, %s)', $this->argument->getArgumentName(), $this->sort_order);
}
function getArguments()
{
$arguments = array();
$arguments[] = $this->argument;
if($this->sort_order_argument)
{
$arguments[] = $this->sort_order_argument;
}
return $arguments;
}
}
/* End of file IndexTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/navigation/IndexTag.class.php */

View file

@ -1,98 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* LimitTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/navigation
* @version 0.1
*/
class LimitTag
{
/**
* Value is relate to limit query
* @var array
*/
var $arguments;
/**
* QueryArgument object
* @var QueryArgument
*/
var $page;
/**
* QueryArgument object
* @var QueryArgument
*/
var $page_count;
/**
* QueryArgument object
* @var QueryArgument
*/
var $list_count;
/**
* QueryArgument object
* @var QueryArgument
*/
var $offset;
/**
* constructor
* @param object $index
* @return void
*/
function __construct($index)
{
if($index->page && $index->page->attrs && $index->page_count && $index->page_count->attrs)
{
if(!isset($index->page->attrs->default))
$index->page->attrs->default = 1;
if(!isset($index->page_count->attrs->default))
$index->page_count->attrs->default = 10;
$this->page = new QueryArgument($index->page);
$this->page_count = new QueryArgument($index->page_count);
$this->arguments[] = $this->page;
$this->arguments[] = $this->page_count;
}
if(!isset($index->list_count->attrs->default))
$index->list_count->attrs->default = 0;
$this->list_count = new QueryArgument($index->list_count);
$this->arguments[] = $this->list_count;
if(isset($index->offset) && isset($index->offset->attrs))
{
$this->offset = new QueryArgument($index->offset);
$this->arguments[] = $this->offset;
}
}
function toString()
{
if($this->page)
{
return sprintf('new Limit(${\'%s_argument\'}, ${\'%s_argument\'}, ${\'%s_argument\'})', $this->list_count->getArgumentName(), $this->page->getArgumentName(), $this->page_count->getArgumentName());
}
elseif($this->offset)
{
return sprintf('new Limit(${\'%s_argument\'}, NULL, NULL, ${\'%s_argument\'})', $this->list_count->getArgumentName(), $this->offset->getArgumentName());
}
else
{
return sprintf('new Limit(${\'%s_argument\'})', $this->list_count->getArgumentName());
}
}
function getArguments()
{
return $this->arguments;
}
}
/* End of file LimitTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/navigation/LimitTag.class.php */

View file

@ -1,137 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* NavigationTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/navigation
* @version 0.1
*/
class NavigationTag
{
/**
* Order
* @var array
*/
var $order;
/**
* List count
* @var int
*/
var $list_count;
/**
* Page count
* @var int
*/
var $page_count;
/**
* Page
* @var int
*/
var $page;
/**
* Limit
* @var LimitTag object
*/
var $limit;
/**
* constructor
* @param object $xml_navigation
* @return void
*/
function __construct($xml_navigation)
{
$this->order = array();
if($xml_navigation)
{
$order = $xml_navigation->index;
if($order)
{
if(!is_array($order))
{
$order = array($order);
}
foreach($order as $order_info)
{
$this->order[] = new IndexTag($order_info);
}
if($xml_navigation->page && $xml_navigation->page->attrs || $xml_navigation->list_count && $xml_navigation->list_count->attrs)
{
$this->limit = new LimitTag($xml_navigation);
}
if($xml_navigation->list_count)
{
$this->list_count = $xml_navigation->list_count->attrs;
}
if($xml_navigation->page_count)
{
$this->page_count = $xml_navigation->page_count->attrs;
}
if($xml_navigation->page)
{
$this->page = $xml_navigation->page->attrs;
}
}
}
}
/**
* NavigationTag object to string
* @return string
*/
function getOrderByString()
{
$output = 'array(' . PHP_EOL;
foreach($this->order as $order)
{
$output .= $order->toString() . PHP_EOL . ',';
}
$output = substr($output, 0, -1);
$output .= ')';
return $output;
}
/**
* LimitTag object to string
* @return string
*/
function getLimitString()
{
if($this->limit)
{
return $this->limit->toString();
}
else
{
return "";
}
}
function getArguments()
{
$arguments = array();
foreach($this->order as $order)
{
$arguments = array_merge($order->getArguments(), $arguments);
}
if($this->limit)
{
$arguments = array_merge($this->limit->getArguments(), $arguments);
}
return $arguments;
}
}
/* End of file NavigationTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/navigation/NavigationTag.class.php */

View file

@ -1,407 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* QueryTag class
*
* @author Arnia Software
* @package /classes/xml/xmlquery/tags/query
* @version 0.1
*/
class QueryTag
{
/**
* Action for example, 'select', 'insert', 'delete'...
* @var string
*/
var $action;
/**
* Query id
* @var string
*/
var $query_id;
/**
* Priority
* @var string
*/
var $priority;
/**
* column type list
* @var array
*/
var $column_type;
/**
* Query stdClass object
* @var object
*/
var $query;
/**
* Columns in xml tags
* @var object
*/
var $columns;
/**
* Tables in xml tags
* @var object
*/
var $tables;
/**
* Subquery in xml tags
* @var object
*/
var $subquery;
/**
* Conditions in xml tags
* @var object
*/
var $conditions;
/**
* Groups in xml tags
* @var object
*/
var $groups;
/**
* Having in xml tags
* @var object
*/
var $having;
/**
* Navigation in xml tags
* @var object
*/
var $navigation;
/**
* Arguments in xml tags
* @var object
*/
var $arguments;
/**
* PreBuff
* @var string
*/
var $preBuff;
/**
* Buff
* @var string
*/
var $buff;
/**
* Subquery status
* @var bool
*/
var $isSubQuery;
/**
* Join type
* @var string
*/
var $join_type;
/**
* alias
* @var string
*/
var $alias;
/**
* constructor
* @param object $query
* @param bool $isSubQuery
* @return void
*/
function __construct($query, $isSubQuery = FALSE)
{
$this->action = $query->attrs->action;
$this->query_id = $query->attrs->id;
$this->priority = $query->attrs->priority;
$this->query = $query;
$this->isSubQuery = $isSubQuery;
if($this->isSubQuery)
{
$this->action = 'select';
}
if($query->attrs->alias)
{
$dbParser = DB::getParser();
$this->alias = $dbParser->escape($query->attrs->alias);
}
$this->join_type = $query->attrs->join_type;
$this->getColumns();
$tables = $this->getTables();
$this->setTableColumnTypes($tables);
$this->getSubquery(); // Used for insert-select
$this->getConditions();
$this->getGroups();
$this->getNavigation();
$this->getPrebuff();
$this->getBuff();
}
function show()
{
return TRUE;
}
function getQueryId()
{
return $this->query->attrs->query_id ? $this->query->attrs->query_id : $this->query->attrs->id;
}
function getPriority()
{
return $this->query->attrs->priority;
}
function getAction()
{
return $this->query->attrs->action;
}
function setTableColumnTypes($tables)
{
$query_id = $this->getQueryId();
if(!isset($this->column_type[$query_id]))
{
$table_tags = $tables->getTables();
$column_type = array();
foreach($table_tags as $table_tag)
{
if(is_a($table_tag, 'TableTag'))
{
$table_name = $table_tag->getTableName();
$table_alias = $table_tag->getTableAlias();
$tag_column_type = QueryParser::getTableInfo($query_id, $table_name);
$column_type[$table_alias] = $tag_column_type;
}
}
$this->column_type[$query_id] = $column_type;
}
}
function getColumns()
{
if($this->action == 'select')
{
return $this->columns = new SelectColumnsTag($this->query->columns);
}
else if($this->action == 'insert' || $this->action == 'insert-select')
{
return $this->columns = new InsertColumnsTag($this->query->columns->column);
}
else if($this->action == 'update')
{
return $this->columns = new UpdateColumnsTag($this->query->columns->column);
}
else if($this->action == 'delete')
{
return $this->columns = null;
}
}
function getPrebuff()
{
if($this->isSubQuery)
{
return;
}
// TODO Check if this work with arguments in join clause
$arguments = $this->getArguments();
$prebuff = '';
foreach($arguments as $argument)
{
if(isset($argument))
{
$arg_name = $argument->getArgumentName();
if($arg_name)
{
unset($column_type);
$prebuff .= $argument->toString();
$table_alias = $argument->getTableName();
if(isset($table_alias))
{
if(isset($this->column_type[$this->getQueryId()][$table_alias][$argument->getColumnName()]))
{
$column_type = $this->column_type[$this->getQueryId()][$table_alias][$argument->getColumnName()];
}
}
else
{
$current_tables = $this->column_type[$this->getQueryId()];
$column_name = $argument->getColumnName();
foreach($current_tables as $current_table)
{
if(isset($current_table[$column_name]))
{
$column_type = $current_table[$column_name];
}
}
}
if(isset($column_type))
{
$prebuff .= sprintf('if(${\'%s_argument\'} !== null) ${\'%s_argument\'}->setColumnType(\'%s\');' . "\n"
, $arg_name
, $arg_name
, $column_type);
}
}
}
}
$prebuff .= "\n";
return $this->preBuff = $prebuff;
}
function getBuff()
{
$buff = '';
if($this->isSubQuery)
{
$buff = 'new Subquery(';
$buff .= "'" . $this->alias . '\', ';
$buff .= ($this->columns ? $this->columns->toString() : 'null' ) . ', ' . PHP_EOL;
$buff .= $this->tables->toString() . ',' . PHP_EOL;
$buff .= $this->conditions->toString() . ',' . PHP_EOL;
$buff .= $this->groups->toString() . ',' . PHP_EOL;
$buff .= $this->navigation->getOrderByString() . ',' . PHP_EOL;
$limit = $this->navigation->getLimitString();
$buff .= $limit ? $limit : 'null' . PHP_EOL;
$buff .= $this->join_type ? "'" . $this->join_type . "'" : '';
$buff .= ')';
$this->buff = $buff;
return $this->buff;
}
$buff .= '$query = new Query();' . PHP_EOL;
$buff .= sprintf('$query->setQueryId("%s");%s', $this->query_id, "\n");
$buff .= sprintf('$query->setAction("%s");%s', $this->action, "\n");
$buff .= sprintf('$query->setPriority("%s");%s', $this->priority, "\n");
$buff .= $this->preBuff;
if($this->columns)
{
$buff .= '$query->setColumns(' . $this->columns->toString() . ');' . PHP_EOL;
}
$buff .= '$query->setTables(' . $this->tables->toString() . ');' . PHP_EOL;
if($this->action == 'insert-select')
{
$buff .= '$query->setSubquery(' . $this->subquery->toString() . ');' . PHP_EOL;
}
$buff .= '$query->setConditions(' . $this->conditions->toString() . ');' . PHP_EOL;
$buff .= '$query->setGroups(' . $this->groups->toString() . ');' . PHP_EOL;
$buff .= '$query->setHaving(' . $this->having->toString() . ');' . PHP_EOL;
$buff .= '$query->setOrder(' . $this->navigation->getOrderByString() . ');' . PHP_EOL;
$buff .= '$query->setLimit(' . $this->navigation->getLimitString() . ');' . PHP_EOL;
$this->buff = $buff;
return $this->buff;
}
function getTables()
{
if($this->query->index_hint && ($this->query->index_hint->attrs->for == 'ALL' || Context::getDBType() == strtolower($this->query->index_hint->attrs->for)))
{
return $this->tables = new TablesTag($this->query->tables, $this->query->index_hint);
}
else
{
return $this->tables = new TablesTag($this->query->tables);
}
}
function getSubquery()
{
if($this->query->query)
{
$this->subquery = new QueryTag($this->query->query, true);
}
}
function getConditions()
{
return $this->conditions = new ConditionsTag($this->query->conditions);
}
function getGroups()
{
if($this->query->groups)
{
$this->groups = new GroupsTag($this->query->groups->group);
$this->having = new ConditionsTag($this->query->groups->having);
}
else
{
$this->groups = new GroupsTag(NULL);
$this->having = new ConditionsTag(array());
}
return $this->groups;
}
function getNavigation()
{
return $this->navigation = new NavigationTag($this->query->navigation);
}
function toString()
{
return $this->buff;
}
function getTableString()
{
return $this->buff;
}
function getConditionString()
{
return $this->buff;
}
function getExpressionString()
{
return $this->buff;
}
function getArguments()
{
$arguments = array();
if($this->columns)
{
$arguments = array_merge($arguments, $this->columns->getArguments());
}
if($this->action == 'insert-select')
{
$arguments = array_merge($arguments, $this->subquery->getArguments());
}
$arguments = array_merge($arguments, $this->tables->getArguments());
$arguments = array_merge($arguments, $this->conditions->getArguments());
$arguments = array_merge($arguments, $this->having->getArguments());
$arguments = array_merge($arguments, $this->navigation->getArguments());
return $arguments;
}
}
/* End of file QueryTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/navigation/QueryTag.class.php */

View file

@ -1,66 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* HintTableTag
* Models the <table> tag inside an XML Query file and the corresponding <index_hint> tag
*
* @author Arnia Sowftare
* @package /classes/xml/xmlquery/tags/table
* @version 0.1
*/
class HintTableTag extends TableTag
{
/**
* Action for example, 'select', 'insert', 'delete'...
* @var array
*/
var $index;
/**
* constructor
* Initialises Table Tag properties
* @param object $table XML <table> tag
* @param array $index
* @return void
*/
function __construct($table, $index)
{
parent::__construct($table);
$this->index = $index;
}
function getTableString()
{
$dbParser = DB::getParser();
$dbType = ucfirst(Context::getDBType());
$result = sprintf('new %sTableWithHint(\'%s\'%s, array('
, starts_with('mysql', $dbType, false) ? 'Mysql' : $dbType
, $dbParser->escape($this->name)
, $this->alias ? ', \'' . $dbParser->escape($this->alias) . '\'' : ', null'
//, ', \'' . $dbParser->escape($this->index->name) .'\', \'' . $this->index->type .'\''
);
foreach($this->index as $indx)
{
$result .= "new IndexHint(";
$result .= '\'' . $dbParser->escape($indx->name) . '\', \'' . $indx->type . '\'' . ') , ';
}
$result = substr($result, 0, -2);
$result .= '))';
return $result;
}
function getArguments()
{
if(!isset($this->conditionsTag))
{
return array();
}
return $this->conditionsTag->getArguments();
}
}
/* End of file HintTableTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/table/HintTableTag.class.php */

View file

@ -1,145 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* TableTag
* Models the <table> tag inside an XML Query file
* @abstract
* Example
* <table name="modules" />
* <table name="documents" alias="doc" />
* Attributes
* name - name of the table - table prefix will be automatically added
* alias - table alias. If no value is specified, the table name will be set as default alias
* join_type - in case the table is part of a join clause, this specifies the type of join: left, right etc.
* - permitted values: 'left join','left outer join','right join','right outer join'
* Children
* Can have children of type <conditions>
*
* @author Arnia Sowftare
* @package /classes/xml/xmlquery/tags/table
* @version 0.1
*/
class TableTag
{
/**
* Unescaped name
* @var string
*/
var $unescaped_name;
/**
* name
* @var string
*/
var $name;
/**
* alias
* @var string
*/
var $alias;
/**
* Join type
* @example 'left join', 'left outer join', 'right join', 'right outer join'
* @var string
*/
var $join_type;
/**
* Condition object
* @var object
*/
var $conditions;
/**
* JoinConditionsTag
* @var JoinConditionsTag object
*/
var $conditionsTag;
/**
* constructor
* Initialises Table Tag properties
* @param object $table XML <table> tag
* @return void
*/
function __construct($table)
{
$dbParser = DB::getParser();
$this->unescaped_name = $table->attrs->name;
$this->name = $dbParser->parseTableName($table->attrs->name);
$this->alias = $table->attrs->alias;
if(!$this->alias)
{
$this->alias = $table->attrs->name;
}
$this->join_type = $table->attrs->type;
$this->conditions = $table->conditions;
if($this->isJoinTable())
{
$this->conditionsTag = new JoinConditionsTag($this->conditions);
}
}
function isJoinTable()
{
$joinList = array('left join' => 1, 'left outer join' => 1, 'right join' => 1, 'right outer join' => 1);
if(isset($joinList[$this->join_type]) && countobj($this->conditions))
{
return true;
}
return false;
}
function getTableAlias()
{
return $this->alias;
}
function getTableName()
{
return $this->unescaped_name;
}
/**
* Returns string for printing in PHP query cache file
* The string contains code for instantiation of either
* a Table or a JoinTable object
* @return string
*/
function getTableString()
{
$dbParser = DB::getParser();
if($this->isJoinTable())
{
return sprintf('new JoinTable(\'%s\', \'%s\', "%s", %s)'
, $dbParser->escape($this->name)
, $dbParser->escape($this->alias)
, $this->join_type, $this->conditionsTag->toString());
}
return sprintf('new Table(\'%s\'%s)'
, $dbParser->escape($this->name)
, $this->alias ? ', \'' . $dbParser->escape($this->alias) . '\'' : '');
}
function getArguments()
{
if(!isset($this->conditionsTag))
{
return array();
}
return $this->conditionsTag->getArguments();
}
}
/* End of file TableTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/table/TableTag.class.php */

View file

@ -1,122 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
* TablesTag class
* Models the <tables> tag inside an XML Query file
* @abstract
* Example
* <tables>
* <table name="documents" alias="doc" />
* </tables>
* Attributes
* None.
* Children
* Can have children of type <table> or <query>
*
* @author Arnia Sowftare
* @package /classes/xml/xmlquery/tags/table
* @version 0.1
*/
class TablesTag
{
/**
* Table list
* @var array
*/
var $tables;
/**
* constructor
* @param object $xml_tables_tag
* @param object $xml_index_hints_tag
* @return void
*/
function __construct($xml_tables_tag, $xml_index_hints_tag = NULL)
{
$this->tables = array();
$xml_tables = $xml_tables_tag->table;
if(!is_array($xml_tables))
{
$xml_tables = array($xml_tables);
}
if($xml_index_hints_tag)
{
$index_nodes = $xml_index_hints_tag->index;
if(!is_array($index_nodes))
{
$index_nodes = array($index_nodes);
}
foreach($index_nodes as $index_node)
{
if(!isset($indexes[$index_node->attrs->table]))
{
$indexes[$index_node->attrs->table] = array();
}
$count = count($indexes[$index_node->attrs->table]);
$indexes[$index_node->attrs->table][$count] = (object) NULL;
$indexes[$index_node->attrs->table][$count]->name = $index_node->attrs->name;
$indexes[$index_node->attrs->table][$count]->type = $index_node->attrs->type;
}
}
foreach($xml_tables as $tag)
{
if($tag->attrs->query == 'true')
{
$this->tables[] = new QueryTag($tag, true);
}
else
{
if(isset($indexes[$tag->attrs->name]) && $indexes[$tag->attrs->name])
{
$this->tables[] = new HintTableTag($tag, $indexes[$tag->attrs->name]);
}
else
{
$this->tables[] = new TableTag($tag);
}
}
}
}
function getTables()
{
return $this->tables;
}
function toString()
{
$output_tables = 'array(' . PHP_EOL;
foreach($this->tables as $table)
{
if(is_a($table, 'QueryTag'))
{
$output_tables .= $table->toString() . PHP_EOL . ',';
}
else
{
$output_tables .= $table->getTableString() . PHP_EOL . ',';
}
}
$output_tables = substr($output_tables, 0, -1);
$output_tables .= ')';
return $output_tables;
}
function getArguments()
{
$arguments = array();
foreach($this->tables as $table)
{
$arguments = array_merge($arguments, $table->getArguments());
}
return $arguments;
}
}
/* End of file TablesTag.class.php */
/* Location: ./classes/xml/xmlquery/tags/table/TablesTag.class.php */

View file

@ -49,27 +49,6 @@ $GLOBALS['RX_AUTOLOAD_FILE_MAP'] = array_change_key_case(array(
'CacheHandler' => 'classes/cache/CacheHandler.class.php',
'Context' => 'classes/context/Context.class.php',
'DB' => 'classes/db/DB.class.php',
'Query' => 'classes/db/queryparts/Query.class.php',
'Subquery' => 'classes/db/queryparts/Subquery.class.php',
'Condition' => 'classes/db/queryparts/condition/Condition.class.php',
'ConditionGroup' => 'classes/db/queryparts/condition/ConditionGroup.class.php',
'ConditionSubquery' => 'classes/db/queryparts/condition/ConditionSubquery.class.php',
'ConditionWithArgument' => 'classes/db/queryparts/condition/ConditionWithArgument.class.php',
'ConditionWithoutArgument' => 'classes/db/queryparts/condition/ConditionWithoutArgument.class.php',
'ClickCountExpression' => 'classes/db/queryparts/expression/ClickCountExpression.class.php',
'DeleteExpression' => 'classes/db/queryparts/expression/DeleteExpression.class.php',
'Expression' => 'classes/db/queryparts/expression/Expression.class.php',
'InsertExpression' => 'classes/db/queryparts/expression/InsertExpression.class.php',
'SelectExpression' => 'classes/db/queryparts/expression/SelectExpression.class.php',
'StarExpression' => 'classes/db/queryparts/expression/StarExpression.class.php',
'UpdateExpression' => 'classes/db/queryparts/expression/UpdateExpression.class.php',
'UpdateExpressionWithoutArgument' => 'classes/db/queryparts/expression/UpdateExpressionWithoutArgument.class.php',
'Limit' => 'classes/db/queryparts/limit/Limit.class.php',
'OrderByColumn' => 'classes/db/queryparts/order/OrderByColumn.class.php',
'IndexHint' => 'classes/db/queryparts/table/IndexHint.class.php',
'JoinTable' => 'classes/db/queryparts/table/JoinTable.class.php',
'MysqlTableWithHint' => 'classes/db/queryparts/table/MysqlTableWithHint.class.php',
'Table' => 'classes/db/queryparts/table/Table.class.php',
'DisplayHandler' => 'classes/display/DisplayHandler.class.php',
'HTMLDisplayHandler' => 'classes/display/HTMLDisplayHandler.php',
'JSCallbackDisplayHandler' => 'classes/display/JSCallbackDisplayHandler.php',
@ -104,36 +83,6 @@ $GLOBALS['RX_AUTOLOAD_FILE_MAP'] = array_change_key_case(array(
'XmlJsFilter' => 'classes/xml/XmlJsFilter.class.php',
'XmlLangParser' => 'classes/xml/XmlLangParser.class.php',
'XmlParser' => 'classes/xml/XmlParser.class.php',
'XmlQueryParser' => 'classes/xml/XmlQueryParser.class.php',
'DBParser' => 'classes/xml/xmlquery/DBParser.class.php',
'QueryParser' => 'classes/xml/xmlquery/QueryParser.class.php',
'Argument' => 'classes/xml/xmlquery/argument/Argument.class.php',
'ConditionArgument' => 'classes/xml/xmlquery/argument/ConditionArgument.class.php',
'SortArgument' => 'classes/xml/xmlquery/argument/SortArgument.class.php',
'DefaultValue' => 'classes/xml/xmlquery/queryargument/DefaultValue.class.php',
'QueryArgument' => 'classes/xml/xmlquery/queryargument/QueryArgument.class.php',
'SortQueryArgument' => 'classes/xml/xmlquery/queryargument/SortQueryArgument.class.php',
'QueryArgumentValidator' => 'classes/xml/xmlquery/queryargument/validator/QueryArgumentValidator.class.php',
'ColumnTag' => 'classes/xml/xmlquery/tags/column/ColumnTag.class.php',
'InsertColumnTag' => 'classes/xml/xmlquery/tags/column/InsertColumnTag.class.php',
'InsertColumnTagWithoutArgument' => 'classes/xml/xmlquery/tags/column/InsertColumnTagWithoutArgument.class.php',
'InsertColumnsTag' => 'classes/xml/xmlquery/tags/column/InsertColumnsTag.class.php',
'SelectColumnTag' => 'classes/xml/xmlquery/tags/column/SelectColumnTag.class.php',
'SelectColumnsTag' => 'classes/xml/xmlquery/tags/column/SelectColumnsTag.class.php',
'UpdateColumnTag' => 'classes/xml/xmlquery/tags/column/UpdateColumnTag.class.php',
'UpdateColumnsTag' => 'classes/xml/xmlquery/tags/column/UpdateColumnsTag.class.php',
'ConditionGroupTag' => 'classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php',
'ConditionTag' => 'classes/xml/xmlquery/tags/condition/ConditionTag.class.php',
'ConditionsTag' => 'classes/xml/xmlquery/tags/condition/ConditionsTag.class.php',
'JoinConditionsTag' => 'classes/xml/xmlquery/tags/condition/JoinConditionsTag.class.php',
'GroupsTag' => 'classes/xml/xmlquery/tags/group/GroupsTag.class.php',
'IndexTag' => 'classes/xml/xmlquery/tags/navigation/IndexTag.class.php',
'LimitTag' => 'classes/xml/xmlquery/tags/navigation/LimitTag.class.php',
'NavigationTag' => 'classes/xml/xmlquery/tags/navigation/NavigationTag.class.php',
'QueryTag' => 'classes/xml/xmlquery/tags/query/QueryTag.class.php',
'HintTableTag' => 'classes/xml/xmlquery/tags/table/HintTableTag.class.php',
'TableTag' => 'classes/xml/xmlquery/tags/table/TableTag.class.php',
'TablesTag' => 'classes/xml/xmlquery/tags/table/TablesTag.class.php',
'Bmp' => 'common/libraries/bmp.php',
'Ftp' => 'common/libraries/ftp.php',
'Tar' => 'common/libraries/tar.php',

1304
common/framework/db.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -355,7 +355,7 @@ class Debug
'query_id' => $query['query_id'],
'query_connection' => $query['connection'],
'query_string' => $query['query'],
'query_time' => $query['elapsed_time'],
'query_time' => floatval($query['elapsed_time']),
'file' => $query['called_file'],
'line' => $query['called_line'],
'method' => $query['called_method'],
@ -746,6 +746,7 @@ class Debug
public static function getDebugData()
{
// Collect debug information.
$db = DB::getInstance();
$data = (object)array(
'timestamp' => DateTime::formatTimestamp('Y-m-d H:i:s', \RX_TIME),
'url' => getCurrentPageUrl(),
@ -761,8 +762,8 @@ class Debug
'total' => sprintf('%0.4f sec', microtime(true) - \RX_MICROTIME),
'template' => sprintf('%0.4f sec (count: %d)', $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']),
'xmlparse' => sprintf('%0.4f sec', $GLOBALS['__xmlparse_elapsed__']),
'db_query' => sprintf('%0.4f sec (count: %d)', $GLOBALS['__db_elapsed_time__'], count(self::$_queries)),
'db_class' => sprintf('%0.4f sec', $GLOBALS['__dbclass_elapsed_time__'] - $GLOBALS['__db_elapsed_time__']),
'db_query' => sprintf('%0.4f sec (count: %d)', $db->getQueryElapsedTime(), count(self::$_queries)),
'db_class' => sprintf('%0.4f sec', $db->getTotalElapsedTime() - $db->getQueryElapsedTime()),
'layout' => sprintf('%0.4f sec', $GLOBALS['__layout_compile_elapsed__']),
'widget' => sprintf('%0.4f sec', $GLOBALS['__widget_excute_elapsed__']),
'remote' => sprintf('%0.4f sec', $GLOBALS['__remote_request_elapsed__']),

View file

@ -0,0 +1,18 @@
<?php
namespace Rhymix\Framework\Exceptions;
/**
* The DB Error exception class.
*/
class DBError extends \Rhymix\Framework\Exception
{
public function __construct($message = '', $code = 0, $previous = null)
{
if ($message === '')
{
$message = 'DB Error';
}
parent::__construct($message, $code, $previous);
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace Rhymix\Framework\Exceptions;
/**
* The Query Error exception class.
*/
class QueryError extends DBError
{
public function __construct($message = '', $code = 0, $previous = null)
{
if ($message === '')
{
$message = 'Query Error';
}
parent::__construct($message, $code, $previous);
}
}

View file

@ -0,0 +1,148 @@
<?php
namespace Rhymix\Framework\Helpers;
use Rhymix\Framework\DB;
use Rhymix\Framework\Debug;
use Rhymix\Framework\Exceptions\DBError;
/**
* DB helper class.
*
* We use instances of this class instead of raw PDO in order to provide
* better logging and error handling while keeping backward compatibility.
*/
class DBHelper extends \PDO
{
/**
* Store the database type (e.g. master) here.
*/
protected $_type = 'master';
/**
* Set the database type.
*/
public function setType(string $type)
{
$this->_type = $type;
}
/**
* Create a prepared statement.
*
* @param string $statement
* @param array $driver_options
* @return PDOStatement|DBStmtHelper
*/
public function prepare($statement, $driver_options = null)
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
try
{
/**
* $stmt will be an instance of DBStmtHelper.
* This allows it to track the parent database's type
* and send query logs to the appropriate place.
*/
$stmt = $driver_options ? parent::prepare($statement, $driver_options) : parent::prepare($statement);
$stmt->setFetchMode(\PDO::FETCH_OBJ);
$stmt->setType($this->_type);
$db_class->clearError();
}
catch (\PDOException $e)
{
/**
* We only measure the time when the prepared statement fails.
* If the statement is successfully prepared, time will be measured
* when the statement is executed in DBStmtHelper.
*/
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
$db_class->setError(-1, $e->getMessage());
Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time));
/**
* This is a new feature in Rhymix 2.0 so we don't have to mess
* with status objects. We just throw an exception. Catch it!
*/
throw new DBError($e->getMessage(), 0, $e);
}
return $stmt;
}
/**
* Execute a query.
*
* This method accepts additional parameters, but they are not for creating
* prepared statements. They exist because PDO's own query() method accepts
* various kinds of additional parameters, and we don't want to touch them.
*
* @param string $statement
* @return PDOStatement|DBStmtHelper
*/
public function query($statement)
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
$args = func_get_args();
array_shift($args);
try
{
/**
* $stmt will be an instance of DBStmtHelper.
* This allows it to track the parent database's type
* and send query logs to the appropriate place.
*/
$stmt = parent::query($statement, ...$args);
$stmt->setFetchMode(\PDO::FETCH_OBJ);
$stmt->setType($this->_type);
$db_class->clearError();
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
}
finally
{
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time));
}
return $stmt;
}
/**
* Execute a query and return the number of affected rows.
*
* @param string $statement
* @return bool
*/
public function exec($query)
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
try
{
$result = parent::exec($query);
$db_class->clearError();
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
}
finally
{
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($query, $elapsed_time));
}
return $result;
}
}

View file

@ -0,0 +1,65 @@
<?php
namespace Rhymix\Framework\Helpers;
use Rhymix\Framework\DB;
use Rhymix\Framework\Debug;
use Rhymix\Framework\Exceptions\DBError;
/**
* DB Statement helper class.
*
* We use instances of this class instead of raw PDOStatement in order to log
* individual execute() calls of prepared statements. This is controlled by
* the PDO::ATTR_STATEMENT_CLASS attribute set in the DB class.
*/
class DBStmtHelper extends \PDOStatement
{
/**
* Store the database type (e.g. master) here.
*/
protected $_type = 'master';
/**
* Set the database type.
*/
public function setType(string $type)
{
$this->_type = $type;
}
/**
* Execute a prepared statement.
*
* We don't set a type for $input_parameters because the original
* PDOStatement class accepts both arrays and null. Actually, the null
* value must be omitted altogether or it will throw an error.
*
* @param array $input_parameters
* @return bool
*/
public function execute($input_parameters = null): bool
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
try
{
$result = parent::execute($input_parameters);
$db_class->clearError();
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
throw new DBError($e->getMessage(), 0, $e);
}
finally
{
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($this->queryString, $elapsed_time));
}
return $result;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* ColumnRead class.
*/
class ColumnRead
{
public $name;
public $alias;
public $is_expression = false;
public $is_wildcard = false;
}

View file

@ -0,0 +1,18 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* ColumnWrite class.
*/
class ColumnWrite extends VariableBase
{
public $name;
public $operation = 'equal';
public $var;
public $default;
public $not_null;
public $filter;
public $minlength = 0;
public $maxlength = 0;
}

View file

@ -0,0 +1,19 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* Condition class.
*/
class Condition extends VariableBase
{
public $operation;
public $column;
public $var;
public $default;
public $not_null;
public $filter;
public $minlength = 0;
public $maxlength = 0;
public $pipe = 'AND';
}

View file

@ -0,0 +1,12 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* Condition Group class.
*/
class ConditionGroup
{
public $conditions = array();
public $pipe = 'AND';
}

View file

@ -0,0 +1,12 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* GroupBy class.
*/
class GroupBy
{
public $columns = array();
public $having = array();
}

View file

@ -0,0 +1,15 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* Navigation class.
*/
class Navigation
{
public $orderby = array();
public $list_count;
public $page_count;
public $page;
public $offset;
}

View file

@ -0,0 +1,14 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* OrderBy class.
*/
class OrderBy extends VariableBase
{
public $var;
public $default;
public $order_var;
public $order_default = 'ASC';
}

View file

@ -0,0 +1,626 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* Query class.
*/
class Query extends VariableBase
{
/**
* Attributes common to all queries.
*/
public $name;
public $type;
public $tables = array();
public $columns = array();
public $conditions = array();
public $groupby = null;
public $navigation = null;
public $select_distinct = false;
public $update_duplicate = false;
public $requires_pagination = false;
/**
* Attributes for subqueries in the <tables> or <columns> section.
*/
public $alias;
public $join_type;
public $join_conditions = array();
/**
* Attributes for subqueries in the <conditions> section.
*/
public $operation;
public $column;
public $pipe;
/**
* Attributes used during query string generation.
*/
protected $_prefix = '';
protected $_args = array();
protected $_column_list = array();
protected $_params = array();
/**
* Generate the query string for this query.
*
* @param string $prefix
* @param array $args
* @param array $column_list
* @param bool $count_only
* @return string
*/
public function getQueryString(string $prefix = '', array $args, array $column_list = [], bool $count_only = false): string
{
// Save the query information.
$this->_prefix = $prefix;
$this->_args = $args;
$this->_column_list = $column_list;
$this->_params = array();
// Call different internal methods depending on the query type.
switch ($this->type)
{
case 'SELECT':
$result = $this->_getSelectQueryString($count_only);
break;
case 'INSERT':
$result = $this->_getInsertQueryString();
break;
case 'UPDATE':
$result = $this->_getUpdateQueryString();
break;
case 'DELETE':
$result = $this->_getDeleteQueryString();
break;
default:
$result = '';
}
// Reset state and return the result.
$this->_prefix = '';
$this->_args = array();
$this->_column_list = array();
return $result;
}
/**
* Get the query parameters to use with the query string generated above.
*
* @return array
*/
public function getQueryParams()
{
return $this->_params;
}
/**
* Check if this query requires pagination.
*
* @return bool
*/
public function requiresPagination(): bool
{
return $this->requires_pagination;
}
/**
* Generate a SELECT query string.
*
* @param bool $count_only
* @return string
*/
protected function _getSelectQueryString(bool $count_only = false): string
{
// Initialize the query string.
$result = 'SELECT ';
if ($this->select_distinct)
{
$result .= 'DISTINCT ';
}
// Compose the column list.
$columns = array();
if ($count_only)
{
$result .= 'COUNT(*) AS `count`';
}
elseif ($this->_column_list)
{
$result .= implode(', ', array_map(function($str) {
return self::quoteName($str);
}, $this->_column_list));
}
else
{
foreach ($this->columns as $column)
{
if ($column instanceof self)
{
$subquery = $column->getQueryString($this->_prefix, $this->_args);
foreach ($column->getQueryParams() as $param)
{
$this->_params[] = $param;
}
$columns[] = sprintf('(%s) AS %s', $subquery, self::quoteName($column->alias));
}
elseif ($column->is_expression && !$column->is_wildcard)
{
$columns[] = $column->name . ($column->alias ? (' AS ' . self::quoteName($column->alias)) : '');
}
else
{
$columns[] = self::quoteName($column->name) . ($column->alias ? (' AS ' . self::quoteName($column->alias)) : '');
}
}
$result .= implode(', ', $columns);
}
// Compose the FROM clause.
if (count($this->tables))
{
$tables = $this->_arrangeTables($this->tables);
if ($tables !== '')
{
$result .= ' FROM ' . $tables;
}
}
// Compose the WHERE clause.
if (count($this->conditions))
{
$where = $this->_arrangeConditions($this->conditions);
if ($where !== '')
{
$result .= ' WHERE ' . $where;
}
}
// Compose the GROUP BY clause.
if ($this->groupby && count($this->groupby->columns))
{
$columns = array();
foreach ($this->groupby->columns as $column_name)
{
if (self::isValidColumnName($column_name))
{
$columns[] = self::quoteName($column_name);
}
else
{
$columns[] = $column_name;
}
}
$result .= ' GROUP BY ' . implode(', ', $columns);
}
if ($this->groupby && count($this->groupby->having))
{
$having = $this->_arrangeConditions($this->groupby->having);
if ($having !== '')
{
$result .= ' HAVING ' . $having;
}
}
// Compose the ORDER BY clause.
if ($this->navigation && count($this->navigation->orderby) && !$count_only)
{
$result .= ' ORDER BY ' . $this->_arrangeOrderBy($this->navigation);
}
// Compose the LIMIT/OFFSET clause.
if ($this->navigation && $this->navigation->list_count && !$count_only)
{
$result .= ' LIMIT ' . $this->_arrangeLimitOffset($this->navigation);
}
// Return the final query string.
return $result;
}
/**
* Generate a INSERT query string.
*
* @return string
*/
protected function _getInsertQueryString(): string
{
// Initialize the query string.
$result = 'INSERT';
// Compose the INTO clause.
if (count($this->tables))
{
$tables = $this->_arrangeTables($this->tables, false);
if ($tables !== '')
{
$result .= ' INTO ' . $tables;
}
}
// Process the SET clause with new values.
$columns = array();
foreach ($this->columns as $column)
{
$setval_string = $this->_parseCondition($column);
if ($setval_string !== '')
{
$columns[] = $setval_string;
}
}
$result .= ' SET ' . implode(', ', $columns);
// Process the ON DUPLICATE KEY UPDATE (upsert) clause.
if ($this->update_duplicate && count($columns))
{
$result .= ' ON DUPLICATE KEY UPDATE ' . implode(', ', $columns);
$duplicate_params = $this->_params;
foreach ($duplicate_params as $param)
{
$this->_params[] = $param;
}
}
// Return the final query string.
return $result;
}
/**
* Generate a UPDATE query string.
*
* @return string
*/
protected function _getUpdateQueryString(): string
{
// Initialize the query string.
$result = 'UPDATE ';
// Compose the INTO clause.
if (count($this->tables))
{
$tables = $this->_arrangeTables($this->tables, false);
if ($tables !== '')
{
$result .= $tables;
}
}
// Compose the SET clause with updated values.
$columns = array();
foreach ($this->columns as $column)
{
$setval_string = $this->_parseCondition($column);
if ($setval_string !== '')
{
$columns[] = $setval_string;
}
}
$result .= ' SET ' . implode(', ', $columns);
// Compose the WHERE clause.
if (count($this->conditions))
{
$where = $this->_arrangeConditions($this->conditions);
if ($where !== '')
{
$result .= ' WHERE ' . $where;
}
}
// Return the final query string.
return $result;
}
/**
* Generate a DELETE query string.
*
* @return string
*/
protected function _getDeleteQueryString(): string
{
// Initialize the query string.
$result = 'DELETE';
// Compose the FROM clause.
if (count($this->tables))
{
$tables = $this->_arrangeTables($this->tables, false);
if ($tables !== '')
{
$result .= ' FROM ' . $tables;
}
}
// Compose the WHERE clause.
if (count($this->conditions))
{
$where = $this->_arrangeConditions($this->conditions);
if ($where !== '')
{
$result .= ' WHERE ' . $where;
}
}
// Compose the ORDER BY clause.
if ($this->navigation && count($this->navigation->orderby))
{
$result .= ' ORDER BY ' . $this->_arrangeOrderBy($this->navigation);
}
// Compose the LIMIT/OFFSET clause.
if ($this->navigation && $this->navigation->list_count)
{
$result .= ' LIMIT ' . $this->_arrangeLimitOffset($this->navigation);
}
// Return the final query string.
return $result;
}
/**
* Generate a FROM clause from a list of tables.
*
* @param array $tables
* @param bool $use_aliases
* @return string
*/
protected function _arrangeTables(array $tables, bool $use_aliases = true): string
{
// Initialize the result.
$result = array();
// Process each table definition.
foreach ($tables as $table)
{
// Subquery
if ($table instanceof self)
{
$tabledef = '(' . $table->getQueryString($this->_prefix, $this->_args) . ')';
if ($table->alias)
{
$tabledef .= ' AS `' . $table->alias . '`';
}
foreach ($table->getQueryParams() as $param)
{
$this->_params[] = $param;
}
}
// Regular table
else
{
$tabledef = self::quoteName($this->_prefix . $table->name);
if ($use_aliases && $table->alias && $table->alias !== ($this->_prefix . $table->name))
{
$tabledef .= ' AS `' . $table->alias . '`';
}
}
// Add join conditions
if ($table->join_type)
{
$join_where = $this->_arrangeConditions($table->join_conditions);
if ($join_where !== '')
{
$tabledef = $tabledef . ' ON ' . $join_where;
}
$result[] = ' ' . $table->join_type . ' ' . $tabledef;
}
else
{
$result[] = (count($result) ? ', ' : '') . $tabledef;
}
}
// Combine the result and return as a string.
return implode('', $result);
}
/**
* Generate a WHERE clause from a list of conditions.
*
* @param array $conditions
* @return string
*/
protected function _arrangeConditions(array $conditions): string
{
// Initialize the result.
$result = '';
// Process each condition.
foreach ($conditions as $condition)
{
// Subquery
if ($condition instanceof self)
{
$condition_string = $this->_parseCondition($condition);
if ($condition_string !== '')
{
$result .= ($result === '' ? '' : (' ' . $condition->pipe . ' ')) . $condition_string;
}
}
// Condition group
elseif ($condition instanceof ConditionGroup)
{
$condition_string = $this->_arrangeConditions($condition->conditions);
if ($condition_string !== '')
{
$result .= ($result === '' ? '' : (' ' . $condition->pipe . ' ')) . '(' . $condition_string . ')';
}
}
// Simple condition
else
{
$condition_string = $this->_parseCondition($condition);
if ($condition_string !== '')
{
$result .= ($result === '' ? '' : (' ' . $condition->pipe . ' ')) . $condition_string;
}
}
}
// Return the WHERE clause.
return $result;
}
/**
* Generate a ORDER BY clause from navigation settings.
*
* @param object $navigation
* @return string
*/
protected function _arrangeOrderBy(Navigation $navigation): string
{
// Initialize the result.
$result = array();
// Process each column definition.
foreach ($navigation->orderby as $orderby)
{
// Get the name of the column or expression to order by.
$column_name = '';
list($is_expression, $column_name) = $orderby->getValue($this->_args);
if (!$column_name)
{
continue;
}
if (!$is_expression && self::isValidColumnName($column_name))
{
$column_name = self::quoteName($column_name);
}
// Get the ordering (ASC or DESC).
if (preg_match('/^(ASC|DESC)$/i', $orderby->order_var, $matches))
{
$column_order = strtoupper($matches[1]);
}
elseif (isset($this->_args[$orderby->order_var]))
{
$column_order = preg_replace('/[^A-Z]/', '', strtoupper($this->_args[$orderby->order_var]));
}
else
{
$column_order = preg_replace('/[^A-Z]/', '', strtoupper($orderby->order_default));
}
$result[] = $column_name . ' ' . $column_order;
}
// Return the ORDER BY clause.
return implode(', ', $result);
}
/**
* Generate a LIMIT/OFFSET clause from navigation settings.
*
* @param object $navigation
* @return string
*/
protected function _arrangeLimitOffset(Navigation $navigation): string
{
// Get the list count.
list($is_expression, $list_count) = $navigation->list_count->getValue($this->_args);
if ($list_count <= 0)
{
return '';
}
// Get the offset from the page or offset variable.
if ($navigation->page)
{
list($is_expression, $page) = $navigation->page->getValue($this->_args);
}
if ($navigation->offset)
{
list($is_expression, $offset) = $navigation->offset->getValue($this->_args);
}
// If page is available, set the offset and require pagination for this query.
if ($page > 0)
{
$offset = $list_count * ($page - 1);
if ($this->type === 'SELECT')
{
$this->requires_pagination = true;
}
}
else
{
$page = 1;
}
// Return the LIMIT/OFFSET clause.
return ($offset > 0 ? (intval($offset) . ', ') : '') . intval($list_count);
}
/**
* Generate each condition in a WHERE clause.
*
* @param object $condition
* @return string
*/
protected function _parseCondition(VariableBase $condition): string
{
list($where, $params) = $condition->getQueryStringAndParams($this->_args, $this->_prefix);
foreach ($params as $param)
{
$this->_params[] = $param;
}
return $where;
}
/**
* Quote a column name.
*
* @param string $column_name
* @return string
*/
public static function quoteName(string $column_name): string
{
$columns = explode('.', $column_name);
$columns = array_map(function($str) {
return $str === '*' ? $str : ('`' . $str . '`');
}, $columns);
return implode('.', $columns);
}
/**
* Check if a column name is valid.
*
* @param string $column_name
* @return bool
*/
public static function isValidColumnName(string $column_name): bool
{
return preg_match('/^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/i', $column_name) ? true : false;
}
/**
* Check if a variable is considered valid for XE compatibility.
*
* @param mixed $var
* @return bool
*/
public static function isValidVariable($var): bool
{
if ($var === null || $var === '')
{
return false;
}
if (is_array($var))
{
$count = count($var);
if ($count === 0 || ($count === 1 && reset($var) === ''))
{
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* Table class.
*/
class Table
{
public $name;
public $alias;
public $join_type;
public $join_conditions = array();
}

View file

@ -0,0 +1,393 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* VariableBase class.
*/
class VariableBase
{
/**
* Instance properties.
*/
public $var;
public $default;
/**
* Convert an operator into real SQL.
*
* @param array $args
* @param string $prefix
* @return array
*/
public function getQueryStringAndParams(array $args, string $prefix = ''): array
{
// Return if this method is called on an invalid child class.
if ((!isset($this->column) && !isset($this->name)) || !isset($this->operation))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Invalid invocation of getQueryStringAndParams()');
}
// Initialze the return values.
$where = '';
$params = array();
// Process the variable or default value.
if ($this instanceof Query)
{
$is_expression = true;
$value = '(' . $this->getQueryString($prefix, $args) . ')';
$params = $this->getQueryParams();
}
elseif ($this->var && Query::isValidVariable($args[$this->var]))
{
$this->filterValue($args[$this->var]);
$is_expression = false;
$value = $args[$this->var];
}
elseif ($this->default !== null)
{
list($is_expression, $value) = $this->getDefaultValue();
}
elseif ($this->not_null)
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' is not set');
}
else
{
return [$where, $params];
}
// Quote the column name.
$column = Query::quoteName(isset($this->column) ? $this->column : $this->name);
// Prepare the target value.
$list_ops = array('in' => true, 'notin' => true, 'not_in' => true, 'between' => true);
if (isset($list_ops[$this->operation]) && !$is_expression && !is_array($value) && $value !== '')
{
$value = explode(',', preg_replace('/[\s\']/', '', $value));
}
// Apply the operator.
switch ($this->operation)
{
case 'equal':
$where = sprintf('%s = %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'notequal':
case 'not_equal':
$where = sprintf('%s != %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'more':
case 'gte':
$where = sprintf('%s >= %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'excess':
case 'gt';
$where = sprintf('%s > %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'less':
case 'lte':
$where = sprintf('%s <= %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'below':
case 'lt';
$where = sprintf('%s < %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'regexp';
$where = sprintf('%s REGEXP %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'notregexp';
case 'not_regexp';
$where = sprintf('%s NOT REGEXP %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'like':
$where = sprintf('%s LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value . '%';
break;
case 'like_prefix':
case 'like_head':
$where = sprintf('%s LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value . '%';
break;
case 'like_suffix':
case 'like_tail':
$where = sprintf('%s LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'notlike':
$where = sprintf('%s NOT LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value . '%';
break;
case 'notlike_prefix':
case 'notlike_head':
$where = sprintf('%s NOT LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value . '%';
break;
case 'notlike_suffix':
case 'notlike_tail':
$where = sprintf('%s NOT LIKE %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'and':
$where = sprintf('%s & %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'or':
$where = sprintf('%s | %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'xor':
$where = sprintf('%s ^ %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'not':
$where = sprintf('%s ~ %s', $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = '%' . $value;
break;
case 'null':
$where = sprintf('%s IS NULL', $column);
break;
case 'notnull':
case 'not_null':
$where = sprintf('%s IS NOT NULL', $column);
break;
case 'in':
if ($is_expression)
{
$where = sprintf('%s IN %s', $column, $value);
}
else
{
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s IN (%s)', $column, $placeholders);
foreach ($value as $item)
{
$params[] = $item;
}
}
break;
case 'notin':
case 'not_in':
if ($is_expression)
{
$where = sprintf('%s IN %s', $column, $value);
}
else
{
$count = count($value);
$placeholders = implode(', ', array_fill(0, $count, '?'));
$where = sprintf('%s NOT IN (%s)', $column, $placeholders);
foreach ($value as $item)
{
$params[] = $item;
}
}
break;
case 'between':
$where = sprintf('%s BETWEEN ? AND ?', $column);
foreach ($value as $item)
{
$params[] = $item;
}
break;
case 'notbetween':
case 'not_between':
$where = sprintf('%s NOT BETWEEN ? AND ?', $column);
foreach ($value as $item)
{
$params[] = $item;
}
break;
case 'search':
$keywords = preg_split('/[\s,]+/', $value, 10, \PREG_SPLIT_NO_EMPTY);
$conditions = array();
$placeholders = implode(', ', array_fill(0, count($keywords), '?'));
foreach ($keywords as $item)
{
if (substr($item, 0, 1) === '-')
{
$conditions[] = sprintf('%s NOT LIKE ?', $column);
$item = substr($item, 1);
}
else
{
$conditions[] = sprintf('%s LIKE ?', $column);
}
$params[] = '%' . str_replace(['\\', '_', '%'], ['\\\\', '\_', '\%'], $item) . '%';
}
$conditions = implode(' AND ', $conditions);
$where = count($keywords) === 1 ? $conditions : "($conditions)";
break;
case 'plus':
$where = sprintf('%s = %s + %s', $column, $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'minus':
$where = sprintf('%s = %s - %s', $column, $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
case 'multiply':
$where = sprintf('%s = %s * %s', $column, $column, $is_expression ? $value : '?');
if (!$is_expression) $params[] = $value;
break;
default:
$where = sprintf('%s = ?', $column);
$params[] = $value;
}
// Return the complete condition and parameters.
return [$where, $params];
}
/**
* Get the current value, falling back to the default value if necessary.
*
* @param array $args
* @return array
*/
public function getValue(array $args)
{
if ($this->var && Query::isValidVariable($args[$this->var]))
{
$is_expression = false;
$value = $args[$this->var];
}
elseif ($this->default !== null)
{
list($is_expression, $value) = $this->getDefaultValue();
}
return [$is_expression, $value];
}
/**
* Get the default value of this variable.
*
* @return array
*/
public function getDefaultValue()
{
// If the default value is a column name, escape it.
if (strpos($this->default, '.') !== false && Query::isValidColumnName($this->default))
{
return [true, Query::quoteName($this->default)];
}
elseif (isset($this->column) && preg_match('/_srl$/', $this->column) && !is_numeric($this->default))
{
return [true, Query::quoteName($this->default)];
}
// If the default value is a function shortcut, return an appropriate value.
switch ($this->default)
{
case 'ipaddress()':
return [false, \RX_CLIENT_IP];
case 'unixtime()':
return [false, time()];
case 'curdate()':
case 'datetime()':
return [false, date('YmdHis')];
case 'date()':
return [false, date('Ymd')];
case 'time()':
return [false, date('His')];
case 'member_srl()':
return [false, intval(\Rhymix\Framework\Session::getMemberSrl())];
case 'sequence()':
return [false, getNextSequence()];
}
// If the default value is a calculation based on the current value, return a query string.
if (isset($this->column) && preg_match('/^(plus|minus|multiply)\(([0-9]+)\)$/', $this->default, $matches))
{
switch ($matches[1])
{
case 'plus':
return [true, sprintf('%s + %d', Query::quoteName($this->column), $matches[2])];
case 'minus':
return [true, sprintf('%s - %d', Query::quoteName($this->column), $matches[2])];
case 'multiply':
return [true, sprintf('%s * %d', Query::quoteName($this->column), $matches[2])];
}
}
// Otherwise, just return the literal value.
return [false, $this->default];
}
/**
* Filter a value.
*
* @param mixed $value
* @return void
*/
public function filterValue($value)
{
// Apply filters.
switch (isset($this->filter) ? $this->filter : '')
{
case 'email':
case 'email_address':
if (!preg_match('/^[\w-]+((?:\.|\+|\~)[\w-]+)*@[\w-]+(\.[\w-]+)+$/', $value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain a valid e-mail address');
}
break;
case 'homepage':
case 'url':
if (!preg_match('/^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$/i', $value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain a valid URL');
}
break;
case 'userid':
case 'user_id':
if (!preg_match('/^[a-zA-Z]+([_0-9a-zA-Z]+)*$/', $value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain a valid user ID');
}
break;
case 'number':
case 'numbers':
if (!preg_match('/^(-?)[0-9]+(,\-?[0-9]+)*$/', is_array($value) ? implode(',', $value) : $value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain a valid number');
}
break;
case 'alpha':
if (!ctype_alpha($value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain only alphabets');
}
break;
case 'alnum':
case 'alpha_number':
if (!ctype_alnum($value))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain only alphanumeric characters');
}
break;
}
// Check minimum and maximum lengths.
$length = is_scalar($value) ? iconv_strlen($value, 'UTF-8') : (is_countable($value) ? count($value) : 1);
if (isset($this->minlength) && $this->minlength > 0 && $length < $this->minlength)
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain no less than ' . $this->minlength . ' characters');
}
if (isset($this->maxlength) && $this->maxlength > 0 && $length > $this->maxlength)
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $this->column . ' must contain no more than ' . $this->minlength . ' characters');
}
}
}

View file

@ -0,0 +1,251 @@
<?php
namespace Rhymix\Framework\Parsers;
/**
* DB query parser class for XE compatibility.
*/
class DBQueryParser extends BaseParser
{
/**
* Load a query XML file.
*
* @param string $filename
* @return object|false
*/
public static function loadXML(string $filename)
{
// Load the XML file.
$xml = simplexml_load_string(file_get_contents($filename));
if ($xml === false)
{
return false;
}
// Parse the query.
$query_name = preg_replace('/\.xml$/', '', basename($filename));
$query = self::_parseQuery($xml, $query_name);
return $query;
}
/**
* Parse a query.
*
* @param SimpleXMLElement $xml
* @param string $name
* @return object
*/
protected static function _parseQuery(\SimpleXMLElement $xml, string $name = ''): DBQuery\Query
{
// Load basic information about this query.
$attribs = self::_getAttributes($xml);
$query = new DBQuery\Query;
$query->name = $name ?: null;
$query->type = strtoupper($attribs['action']) ?: 'SELECT';
$query->alias = $attribs['alias'] ?? null;
if ($query->alias && !$query->name)
{
$query->name = $query->alias;
}
// Load attributes that only apply to subqueries in the <conditions> block.
$query->operation = $attribs['operation'] ?? null;
$query->column = preg_replace('/[^a-z0-9_\.]/i', '', $attribs['column']) ?: null;
$query->pipe = strtoupper($attribs['pipe']) ?: 'AND';
// Load tables.
foreach ($xml->tables->table ?: [] as $tag)
{
if (trim($tag['query']) === 'true')
{
$table = self::_parseQuery($tag);
$query->tables[$table->alias] = $table;
}
else
{
$table = new DBQuery\Table;
$table->name = trim($tag['name']);
$table->alias = trim($tag['alias']) ?: $table->name;
}
$table_type = trim($tag['type']);
if (stripos($table_type, 'join') !== false)
{
$table->join_type = strtoupper($table_type);
if ($tag->conditions)
{
$table->join_conditions = self::_parseConditions($tag->conditions);
}
}
$query->tables[$table->alias] = $table;
}
// Load columns.
foreach ($xml->columns->column ?: [] as $tag)
{
if ($tag->getName() === 'query')
{
$subquery = self::_parseQuery($tag, trim($tag['id']));
$query->columns[] = $subquery;
}
elseif ($query->type === 'SELECT')
{
$column = new DBQuery\ColumnRead;
$column->name = trim($tag['name']);
$column->alias = trim($tag['alias']) ?: null;
if ($column->name === '*' || preg_match('/\.\*$/', $column->name))
{
$column->is_wildcard = true;
}
if (!DBQuery\Query::isValidColumnName($column->name))
{
$column->is_expression = true;
}
$query->columns[] = $column;
}
else
{
$attribs = self::_getAttributes($tag);
$column = new DBQuery\ColumnWrite;
$column->name = $attribs['name'];
$column->operation = $attribs['operation'] ?: 'equal';
$column->var = $attribs['var'] ?? null;
$column->default = $attribs['default'] ?? null;
$column->not_null = $attribs['notnull'] ? true : false;
$column->filter = $attribs['filter'] ?? null;
$column->minlength = intval($attribs['minlength'], 10);
$column->maxlength = intval($attribs['maxlength'], 10);
$query->columns[] = $column;
}
}
// Load conditions.
if ($xml->conditions)
{
$query->conditions = self::_parseConditions($xml->conditions);
}
// Load groups.
if ($xml->groups)
{
$query->groupby = new DBQuery\GroupBy;
foreach ($xml->groups->children() as $tag)
{
$name = $tag->getName();
if ($name === 'group')
{
$query->groupby->columns[] = trim($tag['column']);
}
elseif ($name === 'having')
{
$query->groupby->having = self::_parseConditions($tag);
}
}
}
// Load navigation settings.
if ($xml->navigation)
{
$query->navigation = new DBQuery\Navigation;
foreach ($xml->navigation->index ?: [] as $tag)
{
$orderby = new DBQuery\OrderBy;
$orderby->var = trim($tag['var']) ?: null;
$orderby->default = trim($tag['default']) ?: null;
$orderby->order_var = trim($tag['order']) ?: null;
$query->navigation->orderby[] = $orderby;
}
foreach (['list_count', 'page_count', 'page', 'offset'] as $key)
{
if ($tag = $xml->navigation->{$key})
{
$query->navigation->{$key} = new DBQuery\VariableBase;
$query->navigation->{$key}->var = trim($tag['var']) ?: null;
$query->navigation->{$key}->default = trim($tag['default']) ?: null;
}
}
}
// If a SELECT query has no columns, use * by default.
if ($query->type === 'SELECT' && !count($query->columns))
{
$column = new DBQuery\ColumnRead;
$column->name = '*';
$column->is_wildcard = true;
$column->is_expression = true;
$query->columns[] = $column;
}
// Check the SELECT DISTINCT flag.
if ($xml->columns && $select_distinct = trim($xml->columns['distinct']))
{
if ($select_distinct === 'distinct' || toBool($select_distinct))
{
$query->select_distinct = true;
}
}
// Check the ON DUPLICATE KEY UPDATE (upsert) flag.
if ($query->type === 'INSERT' && $update_duplicate = $attribs['updateduplicate'])
{
if (toBool($update_duplicate))
{
$query->update_duplicate = true;
}
}
// Return the complete query definition.
return $query;
}
/**
* Parse conditions.
*
* @param SimpleXMLElement $parent
* @return array
*/
protected static function _parseConditions(\SimpleXMLElement $parent): array
{
$result = array();
foreach ($parent->children() as $tag)
{
$attribs = self::_getAttributes($tag);
$name = $tag->getName();
if ($name === 'condition')
{
$cond = new DBQuery\Condition;
$cond->operation = $attribs['operation'];
$cond->column = $attribs['column'];
if (isset($attribs['var']) && !isset($attribs['default']) && preg_match('/^\w+\.\w+$/', $attribs['var']))
{
$cond->default = $attribs['var'];
}
else
{
$cond->var = $attribs['var'] ?? null;
$cond->default = $attribs['default'] ?? null;
}
$cond->not_null = $attribs['notnull'] ? true : false;
$cond->filter = $attribs['filter'] ?? null;
$cond->minlength = intval($attribs['minlength'], 10);
$cond->maxlength = intval($attribs['maxlength'], 10);
$cond->pipe = strtoupper($attribs['pipe']) ?: 'AND';
$result[] = $cond;
}
elseif ($name === 'group')
{
$group = new DBQuery\ConditionGroup;
$group->conditions = self::_parseConditions($tag);
$group->pipe = strtoupper($attribs['pipe']) ?: 'AND';
$result[] = $group;
}
elseif ($name === 'query')
{
$subquery = self::_parseQuery($tag);
$result[] = $subquery;
}
}
return $result;
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace Rhymix\Framework\Parsers\DBTable;
/**
* Column class.
*/
class Column
{
public $name;
public $type;
public $xetype;
public $size;
public $utf8mb4 = true;
public $default_value;
public $not_null = false;
public $is_indexed = false;
public $is_unique = false;
public $is_primary_key = false;
public $auto_increment = false;
}

View file

@ -0,0 +1,16 @@
<?php
namespace Rhymix\Framework\Parsers\DBTable;
/**
* Constraint class.
*/
class Constraint
{
public $type;
public $column;
public $references;
public $condition;
public $on_delete = 'RESTRICT';
public $on_update = 'RESTRICT';
}

View file

@ -0,0 +1,13 @@
<?php
namespace Rhymix\Framework\Parsers\DBTable;
/**
* Index class.
*/
class Index
{
public $name;
public $columns = array();
public $is_unique = false;
}

View file

@ -0,0 +1,132 @@
<?php
namespace Rhymix\Framework\Parsers\DBTable;
/**
* Table class.
*/
class Table
{
public $name;
public $columns = array();
public $indexes = array();
public $primary_key = array();
public $constraints = array();
/**
* Generate the CREATE TABLE query for this table.
*
* @param string $prefix
* @param string $charset
* @param string $engine
* @return string
*/
public function getCreateQuery(string $prefix = '', string $charset = 'utf8mb4', string $engine = 'innodb'): string
{
// Initialize the query.
$result = 'CREATE TABLE `' . $prefix . $this->name . '` (';
// Add columns.
$columns = array();
$adjusted_sizes = array();
foreach ($this->columns as $column)
{
$columndef = ' `' . $column->name . '`' . ' ' . strtoupper($column->type);
$max_size = $column->utf8mb4 ? 191 : 255;
if (preg_match('/char/i', $column->type) && $column->size > $max_size && ($column->is_unique || $column->is_primary_key))
{
$adjusted_sizes[$column->name] = $max_size;
}
if ($column->size)
{
$columndef .= '(' . (isset($adjusted_sizes[$column->name]) ? $adjusted_sizes[$column->name] : $column->size) . ')';
}
if ($column->utf8mb4 === false && $charset === 'utf8mb4')
{
$columndef .= ' CHARACTER SET utf8 COLLATE utf8_unicode_ci';
}
if ($column->not_null)
{
$columndef .= ' NOT NULL';
}
if ($column->default_value !== null)
{
if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value))
{
$columndef .= ' DEFAULT ' . $column->default_value;
}
else
{
$columndef .= ' DEFAULT \'' . $column->default_value . '\'';
}
}
if ($column->auto_increment)
{
$columndef .= ' AUTO_INCREMENT';
}
$columns[] = $columndef;
}
// Add indexes.
if (count($this->primary_key))
{
$pkcolumns = array_map(function($str) {
return '`' . $str . '`';
}, $this->primary_key);
$pkdef = ' ' . 'PRIMARY KEY (' . implode(', ', $pkcolumns) . ')';
$columns[] = $pkdef;
}
foreach ($this->indexes as $index)
{
$idxcolumns = array();
foreach ($index->columns as $column_name => $prefix_size)
{
$column_info = $this->columns[$column_name];
$current_size = isset($adjusted_sizes[$column_name]) ? $adjusted_sizes[$column_name] : $column_info->size;
$max_size = $column_info->utf8mb4 ? 191 : 255;
if (preg_match('/char/i', $column_info->type) && $current_size > $max_size)
{
$prefix_size = $max_size;
}
$idxcolumns[] = '`' . $column_name . '`' . ($prefix_size > 0 ? "($prefix_size)" : '');
}
$idxtype = ($index->is_unique ? 'UNIQUE' : 'INDEX');
$idxdef = ' ' . $idxtype . ' `' . $index->name . '` (' . implode(', ', $idxcolumns) . ')';
$columns[] = $idxdef;
}
// Add constraints.
foreach ($this->constraints as $constraint)
{
$contype = strtoupper($constraint->type);
if ($contype === 'FOREIGN KEY')
{
$condef = ' ' . $contype . ' (`' . $constraint->column . '`)';
list($reftable, $refcolumn) = explode('.', $constraint->references);
$condef .= ' REFERENCES `' . $prefix . $reftable . '` (`' . $refcolumn . '`)';
$condef .= ' ON DELETE ' . strtoupper($constraint->on_delete);
$condef .= ' ON UPDATE ' . strtoupper($constraint->on_update);
}
if ($contype === 'CHECK')
{
$condef = ' ' . $contype . ' (' . $constraint->condition . ')';
}
$columns[] = $condef;
}
// Finish the query.
$footer = '';
if ($engine)
{
$footer .= ' ENGINE = ' . (strtolower($engine) === 'innodb' ? 'InnoDB' : 'MyISAM');
}
if ($charset)
{
$footer .= ' CHARACTER SET ' . $charset . ' COLLATE ' . $charset . '_unicode_ci';
}
$result .= "\n" . implode(",\n", $columns);
$result .= "\n" . ') ' . $footer . ';';
return $result;
}
}

View file

@ -0,0 +1,249 @@
<?php
namespace Rhymix\Framework\Parsers;
/**
* DB table parser class for XE compatibility.
*/
class DBTableParser extends BaseParser
{
/**
* Mapping for XE-compatible types.
*/
protected static $_xe_types = array(
'bignumber' => 'bigint',
'number' => 'bigint',
'bigtext' => 'longtext',
'date' => 'char(14)',
);
/**
* List of types for which the size attribute will be ignored.
*/
protected static $_nosize_types = array(
'bigint' => true,
'int' => true,
'integer' => true,
);
/**
* Load a table definition XML file.
*
* @param string $filename
* @param string $content
* @return object|false
*/
public static function loadXML(string $filename = '', string $content = '')
{
// Load the XML content.
if ($content)
{
$xml = simplexml_load_string($content);
}
else
{
$xml = simplexml_load_string(file_get_contents($filename));
}
if ($xml === false)
{
return false;
}
// Initialize table definition.
$table = new DBTable\Table;
if ($filename)
{
$table->name = preg_replace('/\.xml$/', '', basename($filename));
}
else
{
$table->name = strval($xml['name']);
}
// Load columns.
foreach ($xml->column as $column_info)
{
// Get the column name and type.
$column = new DBTable\Column;
$column->name = strval($column_info['name']);
list($column->type, $column->xetype, $column->size) = self::getTypeAndSize(strval($column_info['type']), strval($column_info['size']));
// Get all attributes.
$attribs = self::_getAttributes($column_info);
// Get the utf8mb4 attribute.
if (isset($attribs['utf8mb4']))
{
$column->utf8mb4 = toBool($attribs['utf8mb4']);
}
// Get the default value.
if (isset($attribs['default']))
{
$column->default_value = $attribs['default'];
}
// Get the NOT NULL attribute.
if (isset($attribs['notnull']))
{
$column->not_null = true;
}
// Get index information.
if (isset($attribs['index']))
{
$index_name = $attribs['index'];
if (!isset($table->indexes[$index_name]))
{
$table->indexes[$index_name] = new DBTable\Index;
$table->indexes[$index_name]->name = $index_name;
}
$table->indexes[$index_name]->columns[$column->name] = 0;
$column->is_indexed = true;
}
if (isset($attribs['unique']))
{
$index_name = $attribs['unique'];
if (!isset($table->indexes[$index_name]))
{
$table->indexes[$index_name] = new DBTable\Index;
$table->indexes[$index_name]->name = $index_name;
$table->indexes[$index_name]->is_unique = true;
}
$table->indexes[$index_name]->columns[$column->name] = 0;
$column->is_indexed = true;
$column->is_unique = true;
}
// Get primary key information.
if (isset($attribs['primarykey']) && toBool($attribs['primarykey']))
{
$table->primary_key[] = $column->name;
$column->is_indexed = true;
$column->is_unique = true;
$column->is_primary_key = true;
}
// Get auto-increment information.
if (isset($attribs['autoincrement']) && toBool($attribs['autoincrement']))
{
$column->auto_increment = true;
}
// Add the column to the table definition.
$table->columns[$column->name] = $column;
}
// Load indexes.
foreach ($xml->index as $index_info)
{
$index_info = self::_getAttributes($index_info);
$index = new DBTable\Index;
$index->name = $index_info['name'];
$idxcolumns = array_map('trim', explode(',', $index_info['columns'] ?? $index_info['column']));
foreach ($idxcolumns as $idxcolumn)
{
if (preg_match('/^(\S+)\s*\(([0-9]+)\)$/', $idxcolumn, $matches))
{
$index->columns[$matches[1]] = intval($matches[2]);
$idxcolumn = $matches[1];
}
else
{
$index->columns[$idxcolumn] = 0;
}
}
$index->is_unique = toBool($index_info['unique'] ?? '');
if (isset($table->columns[$idxcolumn]) && is_object($table->columns[$idxcolumn]))
{
$table->columns[$idxcolumn]->is_indexed = true;
$table->columns[$idxcolumn]->is_unique = $index->is_unique;
}
$table->indexes[$index->name] = $index;
}
// Load other constraints (foreign keys).
foreach ($xml->constraint as $const_info)
{
$const_info = self::_getAttributes($const_info);
$constraint = new DBTable\Constraint;
$constraint->type = strtoupper($const_info['type']);
$constraint->column = $const_info['column'] ?: null;
$constraint->references = $const_info['references'] ?: null;
$constraint->condition = $const_info['condition'] ?: null;
$constraint->on_delete = $const_info['ondelete'] ?: $constraint->on_delete;
$constraint->on_update = $const_info['onupdate'] ?: $constraint->on_update;
$table->constraints[] = $constraint;
}
// Return the complete table definition.
return $table;
}
/**
* Get column type and size.
*
* @param string $type
* @param string $size
* @return array
*/
public static function getTypeAndSize(string $type, string $size): array
{
// Map XE-compatible types to database native types.
if (isset(self::$_xe_types[$type]))
{
$xetype = $type;
$type = self::$_xe_types[$type];
}
else
{
$xetype = $type;
}
// Extract and normalize the size.
if (preg_match('/^([a-z0-9_]+)\(([0-9,\s]+)\)$/i', $type, $matches))
{
$type = $matches[1];
$size = $matches[2];
}
$size = implode(',', array_map('trim', explode(',', $size))) ?: null;
if (isset(self::$_nosize_types[$type]))
{
$size = null;
}
// Return a complete array.
return [$type, $xetype, $size];
}
/**
* Get the XE-compatible type from a real database type.
*
* @param string $type
* @param string $size
* @return string
*/
public static function getXEType(string $type, string $size): string
{
$type = strtolower($type);
switch ($type)
{
case 'bigint':
return 'bignumber';
case 'int':
case 'integer':
return 'number';
case 'longtext':
return 'bigtext';
case 'char':
case 'varchar':
if ($size == 14)
{
return 'date';
}
default:
return $type;
}
}
}

View file

@ -78,12 +78,16 @@ class ModuleInfoParser extends BaseParser
}
// Add information about actions.
$action_info = ModuleActionParser::loadXML(strtr($filename, ['info.xml' => 'module.xml']));
$info->admin_index_act = $action_info->admin_index_act;
$info->default_index_act = $action_info->default_index_act;
$info->setup_index_act = $action_info->setup_index_act;
$info->simple_setup_index_act = $action_info->simple_setup_index_act;
$info->error_handlers = $action_info->error_handlers ?: [];
$action_filename = strtr($filename, ['info.xml' => 'module.xml']);
if (file_exists($action_filename))
{
$action_info = ModuleActionParser::loadXML($action_filename);
$info->admin_index_act = $action_info->admin_index_act;
$info->default_index_act = $action_info->default_index_act;
$info->setup_index_act = $action_info->setup_index_act;
$info->simple_setup_index_act = $action_info->simple_setup_index_act;
$info->error_handlers = $action_info->error_handlers ?: [];
}
// Return the complete result.
return $info;

View file

@ -134,35 +134,30 @@ function getClass($module_name)
*
* @see DB::executeQuery()
* @param string $query_id (module name.query XML file)
* @param object $args values of args object
* @param string[] $arg_columns Column list
* @param array|object $args Arguments
* @param array $column_list Column list
* @param string $result_type 'auto', 'array' or 'raw'
* @return object Query result data
*/
function executeQuery($query_id, $args = NULL, $arg_columns = NULL)
function executeQuery($query_id, $args = [], $column_list = [], $result_type = 'auto')
{
$oDB = DB::getInstance();
return $oDB->executeQuery($query_id, $args, $arg_columns);
$oDB = Rhymix\Framework\DB::getInstance();
return $oDB->executeQuery($query_id, $args, $column_list, $result_type);
}
/**
* Function to handle the result of DB::executeQuery() as an array
*
* @see DB::executeQuery()
* @see executeQuery()
* @param string $query_id (module name.query XML file)
* @param object $args values of args object
* @param string[] $arg_columns Column list
* @param array|object $args Arguments
* @param array $column_list Column list
* @return object Query result data
*/
function executeQueryArray($query_id, $args = NULL, $arg_columns = NULL)
function executeQueryArray($query_id, $args = [], $column_list = [])
{
$oDB = DB::getInstance();
$output = $oDB->executeQuery($query_id, $args, $arg_columns);
if(isset($output->data) && !is_array($output->data) && countobj($output->data) > 0)
{
$output->data = array($output->data);
}
return $output;
$oDB = Rhymix\Framework\DB::getInstance();
return $oDB->executeQuery($query_id, $args, $column_list, 'array');
}
/**
@ -173,8 +168,7 @@ function executeQueryArray($query_id, $args = NULL, $arg_columns = NULL)
*/
function getNextSequence()
{
$oDB = DB::getInstance();
$seq = $oDB->getNextSequence();
$seq = Rhymix\Framework\DB::getInstance()->getNextSequence();
setUserSequence($seq);
return $seq;
}

View file

@ -797,7 +797,7 @@ class adminAdminView extends admin
// System settings
$info[] = '[System Settings]';
$info['db.type'] = config('db.master.type');
$info['db.type'] = preg_replace('/^mysql.+/', 'mysql', config('db.master.type'));
$db_extra_info = array();
if (config('db.master.engine')) $db_extra_info[] = config('db.master.engine');
if (config('db.master.charset')) $db_extra_info[] = config('db.master.charset');
@ -805,24 +805,27 @@ class adminAdminView extends admin
{
$info['db.type'] .= ' (' . implode(', ', $db_extra_info) . ')';
}
$info['db.version'] = DB::getInstance()->db_version;
$info['db.version'] = Rhymix\Framework\DB::getInstance()->db_version;
if (preg_match('/\d+\.\d+\.\d+-MariaDB.*$/', $info['db.version'], $matches))
{
$info['db.version'] = $matches[0];
}
$info['cache.type'] = config('cache.type') ?: 'none';
$info['file.folder_structure'] = config('file.folder_structure');
$info['file.umask'] = config('file.umask');
$info['url.rewrite'] = Rhymix\Framework\Router::getRewriteLevel();
$info['locale.default_lang'] = config('locale.default_lang');
$info['locale.default_timezone'] = config('locale.default_timezone');
$info['locale.internal_timezone'] = config('locale.internal_timezone');
$info['mobile.enabled'] = config('mobile.enabled') ? 'true' : 'false';
$info['mobile.tablets'] = config('mobile.tablets') ? 'true' : 'false';
$info['session.delay'] = config('session.delay') ? 'true' : 'false';
$info['session.use_db'] = config('session.use_db') ? 'true' : 'false';
$info['session.use_keys'] = config('session.use_keys') ? 'true' : 'false';
$info['session.use_ssl'] = config('session.use_ssl') ? 'true' : 'false';
$info['session.use_ssl_cookies'] = config('session.use_ssl_cookies') ? 'true' : 'false';
$info['view.concat_scripts'] = config('view.concat_scripts');
$info['view.minify_scripts'] = config('view.minify_scripts');
$info['use_rewrite'] = config('use_rewrite') ? 'true' : 'false';
$info['use_sso'] = config('use_sso') ? 'true' : 'false';
$info[] = '';

View file

@ -40,7 +40,7 @@ class installController extends install
'user' => $config->db_user,
'pass' => $config->db_pass,
'database' => $config->db_database,
'prefix' => rtrim($config->db_prefix, '_') . '_',
'prefix' => $config->db_prefix ? (rtrim($config->db_prefix, '_') . '_') : '',
));
// Check connection to the DB.
@ -107,7 +107,7 @@ class installController extends install
if ($install_config)
{
$install_config = (array)$install_config;
$config['db']['master']['type'] = str_replace('_innodb', '', $install_config['db_type']);
$config['db']['master']['type'] = 'mysql';
$config['db']['master']['host'] = $install_config['db_hostname'];
$config['db']['master']['port'] = $install_config['db_port'];
$config['db']['master']['user'] = $install_config['db_userid'];
@ -115,7 +115,7 @@ class installController extends install
$config['db']['master']['database'] = $install_config['db_database'];
$config['db']['master']['prefix'] = $install_config['db_table_prefix'];
$config['db']['master']['charset'] = $install_config['db_charset'];
$config['db']['master']['engine'] = strpos($install_config['db_type'], 'innodb') !== false ? 'innodb' : (strpos($install_config['db_type'], 'mysql') !== false ? 'myisam' : null);
$config['db']['master']['engine'] = strpos($install_config['db_type'], 'innodb') !== false ? 'innodb' : 'myisam';
$config['use_rewrite'] = $install_config['use_rewrite'] === 'Y' ? true : false;
$config['url']['ssl'] = $install_config['use_ssl'] ?: 'none';
$time_zone = $install_config['time_zone'];
@ -127,7 +127,7 @@ class installController extends install
}
else
{
$config['db']['master']['type'] = str_replace('_innodb', '', $_SESSION['db_config']->db_type);
$config['db']['master']['type'] = 'mysql';
$config['db']['master']['host'] = $_SESSION['db_config']->db_host;
$config['db']['master']['port'] = $_SESSION['db_config']->db_port;
$config['db']['master']['user'] = $_SESSION['db_config']->db_user;
@ -135,7 +135,7 @@ class installController extends install
$config['db']['master']['database'] = $_SESSION['db_config']->db_database;
$config['db']['master']['prefix'] = $_SESSION['db_config']->db_prefix;
$config['db']['master']['charset'] = $_SESSION['db_config']->db_charset;
$config['db']['master']['engine'] = strpos($_SESSION['db_config']->db_type, 'innodb') !== false ? 'innodb' : (strpos($_SESSION['db_config']->db_type, 'mysql') !== false ? 'myisam' : null);
$config['db']['master']['engine'] = strpos($_SESSION['db_config']->db_type, 'innodb') !== false ? 'innodb' : 'myisam';
$config['use_rewrite'] = $_SESSION['use_rewrite'] === 'Y' ? true : false;
$config['url']['ssl'] = Context::get('use_ssl') ?: 'none';
$time_zone = Context::get('time_zone');
@ -227,6 +227,7 @@ class installController extends install
catch(Exception $e)
{
$oDB->rollback();
var_dump($e);exit;
throw new Rhymix\Framework\Exception($e->getMessage());
}
@ -243,7 +244,6 @@ class installController extends install
}
// Apply site lock.
if (Context::get('use_sitelock') === 'Y')
{
$user_ip_range = getView('install')->detectUserIPRange();
@ -286,7 +286,7 @@ class installController extends install
}
// Check DB
if(DB::getEnableList())
if(extension_loaded('pdo_mysql'))
{
$checklist['db_support'] = true;
}
@ -523,10 +523,12 @@ class installController extends install
{
$file = trim($schema_files[$i]);
if(!$file || substr($file,-4)!='.xml') continue;
$table_name = substr(basename($file), 0, -4);
if($oDB->isTableExists($table_name)) continue;
$output = $oDB->createTableByXmlFile($file);
if($output === false)
{
throw new Exception(lang('msg_create_table_failed') . ': ' . $oDB->getError()->getMessage());
throw new Exception(lang('msg_create_table_failed') . ': ' . basename($file) . ': ' . $oDB->getError()->getMessage());
}
}
// Create a table and module instance and then execute install() method

View file

@ -101,21 +101,7 @@ class installView extends install
Context::set('use_rewrite', $_SESSION['use_rewrite'] = 'Y');
}
$defaultDatabase = 'mysqli';
$disableList = DB::getDisableList();
if(is_array($disableList))
{
foreach($disableList as $key => $value)
{
if($value->db_type == $defaultDatabase)
{
$defaultDatabase = 'mysql';
break;
}
}
}
Context::set('defaultDatabase', $defaultDatabase);
Context::set('error_return_url', getNotEncodedUrl('', 'act', Context::get('act'), 'db_type', Context::get('db_type')));
Context::set('error_return_url', getNotEncodedUrl('', 'act', Context::get('act')));
$this->setTemplateFile('db_config');
}

View file

@ -46,10 +46,6 @@ $lang->cmd_install_refresh_page = 'Refresh';
$lang->cmd_install_next = 'Continue installation';
$lang->cmd_ignore = 'Ignore';
$lang->cmd_recommended = 'Recommended';
$lang->db_desc['mysqli'] = 'Use MySQL or MariaDB. Rhymix will automatically use InnoDB if it is supported.';
$lang->db_desc['mysql'] = 'Use MySQL or MariaDB. Rhymix will automatically use InnoDB if it is supported.';
$lang->db_desc['cubrid'] = 'CUBRID is not supported.';
$lang->db_desc['mssql'] = 'Microsoft SQL Server is not supported.';
$lang->can_use_when_installed = 'Not installed on this server';
$lang->form_title = 'Database &amp; Administrator Information';
$lang->db_title = 'Please input DB information';

View file

@ -24,10 +24,6 @@ $lang->install_permission_denied = 'La atribución de la ruta de instalacion no
$lang->cmd_install_refresh_page = 'Refrescar';
$lang->cmd_install_next = 'Continuar la instalación';
$lang->cmd_recommended = 'Recomendado';
$lang->db_desc['mysqli'] = 'Utilizando MySQL o MariaDB. Rhymix automáticamente usará InnoDB si es compatible.';
$lang->db_desc['mysql'] = 'Utilizando MySQL o MariaDB. Rhymix automáticamente usará InnoDB si es compatible.';
$lang->db_desc['cubrid'] = 'CUBRID no es compatible.';
$lang->db_desc['mssql'] = 'Microsoft SQL Server no es compatible.';
$lang->form_title = 'Ingresar BD &amp; Información del Administrador;';
$lang->db_title = 'Por favor escribir información de BD';
$lang->db_type = 'Tipo de BD';

View file

@ -24,10 +24,6 @@ $lang->install_permission_denied = 'La permission du chemin d\'installation n\'e
$lang->cmd_install_refresh_page = 'Rafraîchir';
$lang->cmd_install_next = 'Continuer à installer';
$lang->cmd_recommended = 'Recommandé';
$lang->db_desc['mysqli'] = 'Utilisera MySQL ou MariaDB. Rhymix utilisera automatiquement InnoDB s\'il est pris en charge.';
$lang->db_desc['mysql'] = 'Utilisera MySQL ou MariaDB. Rhymix utilisera automatiquement InnoDB s\'il est pris en charge.';
$lang->db_desc['cubrid'] = 'CUBRID n\'est pas compatible avec Rhymix.';
$lang->db_desc['mssql'] = 'Microsoft SQL Server n\'est pas compatible avec Rhymix.';
$lang->can_use_when_installed = 'Pas installé sur ce serveur';
$lang->form_title = 'Entrer des informations de Base de données et Administrateur';
$lang->db_title = 'Entrez l\'information de Base de Données, S.V.P.';

View file

@ -45,10 +45,6 @@ $lang->cmd_install_refresh_page = 'リフレッシュ';
$lang->cmd_install_next = 'インストールを続けます。';
$lang->cmd_ignore = 'FTP設定を省略する';
$lang->cmd_recommended = '推奨';
$lang->db_desc['mysqli'] = 'MySQLやMariaDBを利用します。InnoDBサポート時に自動的に使用されます。';
$lang->db_desc['mysql'] = 'MySQLやMariaDBを利用します。InnoDBサポート時に自動的に使用されます。';
$lang->db_desc['cubrid'] = 'CUBRIDはサポートしていません。';
$lang->db_desc['mssql'] = 'Microsoft SQL Serverはサポートしていません。';
$lang->can_use_when_installed = 'このサーバーにインストールされていません';
$lang->form_title = 'データベース &amp; 管理者情報入力';
$lang->db_title = 'データベース情報入力';

View file

@ -46,10 +46,6 @@ $lang->cmd_install_refresh_page = '새로고침';
$lang->cmd_install_next = '설치를 진행합니다.';
$lang->cmd_ignore = '무시';
$lang->cmd_recommended = '권장';
$lang->db_desc['mysqli'] = 'MySQL 또는 MariaDB를 이용합니다. InnoDB 지원시 자동으로 사용합니다.';
$lang->db_desc['mysql'] = 'MySQL 또는 MariaDB를 이용합니다. InnoDB 지원시 자동으로 사용합니다.';
$lang->db_desc['cubrid'] = 'CUBRID는 지원하지 않습니다.';
$lang->db_desc['mssql'] = 'Microsoft SQL Server는 지원하지 않습니다.';
$lang->can_use_when_installed = '설치되어 있지 않음';
$lang->form_title = 'DB &amp; 관리자 정보 입력';
$lang->db_title = 'DB 정보 입력';

View file

@ -24,10 +24,6 @@ $lang->install_permission_denied = 'Права доступа пути не ус
$lang->cmd_install_refresh_page = 'обновление';
$lang->cmd_install_next = 'Продолжить установку';
$lang->cmd_recommended = 'рекомендуемые';
$lang->db_desc['mysqli'] = 'Используйте MySQL или MariaDB. Rhymix будет автоматически использовать InnoDB, если он поддерживается.';
$lang->db_desc['mysql'] = 'Используйте MySQL или MariaDB. Rhymix будет автоматически использовать InnoDB, если он поддерживается.';
$lang->db_desc['cubrid'] = 'CUBRID не совместим с Rhymix.';
$lang->db_desc['mssql'] = 'Microsoft SQL Server не совместим с Rhymix.';
$lang->form_title = 'Пожалуйста, введите дазу данных &amp; Административная Информация';
$lang->db_title = 'Пожалуйста, введите информацию базы данных';
$lang->db_type = 'Тип базы данных';

View file

@ -25,10 +25,6 @@ $lang->cmd_install_refresh_page = 'Gerekli koşulları tamamladım.';
$lang->cmd_install_next = 'Kuruluma Devam Et';
$lang->cmd_ignore = 'Önemseme';
$lang->cmd_recommended = 'Tavsiye edilen';
$lang->db_desc['mysqli'] = 'PHP\'de mysqli_*() özellikleri için MySQL\'ü veritabanı olarak kullanınız.';
$lang->db_desc['mysql'] = 'PHP\'de mysql_*() özellikleri için MySQL\'ü veritabanı olarak kullanınız.';
$lang->db_desc['cubrid'] = 'CUBRID\'ü veritabanı olarak kullanın. Daha fazla bilgi için <a href="https://www.cubrid.org/documentation/manuals" target="_blank">Manuel</a>i inceleyiniz';
$lang->db_desc['mssql'] = 'Microsoft SQL Server\'ü veritabanı olarak kullanın';
$lang->form_title = 'Veritabanı &amp; Yönetici Bilgisi';
$lang->db_title = 'Lütfen Veritabanı bilgisini giriniz';
$lang->db_type = 'Veritabanı Tipi';

View file

@ -20,9 +20,6 @@ $lang->cmd_install_refresh_page = 'Tôi đã thay đổi để phù hợp với
$lang->cmd_install_next = 'Tiếp tục cài đặt';
$lang->cmd_ignore = 'Bỏ qua';
$lang->cmd_recommended = 'Đê';
$lang->db_desc['mysqli'] = 'Dùng chức năng <b>mysqli_*()</b> để sử dụng MySql Database.';
$lang->db_desc['mysql'] = 'Dùng chức năng <b>mysql_*()</b> để sử dụng MySql Database.';
$lang->db_desc['cubrid'] = 'Sử dụng <b>CUBRID</b> Database. <a href="https://www.cubrid.org/documentation/manuals" target="_blank">Hướng dẫn</a>';
$lang->form_title = 'Hãy nhập thông tin Database và thông tin Administrator';
$lang->db_title = 'Xin hãy nhập thông tin Database';
$lang->db_type = 'Định dạng Database';

View file

@ -33,10 +33,6 @@ $lang->cmd_install_refresh_page = '刷新屏幕';
$lang->cmd_install_next = '开始安装';
$lang->cmd_ignore = '忽略';
$lang->cmd_recommended = '推荐';
$lang->db_desc['mysqli'] = '使用MySQL或MariaDB。 如果支持Rhymix将自动使用InnoDB。';
$lang->db_desc['mysql'] = '使用MySQL或MariaDB。 如果支持Rhymix将自动使用InnoDB。';
$lang->db_desc['cubrid'] = '不支持CUBRID。';
$lang->db_desc['mssql'] = '不支持Microsoft SQL Server。';
$lang->can_use_when_installed = '不是这个服务器上安装';
$lang->form_title = '数据库及管理员基本信息';
$lang->db_title = '输入数据库信息';

View file

@ -33,10 +33,6 @@ $lang->cmd_install_refresh_page = '刷新屏幕';
$lang->cmd_install_next = '開始進行安裝';
$lang->cmd_ignore = '忽略';
$lang->cmd_recommended = '推薦';
$lang->db_desc['mysqli'] = '使用MySQL或MariaDB。 如果支持Rhymix將自動使用InnoDB。';
$lang->db_desc['mysql'] = '使用MySQL或MariaDB。 如果支持Rhymix將自動使用InnoDB。';
$lang->db_desc['cubrid'] = '不支持CUBRID。';
$lang->db_desc['mssql'] = '不支持Microsoft SQL Server。';
$lang->can_use_when_installed = '不是這個服務器上安裝';
$lang->form_title = '輸入資料庫及管理員資訊';
$lang->db_title = '輸入資料庫資訊';

View file

@ -9,23 +9,7 @@
<input type="hidden" value="{$error_return_url}" name="error_return_url">
<input type="hidden" name="module" value="{$module}" />
<input type="hidden" name="act" value="procDBConfig" />
<div class="x_control-group">
<label for="db_type" class="x_control-label">{$lang->db_type}</label>
<div class="x_controls">
<select id="db_type" name="db_type">
<block loop="DB::getEnableList() => $key,$val">
<option value="{$val->db_type}" selected="selected"|cond="$val->db_type==$defaultDatabase" />
{$val->db_type}
<block cond="$val->db_type == $defaultDatabase">({$lang->cmd_recommended})</block>
</option>
</block>
<block loop="DB::getDisableList() => $key,$val">
<option value="{$val->db_type}" disabled="disabled" />{$val->db_type} ({$lang->can_use_when_installed})</option>
</block>
</select>
</div>
</div>
<p loop="DB::getEnableList() => $key,$val" class="install_help db_type db_type_{$val->db_type}">{$lang->db_desc[$val->db_type]}</p>
<input type="hidden" name="db_type" value="mysql" />
<div class="x_control-group">
<label for="db_host" class="x_control-label">{$lang->db_hostname}</label>
<div class="x_controls"><input name="db_host" value="localhost" type="text" id="db_host" required /></div>
@ -48,7 +32,7 @@
</div>
<div class="x_control-group">
<label for="db_prefix" class="x_control-label">{$lang->db_table_prefix}</label>
<div class="x_controls"><input name="db_prefix" type="text" id="db_prefix" value="rx" required /></div>
<div class="x_controls"><input name="db_prefix" type="text" id="db_prefix" value="rx_" /></div>
</div>
<p class="install_help">
{$lang->db_info_desc}<br />{$lang->db_prefix_desc}

View file

@ -1,11 +1,5 @@
jQuery(function($){
$('.focus').focus();
if($("#db_type").size()) {
$("#db_type").click(function() {
$("p.db_type").hide();
$("p.db_type_" + $(this).val()).show();
}).triggerHandler("click");
}
if($("#mod_rewrite_checking").size()) {
var checking = $("#mod_rewrite_checking");
$.ajax({

View file

@ -11,7 +11,7 @@ $dsn = $db_config['dsn'];
$dsn = preg_split('/[;:]/', $dsn);
$db_type = array_shift($dsn);
$dbinfo = [
'type' => (($db_type === 'mysql') ? 'mysqli' : $db_type),
'type' => $db_type,
'user' => $db_config['user'],
'password' => $db_config['password'],
'port' => ((isset($db_config['port']) && $db_config['port'])?: 3306),

View file

@ -44,10 +44,10 @@ $I->click('#task-checklist-confirm');
// Step 3 : DB Setup
$I->seeInCurrentUrl('act=dispInstallDBConfig');
$I->seeElement('select[name="db_type"]');
$I->seeElement('input[name="db_host"]');
$I->submitForm('#body', [
'act' => 'procDBConfig',
'db_type' => 'mysqli',
'db_type' => 'mysql',
'db_host' => $dbinfo['host'],
'db_port' => $dbinfo['port'],
'db_user' => $dbinfo['user'],

View file

@ -1,973 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
/** @file
vi: ts=4
Extends XE db classes to allow parsing methods to work in the absence of
a real db connection for the db type.
Included by XML Query/Schema Language validator
*/
/**
@brief
@developer
*/
class DBMysqlConnectWrapper extends DBMysql
{
public $queries = '';
/**
@brief
@developer
@return
@access
*/
public function __construct()
{
$this->db_type = 'mysql';
$this->_setDBInfo(); // Context::get() should indicate a mysql db
}
/**
@brief
@developer
@return
@access
*/
public function create()
{
return new DBMysqlConnectWrapper();
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassStart()
{
}
/**
@brief
@developer
@return
@access
@param $query
*/
public function actStart($query)
{
}
/**
@brief
@developer
@return
@access
*/
public function actFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function isSupported()
{
// No need to actually check for 'mysql_connect' function
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function __connect($connection)
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _afterConnect($connection)
{
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _close($connection)
{
}
/**
@brief
@developer
@return
@access
@param $type
@param $indx
*/
public function close($type = 'master', $indx = NULL)
{
}
/**
@brief
@developer
@return
@access
*/
public function _begin()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _rollback()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _commit()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $query
@param $connection
*/
public function __query($query, $connection)
{
$this->queries .= "\n" . $query;
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $result
@param $arrayIndexEndValue
*/
public function _fetch($result, $arrayIndexEndValue = NULL)
{
return new Any_prop_obj_base();
}
/**
@brief
@developer
@return
@access
@param $target_name
*/
public function isTableExists($target_name)
{
parent::isTableExists($target_name);
return FALSE;
}
/**
@brief
@developer
@return
@access
*/
public function db_insert_id()
{
return NULL;
}
/**
@brief
@developer
@return
@access
@param $result
*/
public function db_fetch_object(&$result)
{
return new Any_prop_obj_base();
}
}
/**
@brief
@developer
*/
class DBMysqliConnectWrapper extends DBMysqli
{
public $queries = '';
/**
@brief
@developer
@return
@access
*/
public function __construct()
{
$this->db_type = 'mysqli';
$this->_setDBInfo(); // Context::get() should indicate a mysqli db
}
/**
@brief
@developer
@return
@access
*/
public function create()
{
return new DBMysqlConnectWrapper();
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassStart()
{
}
/**
@brief
@developer
@return
@access
@param $query
*/
public function actStart($query)
{
}
/**
@brief
@developer
@return
@access
*/
public function actFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function isSupported()
{
// No need to actually check for 'mysql_connect' function
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $target_name
*/
public function isTableExists($target_name)
{
parent::isTableExists($target_name);
return FALSE;
}
// use old mysql escape function, since the mysqli one uses
// the connection resource (to get the current character set)
/**
@brief
@developer
@return
@access
@param $string
*/
public function addQuotes($string)
{
if(version_compare(PHP_VERSION, "5.4.0", "<") && get_magic_quotes_gpc())
{
$string = stripslashes(str_replace("\\", "\\\\", $string));
}
if(!is_numeric($string))
{
$string = @mysql_real_escape_string($string);
}
return $string;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function __connect($connection)
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _afterConnect($connection)
{
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _close($connection)
{
}
/**
@brief
@developer
@return
@access
@param $type
@param $indx
*/
public function close($type = 'master', $indx = NULL)
{
}
/**
@brief
@developer
@return
@access
*/
public function _begin()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _rollback()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _commit()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $query
@param $connection
*/
public function __query($query, $connection)
{
$this->queries .= "\n" . $query;
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $result
@param $arrayIndexEndValue
*/
public function _fetch($result, $arrayIndexEndValue = NULL)
{
return new Any_prop_obj_base();
}
/**
@brief
@developer
@return
@access
*/
public function db_insert_id()
{
return NULL;
}
/**
@brief
@developer
@return
@access
@param $result
*/
public function db_fetch_object(&$result)
{
return new Any_prop_obj_base();
}
}
/**
@brief
@developer
*/
class DBCubridConnectWrapper extends DBCubrid
{
public $queries = '';
/**
@brief
@developer
@return
@access
*/
public function __construct()
{
$this->db_type = 'cubrid';
$this->_setDBInfo(); // Context::get() should indicate a CUBRID db
}
/**
@brief
@developer
@return
@access
*/
public function create()
{
return new DBMysqlConnectWrapper();
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassStart()
{
}
/**
@brief
@developer
@return
@access
@param $query
*/
public function actStart($query)
{
}
/**
@brief
@developer
@return
@access
*/
public function _makeSequence()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function actFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function isSupported()
{
// No need to actually check for 'cubrid_connect' function
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $target_name
*/
public function isTableExists($target_name)
{
try
{
parent::isTableExists($target_name);
}
catch (Exception $ex)
{
}
return FALSE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function __connect($connection)
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _afterConnect($connection)
{
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _close($connection)
{
}
/**
@brief
@developer
@return
@access
@param $type
@param $indx
*/
public function close($type = 'master', $indx = NULL)
{
}
/**
@brief
@developer
@return
@access
*/
public function _begin()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _rollback()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _commit()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $query
@param $connection
*/
public function __query($query, $connection)
{
$this->queries .= "\n" . $query;
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $result
@param $arrayIndexEndValue
*/
public function _fetch($result, $arrayIndexEndValue = NULL)
{
return new Any_prop_obj_base();
}
/**
@brief
@developer
@return
@access
*/
public function db_insert_id()
{
return NULL;
}
/**
@brief
@developer
@return
@access
*/
public function &db_fetch_object()
{
return new Any_prop_obj_base();
}
}
/**
@brief
@developer
*/
class DBMssqlConnectWrapper extends DBMssql
{
public $queries = '';
/**
@brief
@developer
@return
@access
*/
public function __construct()
{
$this->db_type = 'mssql';
$this->_setDBInfo(); // Context::get() should indicate a MS Sql db
}
/**
@brief
@developer
@return
@access
*/
public function create()
{
return new DBMssqlConnectWrapper();
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassStart()
{
}
/**
@brief
@developer
@return
@access
@param $query
*/
public function actStart($query)
{
}
/**
@brief
@developer
@return
@access
*/
public function actFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function actDBClassFinish()
{
}
/**
@brief
@developer
@return
@access
*/
public function isSupported()
{
// No need to actually check for 'mssql_connect' function
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $target_name
*/
public function isTableExists($target_name)
{
parent::isTableExists($target_name);
return FALSE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function __connect($connection)
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _afterConnect($connection)
{
}
/**
@brief
@developer
@return
@access
@param $connection
*/
public function _close($connection)
{
}
/**
@brief
@developer
@return
@access
@param $type
@param $indx
*/
public function close($type = 'master', $indx = NULL)
{
}
/**
@brief
@developer
@return
@access
*/
public function _begin()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _rollback()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
*/
public function _commit()
{
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $query
@param $connection
*/
public function __query($query, $connection)
{
if($this->queries)
{
$this->queries .= ";\n";
}
$this->queries .= $query;
return TRUE;
}
/**
@brief
@developer
@return
@access
@param $result
@param $arrayIndexEndValue
*/
public function _fetch($result, $arrayIndexEndValue = NULL)
{
return new Any_prop_obj_base();
}
/**
@brief
@developer
@return
@access
*/
public function db_insert_id()
{
return NULL;
}
/**
@brief
@developer
@return
@access
*/
public function &db_fetch_object()
{
return new Any_prop_obj_base();
}
}
/* End of file connect_wrapper.php */
/* Location: tools/dbxml_validator/connect_wrapper.php */

View file

@ -1,23 +0,0 @@
<query id="checkMissingPipe" action="select">
<tables>
<table name="tableName" alias="alias" />
</tables>
<columns>
<column name="columnName" alias="alias" />
</columns>
<conditions>
<condition operation="like_prefix" column="column1" var="variable" filter="user_id" default="default" notnull="notnull" minlength="10" maxlength="1000" pipe="AND"/>
<group>
<condition operation="notlike_tail" column="column" var="variable" filter="numbers" default="default" notnull="notnull" minlength ="0" maxlength="10000" pipe="and"/>
</group>
</conditions>
<navigation>
<index var="var" default="default" order="desc|asc" />
<list_count var="var" default="25" />
<page_count var="var" default="5" />
<page var="var" default="2" />
</navigation>
<groups>
<group column="GroupBy daesang" />
</groups>
</query>

View file

@ -1,24 +0,0 @@
<query id="dupListCount" action="select">
<tables>
<table name="tableName" />
</tables>
<columns>
<column name="columnName" alias="alias" />
</columns>
<conditions>
<condition operation="like_prefix" column="column1" var="variable" filter="user_id" default="default" notnull="notnull" minlength="10" maxlength="1000" pipe="AND"/>
<group pipe="and">
<condition operation="notlike_tail" column="column" var="variable" filter="numbers" default="default" notnull="notnull" minlength ="0" maxlength="10000" pipe="and"/>
</group>
</conditions>
<navigation>
<index var="var" default="default" order="desc|asc" />
<list_count var="var" default="25" />
<list_count var="var" default="25" />
<page_count var="var" default="5" />
<page var="var" default="2" />
</navigation>
<groups>
<group column="GroupBy daesang" />
</groups>
</query>

View file

@ -1,25 +0,0 @@
<query id="dupPage" action="select">
<tables>
<table name="tableName" />
</tables>
<columns>
<column name="columnName" alias="alias" />
</columns>
<conditions>
<condition operation="like_prefix" column="column1" var="variable" filter="user_id" default="default" notnull="notnull" minlength="10" maxlength="1000" pipe="AND"/>
<group pipe="and">
<condition operation="notlike_tail" column="column" var="variable" filter="numbers" default="default" notnull="notnull" minlength ="0" maxlength="10000" pipe="and"/>
</group>
</conditions>
<navigation>
<index var="var" default="default" order="desc|asc" />
<list_count var="var" default="25" />
<page_count var="var" default="5" />
<page var="var" default="2" />
<page var="var" default="2" />
</navigation>
<groups>
<group column="GroupBy daesang" />
</groups>
</query>

View file

@ -1,24 +0,0 @@
<query id="dupPageCount" action="select">
<tables>
<table name="tableName" />
</tables>
<columns>
<column name="columnName" alias="alias" />
</columns>
<conditions>
<condition operation="like_prefix" column="column1" var="variable" filter="user_id" default="default" notnull="notnull" minlength="10" maxlength="1000" pipe="AND"/>
<group pipe="and">
<condition operation="notlike_tail" column="column" var="variable" filter="numbers" default="default" notnull="notnull" minlength ="0" maxlength="10000" pipe="and"/>
</group>
</conditions>
<navigation>
<index var="var" default="default" order="desc|asc" />
<list_count var="var" default="25" />
<page_count var="var" default="5" />
<page_count var="var" default="5" />
<page var="var" default="2" />
</navigation>
<groups>
<group column="GroupBy daesang" />
</groups>
</query>

Some files were not shown because too many files have changed in this diff Show more