Browse Source

Extracted all identifier quoting logic into a separate object

Jose Lorenzo Rodriguez 12 years ago
parent
commit
34f24d92f1

+ 2 - 5
Cake/Database/Dialect/PostgresDialectTrait.php

@@ -27,10 +27,7 @@ use Cake\Database\SqlDialectTrait;
  */
 trait PostgresDialectTrait {
 
-	use SqlDialectTrait {
-		_expressionTranslators as private _quotingTranslators;
-	}
-
+	use SqlDialectTrait;
 /**
  *  String used to start a database identifier quoting to make it safe
  *
@@ -77,7 +74,7 @@ trait PostgresDialectTrait {
  */
 	protected function _expressionTranslators() {
 		$namespace = 'Cake\Database\Expression';
-		return $this->_quotingTranslators() + [
+		return [
 			$namespace . '\FunctionExpression' => '_transformFunctionExpression'
 		];
 	}

+ 2 - 4
Cake/Database/Dialect/SqliteDialectTrait.php

@@ -23,9 +23,7 @@ use Cake\Database\SqlDialectTrait;
 
 trait SqliteDialectTrait {
 
-	use SqlDialectTrait {
-		_expressionTranslators as private _quotingTranslators;
-	}
+	use SqlDialectTrait;
 
 /**
  *  String used to start a database identifier quoting to make it safe
@@ -49,7 +47,7 @@ trait SqliteDialectTrait {
  */
 	protected function _expressionTranslators() {
 		$namespace = 'Cake\Database\Expression';
-		return $this->_quotingTranslators() + [
+		return [
 			$namespace . '\FunctionExpression' => '_transformFunctionExpression'
 		];
 	}

+ 210 - 0
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())
+		);
+	}
+
+}

+ 1 - 127
Cake/Database/SqlDialectTrait.php

@@ -16,10 +16,6 @@
  */
 namespace Cake\Database;
 
-use Cake\Database\Expression\Comparison;
-use Cake\Database\Expression\OrderByExpression;
-use Cake\Database\Expression\IdentifierExpression;
-
 trait SqlDialectTrait {
 
 /**
@@ -77,10 +73,7 @@ trait SqlDialectTrait {
 	public function queryTranslator($type) {
 		return function($query) use ($type) {
 			if ($this->autoQuoting()) {
-				$binder = $query->valueBinder();
-				$query->valueBinder(false);
-				$query = $this->_quoteQueryIdentifiers($type, $query);
-				$query->valueBinder($binder);
+				$query = (new IdentifierQuoter($this))->quote($query);
 			}
 
 			$query = $this->{'_' . $type . 'QueryTranslator'}($query);
@@ -108,59 +101,10 @@ trait SqlDialectTrait {
  * @return array
  */
 	protected function _expressionTranslators() {
-		if ($this->autoQuoting()) {
-			$namespace = 'Cake\Database\Expression';
-			return [
-				$namespace . '\Comparison' => '_quoteComparison',
-				$namespace . '\OrderByExpression' => '_quoteOrderBy',
-				$namespace . '\IdentifierExpression' => '_quoteField'
-			];
-		}
-
 		return [];
 	}
 
 /**
- * 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->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->quoteIdentifier($field);
-			}
-			return $part;
-		});
-	}
-
-/**
- * Quotes identifiers in "order by" expression objects
- *
- * @param \Cake\Database\Expression\IdentifierExpression $expression
- * @return void
- */
-	protected function _quoteField(IdentifierExpression $expression) {
-		$expression->setIdentifier(
-			$this->quoteIdentifier($expression->getIdentifier())
-		);
-	}
-
-/**
  * Apply translation steps to select queries.
  *
  * @param Query $query The query to translate
@@ -186,76 +130,6 @@ trait SqlDialectTrait {
 	}
 
 /**
- * Iterates over each of the clauses in a query looking for identifiers and
- * quotes them
- *
- * @param string $type the type of query to be quoted
- * @param Query $query The query to have its identifiers quoted
- * @return Query
- */
-	protected function _quoteQueryIdentifiers($type, $query) {
-		if ($type === 'insert') {
-			return $this->_quoteInsertIdentifiers($query);
-		}
-
-		$quoter = function($part) use ($query) {
-			$result = [];
-			foreach ((array)$query->clause($part) as $alias => $value) {
-				$value = !is_string($value) ? $value : $this->quoteIdentifier($value);
-				$alias = is_numeric($alias) ? $alias : $this->quoteIdentifier($alias);
-				$result[$alias] = $value;
-			}
-			if ($result) {
-				$query->{$part}($result, true);
-			}
-		};
-
-		if (is_array($query->clause('distinct'))) {
-			$quoter('distinct', $query);
-		}
-
-		$quoter('select');
-		$quoter('from');
-		$quoter('group');
-
-		$result = [];
-		foreach ((array)$query->clause('join') as $value) {
-			$alias =  empty($value['alias']) ? null : $this->quoteIdentifier($value['alias']);
-			$value['alias'] = $alias;
-
-			if (is_string($value['table'])) {
-				$value['table'] = $this->quoteIdentifier($value['table']);
-			}
-
-			$result[$alias] = $value;
-		}
-
-		if ($result) {
-			$query->join($result, [], true);
-		}
-
-		return $query;
-	}
-
-/**
- * Quotes the table name and columns for an insert query
- *
- * @param Query $query
- * @return Query
- */
-	protected function _quoteInsertIdentifiers($query) {
-		list($table, $columns) = $query->clause('insert');
-		$table = $this->quoteIdentifier($table);
-		foreach ($columns as &$column) {
-			if (is_string($column)) {
-				$column = $this->quoteIdentifier($column);
-			}
-		}
-		$query->insert($table, $columns);
-		return $query;
-	}
-
-/**
  * Apply translation steps to delete queries.
  *
  * @param Query $query The query to translate