Skip to content

Commit

Permalink
Extracted all identifier quoting logic into a separate object
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Nov 7, 2013
1 parent 3c049f9 commit 34f24d9
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 136 deletions.
7 changes: 2 additions & 5 deletions Cake/Database/Dialect/PostgresDialectTrait.php
Expand Up @@ -27,10 +27,7 @@
*/
trait PostgresDialectTrait {

use SqlDialectTrait {
_expressionTranslators as private _quotingTranslators;
}

use SqlDialectTrait;
/**
* String used to start a database identifier quoting to make it safe
*
Expand Down Expand Up @@ -77,7 +74,7 @@ protected function _insertQueryTranslator($query) {
*/
protected function _expressionTranslators() {
$namespace = 'Cake\Database\Expression';
return $this->_quotingTranslators() + [
return [
$namespace . '\FunctionExpression' => '_transformFunctionExpression'
];
}
Expand Down
6 changes: 2 additions & 4 deletions Cake/Database/Dialect/SqliteDialectTrait.php
Expand Up @@ -23,9 +23,7 @@

trait SqliteDialectTrait {

use SqlDialectTrait {
_expressionTranslators as private _quotingTranslators;
}
use SqlDialectTrait;

/**
* String used to start a database identifier quoting to make it safe
Expand All @@ -49,7 +47,7 @@ trait SqliteDialectTrait {
*/
protected function _expressionTranslators() {
$namespace = 'Cake\Database\Expression';
return $this->_quotingTranslators() + [
return [
$namespace . '\FunctionExpression' => '_transformFunctionExpression'
];
}
Expand Down
210 changes: 210 additions & 0 deletions Cake/Database/IdentifierQuoter.php
@@ -0,0 +1,210 @@
<?php
/**
* PHP Version 5.4
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Database;

use Cake\Database\Expression\Comparison;
use Cake\Database\Expression\OrderByExpression;
use Cake\Database\Expression\IdentifierExpression;

/**
* Contains all the logic related to quoting identifiers in a Query object
*
*/
class IdentifierQuoter {

/**
* The driver instance used to do the identifier quoting
*
* @var Cake\Database\Driver
*/
protected $_driver;

/**
* Constructor
*
* @param Cake\Database\Driver The driver instance used to do the identifier quoting
* @return void
*/
public function __construct(Driver $driver) {
$this->_driver = $driver;
}

/**
* Iterates over each of the clauses in a query looking for identifiers and
* quotes them
*
* @param Query $query The query to have its identifiers quoted
* @return Query
*/
public function quote(Query $query) {
$binder = $query->valueBinder();
$query->valueBinder(false);

if ($query->type() === 'insert') {
$this->_quoteInsert($query);
} else {
$this->_qouteParts($query);
}

$query->traverseExpressions(function($expression) {
if ($expression instanceof Comparison) {
$this->_quoteComparison($expression);
return;
}

if ($expression instanceof OrderByExpression) {
$this->_quoteOrderBy($expression);
return;
}

if ($expression instanceof IdentifierExpression) {
$this->_quoteIndetifierExpression($expression);
return;
}
});

$query->valueBinder($binder);
return $query;
}

/**
* Quotes all identifiers in each of the clauses of a query
*
* @param Query
* @return void
*/
protected function _qouteParts($query) {
foreach (['distinct', 'select', 'from', 'group'] as $part) {
$contents = $query->clause($part);

if (!is_array($contents)) {
continue;
}

$result = $this->_basicQuoter($contents);
if ($result) {
$query->{$part}($result, true);
}
}

$joins = $query->clause('join');
if ($joins) {
$joins = $this->_quoteJoins($joins);
$query->join($joins, [], true);
}
}

/**
* A generic identifier quoting function used for various parts of the query
*
* @param array $part the part of the query to quote
* @return array
*/
protected function _basicQuoter($part) {
$result = [];
foreach ((array)$part as $alias => $value) {
$value = !is_string($value) ? $value : $this->_driver->quoteIdentifier($value);
$alias = is_numeric($alias) ? $alias : $this->_driver->quoteIdentifier($alias);
$result[$alias] = $value;
}
return $result;
}

/**
* Quotes both the table and alias fot an array of joins as stored in a Query
* object
*
* @param array $joins
* @return array
*/
protected function _quoteJoins($joins) {
$result = [];
foreach ($joins as $value) {
$alias = null;
if (!empty($value['alias'])) {
$alias = $this->_driver->quoteIdentifier($value['alias']);
$value['alias'] = $alias;
}

if (is_string($value['table'])) {
$value['table'] = $this->_driver->quoteIdentifier($value['table']);
}

$result[$alias] = $value;
}

return $result;
}

/**
* Quotes the table name and columns for an insert query
*
* @param Query $query
* @return Query
*/
protected function _quoteInsert($query) {
list($table, $columns) = $query->clause('insert');
$table = $this->_driver->quoteIdentifier($table);
foreach ($columns as &$column) {
if (is_string($column)) {
$column = $this->_driver->quoteIdentifier($column);
}
}
$query->insert($table, $columns);
}

/**
* Quotes identifiers in comparison expression objects
*
* @param \Cake\Database\Expression\Comparison $expression
* @return void
*/
protected function _quoteComparison(Comparison $expression) {
$field = $expression->getField();
if (is_string($field)) {
$expression->field($this->_driver->quoteIdentifier($field));
}
}

/**
* Quotes identifiers in "order by" expression objects
*
* @param \Cake\Database\Expression\OrderByExpression $expression
* @return void
*/
protected function _quoteOrderBy(OrderByExpression $expression) {
$expression->iterateParts(function($part, &$field) {
if (is_string($field)) {
$field = $this->_driver->quoteIdentifier($field);
}
return $part;
});
}

/**
* Quotes identifiers in "order by" expression objects
*
* @param \Cake\Database\Expression\IdentifierExpression $expression
* @return void
*/
protected function _quoteIndetifierExpression(IdentifierExpression $expression) {
$expression->setIdentifier(
$this->_driver->quoteIdentifier($expression->getIdentifier())
);
}

}

0 comments on commit 34f24d9

Please sign in to comment.