Updated code comments for PHPDocumentor - XmlQueryParser, QueryParser, DBParser

git-svn-id: http://xe-core.googlecode.com/svn/branches/luminous@12417 201d5d3c-b55e-5fd7-737f-ddc643e51545
This commit is contained in:
ucorina 2012-12-17 13:50:35 +00:00
parent d2872f1ac4
commit 2334535831
3 changed files with 347 additions and 264 deletions

View file

@ -43,7 +43,7 @@ if(!defined('__XE_LOADED_XML_CLASS__')){
* Parses XE XML query files * Parses XE XML query files
* *
* @author Corina Udrescu (corina.udrescu@arnia.ro) * @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package dbclasses * @package /classes/xml
*/ */
class XmlQueryParser extends XmlParser { class XmlQueryParser extends XmlParser {
@ -83,7 +83,7 @@ class XmlQueryParser extends XmlParser {
if(!$action) return; if(!$action) return;
// Write query cache file // Write query cache file
$parser = new QueryParser($xml_obj->query); $parser = new QueryParser($xml_obj->query);
FileHandler::writeFile($cache_file, $parser->toString()); FileHandler::writeFile($cache_file, $parser->toString());
return $parser; return $parser;

View file

@ -1,193 +1,262 @@
<?php <?php
/**
* File containing the DBParser class
*/
/**
* Escapes query statements:
* - column names: member.member_srl => "member"."member_srl"
* - expressions: SUM(member.member_srl) => SUM("member"."member_srl")
*
* @author Corina Udrescu (corina.udrescu@arnia.ro)
* @package /classes/xml/xmlquery
*/
class DBParser
{
/** /**
* DBParser class * Character for escape target value on the left
* @author NHN (developers@xpressengine.com) *
* @package /classes/xml/xmlquery * For example, in CUBRID left and right escape
* @version 0.1 * chars are the same, the double quote - "
* But for SQL Server, the escape is made with
* [double brackets], so the left and right char differ
*
*
* @var string
*/ */
class DBParser { var $escape_char_left;
/**
* Character for escape target value on the left
* @var string
*/
var $escape_char_left;
/**
* Character for escape target value on the right
* @var string
*/
var $escape_char_right;
/**
* Table prefix string
* @var string
*/
var $table_prefix;
/** /**
* constructor * Character for escape target value on the right
* @param string $escape_char_left *
* @param string $escape_char_right * For example, in CUBRID left and right escape
* @param string $table_prefix * chars are the same, the double quote - "
* @return void * But for SQL Server, the escape is made with
*/ * [double brackets], so the left and right char differ
function DBParser($escape_char_left, $escape_char_right = "", $table_prefix = "xe_"){ *
$this->escape_char_left = $escape_char_left; * @var string
if ($escape_char_right !== "")$this->escape_char_right = $escape_char_right; */
else $this->escape_char_right = $escape_char_left; var $escape_char_right;
$this->table_prefix = $table_prefix;
}
/** /**
* Get escape character * Table prefix string
* @param string $leftOrRight left or right *
* @return string * Default is "xe_"
*/ *
function getEscapeChar($leftOrRight){ * @var string
if ($leftOrRight === 'left')return $this->escape_char_left; */
else return $this->escape_char_right; var $table_prefix;
}
/** /**
* escape the value * Constructor
* @param mixed $name *
* @return string * @param string $escape_char_left
*/ * @param string $escape_char_right
function escape($name){ * @param string $table_prefix
return $this->escape_char_left . $name . $this->escape_char_right; *
} * @return void
*/
function DBParser($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;
}
/** /**
* escape the string value * Get escape character
* @param string $name * @param string $leftOrRight left or right
* @return string * @return string
*/ */
function escapeString($name){ function getEscapeChar($leftOrRight)
return "'".$this->escapeStringValue($name)."'"; {
} if ($leftOrRight === 'left')return $this->escape_char_left;
else return $this->escape_char_right;
}
/** /**
* escape the string value * Escape the value
* @param string $value * @param mixed $name
* @return string * @return string
*/ */
function escapeStringValue($value){ function escape($name)
if($value == "*") return $value; {
if (is_string($value)) return $value = str_replace("'","''",$value); return $this->escape_char_left . $name . $this->escape_char_right;
return $value; }
}
/** /**
* Return table full name * Escape the string value
* @param string $name table name without table prefix * @param string $name
* @return string table full name with table prefix * @return string
*/ */
function parseTableName($name){ function escapeString($name)
return $this->table_prefix . $name; {
} return "'".$this->escapeStringValue($name)."'";
}
/** /**
* Return colmun name after escape * Escape the string value
* @param string $name column name before escape * @param string $value
* @return string column name after escape * @return string
*/ */
function parseColumnName($name){ function escapeStringValue($value)
return $this->escapeColumn($name); {
} if($value == "*") return $value;
if (is_string($value)) return $value = str_replace("'","''",$value);
return $value;
}
/** /**
* Escape column * Return table full name
* @param string $column_name *
* @return string column name with db name * @param string $name table name without table prefix
*/ *
function escapeColumn($column_name){ * @return string table full name with table prefix
if($this->isUnqualifiedColumnName($column_name)) */
return $this->escape($column_name); function parseTableName($name)
if($this->isQualifiedColumnName($column_name)){ {
list($table, $column) = explode('.', $column_name); return $this->table_prefix . $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);
}
}
/** /**
* Column name is suitable for use in checking * Return column name after escape
* @param string $column_name *
* @return bool * @param string $name column name before escape
*/ *
function isUnqualifiedColumnName($column_name){ * @return string column name after escape
if(strpos($column_name,'.')===false && strpos($column_name,'(')===false) return true; */
return false; function parseColumnName($name)
} {
return $this->escapeColumn($name);
}
/** /**
* Column name is suitable for use in checking * Escape column name
* @param string $column_name *
* @return bool * @param string $column_name
*/ * @return string column name with db name
function isQualifiedColumnName($column_name){ */
if(strpos($column_name,'.')!==false && strpos($column_name,'(')===false) return true; function escapeColumn($column_name)
return false; {
} if($this->isUnqualifiedColumnName($column_name))
return $this->escape($column_name);
function parseExpression($column_name){ if($this->isQualifiedColumnName($column_name)){
$functions = preg_split('/([\+\-\*\/\ ])/', $column_name, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); list($table, $column) = explode('.', $column_name);
foreach($functions as $k => $v){ // $table can also be an alias, so the prefix should not be added
$function = &$functions[$k]; return $this->escape($table).'.'.$this->escape($column);
if(strlen($function)==1) continue; // skip delimiters //return $this->escape($this->parseTableName($table)).'.'.$this->escape($column);
$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'))) {
$match = $this->escapeColumnExpression($match);
}
}
}
$function = implode('', $matches);
}
return implode('', $functions);
}
/*
* Checks argument is 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(strpos(strtolower($column_name), 'distinct') !== false) return $column_name;
return $this->escapeColumn($column_name);
} }
} }
/**
* Checks to see if a given column name is unqualified
*
* Ex: "member_srl" -> unqualified
* "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
* "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
*
* This can be:
* - a column name: "member_srl" or "xe_member"."member_srl"
* - an expression:
* - LEFT(UPPER("content"))
* - readed_count + voted_count
* - CAST(regdate as DATE)
*
* @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'))) {
$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(strpos(strtolower($column_name), 'distinct') !== FALSE) return $column_name;
return $this->escapeColumn($column_name);
}
}

View file

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