<?php
/**
* ÐлаÑÑ QAL.
*
* @package energine
* @subpackage core
* @author 1m.dm
* @copyright ColoCall 2006
* @version $Id: QAL.class.php,v 1.7 2008/04/07 14:34:24 pavka Exp $
*/
//require_once('core/framework/DBA.class.php');
/**
* Query Abstraction Layer.
*
* @package energine
* @subpackage core
* @final
*/
final class QAL extends DBA {
/**
* Ð ÐµÐ¶Ð¸Ð¼Ñ Ð¼Ð¾Ð´Ð¸ÑиÑиÑÑÑÑиÑ
опеÑаÑий
*/
const INSERT = 'INSERT';
const UPDATE = 'UPDATE';
const DELETE = 'DELETE';
/**
* ÐапÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ ÑоÑÑиÑовки
*/
const ASC = 'ASC';
const DESC = 'DESC';
/**
* ÐÑÑÑÐ°Ñ ÑÑÑока
*/
const EMPTY_STRING = null;
/**
* ÐÑибки
*/
const ERR_BAD_QUERY_FORMAT = 'Bad query format.';
/**
* ÐонÑÑÑÑкÑÐ¾Ñ ÐºÐ»Ð°ÑÑа.
*
* @access public
* @param string $dsn
* @param string $username
* @param string $password
* @param object $driverOptions
* @return void
*/
public function __construct($dsn, $username, $password, array $driverOptions, $charset = 'utf8') {
parent::__construct($dsn, $username, $password, $driverOptions, $charset);
}
/**
* ÐÑполнÑÐµÑ Ð¿ÑоÑÑой SELECT-запÑÐ¾Ñ Ðº ÐРи возвÑаÑÐ°ÐµÑ ÑезÑлÑÑÐ°Ñ Ð²ÑбоÑки.
*
* Ðмена полей $fields задаÑÑÑÑ Ð¾Ð´Ð½Ð¸Ð¼ из ÑÑÑÑ
ÑпоÑобов:
* 1. маÑÑив имÑн полей;
* 2. Ð¸Ð¼Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ полÑ;
* 3. true, Ð´Ð»Ñ Ð²ÑбоÑки вÑеÑ
полей ÑаблиÑÑ.
*
* УÑловие вÑбоÑки $condition задаÑÑÑÑ Ð¼Ð°ÑÑивом вида array(имÑ_Ð¿Ð¾Ð»Ñ => знаÑение),
* или ÑÑÑокой WHERE-ÑÑÐ»Ð¾Ð²Ð¸Ñ Ñипа 'field1 = 4 AND field2 = 8'.
*
* ÐоÑÑдок ÑоÑÑиÑовки ÑезÑлÑÑа задаÑÑÑÑ Ð¼Ð°ÑÑивом вида array(имÑ_Ð¿Ð¾Ð»Ñ => поÑÑдок_ÑоÑÑиÑовки),
* или ÑÑÑокой пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ORDER BY Ñипа 'field1 DESC, field2 ASC'.
*
* ÐÐ¸Ð¼Ð¸Ñ Ð²ÑбоÑки задаÑÑÑÑ Ð¼Ð°ÑÑивом вида array(ÑмеÑение, кол-во_ÑÑÑок),
* или ÑÑÑокой пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ LIMIT Ñипа '32'.
*
* ÐозвÑаÑÐ°ÐµÑ Ð¼Ð°ÑÑив ÑезÑлÑÑаÑа вÑбоÑки или true, еÑли ÑезÑлÑÑÐ°Ñ Ð¿ÑÑÑой.
*
* @access public
* @param string $tableName Ð¸Ð¼Ñ ÑаблиÑÑ
* @param mixed $fields маÑÑив имен полей ÐÐÐ Ð¸Ð¼Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»Ñ ÐÐÐ true Ð´Ð»Ñ Ð²ÑбоÑки вÑеÑ
полей ÑаблиÑÑ
* @param mixed $condition ÑÑловие вÑбоÑки
* @param mixed $order поÑÑдок ÑоÑÑиÑовки ÑезÑлÑÑаÑа
* @param mixed $limit Ð»Ð¸Ð¼Ð¸Ñ Ð²ÑбоÑки
* @return array
* @see DBA::selectRequest()
*/
public function select($tableName, $fields = true, $condition = null, $order = null, $limit = null) {
//$tableName = strtolower($tableName);
if (is_array($fields) && !empty($fields)) {
$fields = array_map('strtolower', $fields);
$fields = implode(', ', $fields);
}
elseif (is_string($fields)) {
$fields = strtolower($fields);
}
elseif ($fields === true) {
$fields = '*';
}
else {
throw new SystemException(self::ERR_BAD_QUERY_FORMAT, SystemException::ERR_DB, array($tableName, $fields, $condition, $order, $limit));
}
if ($this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'mysql') {
$tableName = "`$tableName`";
}
$sqlQuery = "SELECT $fields FROM $tableName";
if (isset($condition)) {
$sqlQuery .= $this->buildWhereCondition($condition);
}
if (isset($order)) {
$sqlQuery .= $this->buildOrderCondition($order);
}
if (isset($limit)) {
if (is_array($limit)) {
$sqlQuery .= ' LIMIT '.implode(', ', $limit);
}
else {
$sqlQuery .= " LIMIT $limit";
}
}
return $this->selectRequest($sqlQuery);
}
/**
* ÐÑполнÑÐµÑ Ð¿ÑоÑÑÑÑ Ð¼Ð¾Ð´Ð¸ÑиÑиÑÑÑÑÑÑ (INSERT, UPDATE, DELETE) опеÑаÑÐ¸Ñ Ð² ÐÐ.
*
* Режим опеÑаÑии задаÑÑÑÑ Ð¾Ð´Ð½Ð¾Ð¹ из ÑÑÑÑ
конÑÑанÑ:
* 1. QAL::INSERT - вÑÑавка;
* 2. QAL::UPDATE - обновление;
* 3. QAL::DELETE - Ñдаление.
*
* ÐаннÑе Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑий Ñипа QAL::INSERT и QAL::UPDATE задаÑÑÑÑ Ð¼Ð°ÑÑивом
* вида array(имÑ_Ð¿Ð¾Ð»Ñ => знаÑение).
*
* УÑловие опеÑаÑии задаÑÑÑÑ Ð¼Ð°ÑÑивом вида array(имÑ_Ð¿Ð¾Ð»Ñ => знаÑение),
* или ÑÑÑокой WHERE-ÑÑÐ»Ð¾Ð²Ð¸Ñ Ñипа 'field1 = 4 AND field2 = 8'.
*
* Ð Ñежиме QAL::INSERT меÑод возвÑаÑÐ°ÐµÑ Ð¿Ð¾Ñледний ÑгенеÑиÑованнÑй ID длÑ
* Ð¿Ð¾Ð»Ñ Ñипа AUTO_INCREMENT, или true еÑли Ñакого Ð¿Ð¾Ð»Ñ Ð² ÑаблиÑе неÑ.
*
* Ð ÑежимаÑ
QAL::UPDATE и QAL::DELETE пÑи ÑÑпеÑном вÑполнении запÑоÑа
* вÑегда возвÑаÑаеÑÑÑ true.
*
* ÐÑи оÑибке вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð»Ñбого Ñипа опеÑаÑий возвÑаÑаеÑÑÑ false.
*
* @access public
* @param int $mode Ñежим опеÑаÑии
* @param string $tableName Ð¸Ð¼Ñ ÑаблиÑÑ
* @param array $data даннÑе Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑии
* @param mixed $condition ÑÑловие опеÑаÑии
* @return array
* @see DBA::modifyRequest()
*/
public function modify($mode, $tableName, array $data = null, $condition = null) {
if (empty($mode) || empty($tableName)) {
throw new SystemException(self::ERR_BAD_QUERY_FORMAT, SystemException::ERR_DB);
}
$sqlQuery = '';
switch ($mode) {
case self::INSERT:
if (!empty($data)) {
$fieldNames = array();
$fieldValues = array();
foreach ($data as $fieldName => $fieldValue) {
$fieldNames[] = $fieldName;
if ($fieldValue === self::EMPTY_STRING) {
$fieldValue = $this->quote('');
}
elseif ($fieldValue == '') {
$fieldValue = 'NULL';
}
else {
$fieldValue = $this->quote($fieldValue);
}
$fieldValues[] = $fieldValue;
}
$sqlQuery = "INSERT INTO `$tableName` (".implode(', ', $fieldNames).') VALUES ('.implode(', ', $fieldValues).')';
}
else {
$sqlQuery = "INSERT INTO `$tableName` VALUES ()";
}
break;
case self::UPDATE:
if (!empty($data)) {
$fields = array();
foreach ($data as $fieldName => $fieldValue) {
if ($fieldValue === self::EMPTY_STRING) {
$fieldValue = $this->quote('');
}
elseif ($fieldValue === '') {
$fieldValue = 'NULL';
}
else {
$fieldValue = $this->quote($fieldValue);
}
$fields[] = "$fieldName = $fieldValue";
}
$sqlQuery = "UPDATE `$tableName` SET ".implode(', ', $fields);
}
else {
throw new SystemException(self::ERR_BAD_QUERY_FORMAT, SystemException::ERR_DB);
}
break;
case self::DELETE:
$sqlQuery = "DELETE FROM `$tableName`";
break;
default:
throw new SystemException(self::ERR_BAD_QUERY_FORMAT, SystemException::ERR_DB);
}
if (isset($condition) && $mode != self::INSERT) {
$sqlQuery .= $this->buildWhereCondition($condition);
}
return $this->modifyRequest($sqlQuery);
}
/**
* СÑÑÐ¾Ð¸Ñ WHERE-ÑÑловие Ð´Ð»Ñ SQL-запÑоÑа.
*
* @access public
* @param mixed $condition
* @return string
* @see QAL::selectRequest()
*/
public function buildWhereCondition($condition) {
$result = '';
if (!empty($condition)) {
$result = ' WHERE ';
if (is_array($condition)) {
$cond = array();
foreach ($condition as $fieldName => $value) {
//$fieldName = strtolower($fieldName);
if (is_null($value)) {
$cond[] = "$fieldName IS NULL";
}
elseif (is_numeric($fieldName)) {
$cond[] = $value;
}
elseif (is_array($value)) {
$cond[] = $fieldName.' IN ('.implode(',',$value).')';
}
else {
$cond[] = "$fieldName = ".$this->quote($value);
}
}
$result .= implode(' AND ', $cond);
}
else {
$result .= $condition;
}
}
return $result;
}
/**
* СÑÑÐ¾Ð¸Ñ Ð¿Ñедложение ORDER BY Ð´Ð»Ñ SQL-запÑоÑа.
*
* @access public
* @param mixed $order
* @return string
* @see QAL::selectRequest()
*/
public function buildOrderCondition($clause) {
$orderClause = ' ORDER BY ';
if (is_array($clause)) {
$cls = array();
foreach ($clause as $fieldName => $direction) {
//$fieldName = strtolower($fieldName);
$cls[] = "$fieldName ".constant("self::$direction");
}
$orderClause .= implode(', ', $cls);
}
else {
$orderClause .= $clause;
}
return $orderClause;
}
/**
* СÑÑÐ¾Ð¸Ñ Ð¿Ñедложение LIMIT Ð´Ð»Ñ SQL-запÑоÑа.
*
* @access public
* @param mixed $limit
* @return string
* @see QAL::selectRequest()
*/
public function buildLimitStatement($clause) {
$limitClause = '';
if (is_array($clause)) {
$limitClause = " LIMIT {$clause[0]}";
if (isset($clause[1])) {
$limitClause .= ", {$clause[1]}";
}
}
return $limitClause;
}
}