89 lines
3.0 KiB
PHP
89 lines
3.0 KiB
PHP
|
<?php
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
/**
|
||
|
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||
|
* Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org)
|
||
|
* @link https://cakephp.org CakePHP(tm) Project
|
||
|
* @since 3.0.0
|
||
|
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||
|
*/
|
||
|
namespace Cake\Database\Expression;
|
||
|
|
||
|
use Cake\Database\ExpressionInterface;
|
||
|
use Cake\Database\ValueBinder;
|
||
|
use RuntimeException;
|
||
|
|
||
|
/**
|
||
|
* An expression object for ORDER BY clauses
|
||
|
*/
|
||
|
class OrderByExpression extends QueryExpression
|
||
|
{
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* @param \Cake\Database\ExpressionInterface|array|string $conditions The sort columns
|
||
|
* @param \Cake\Database\TypeMap|array<string, string> $types The types for each column.
|
||
|
* @param string $conjunction The glue used to join conditions together.
|
||
|
*/
|
||
|
public function __construct($conditions = [], $types = [], $conjunction = '')
|
||
|
{
|
||
|
parent::__construct($conditions, $types, $conjunction);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @inheritDoc
|
||
|
*/
|
||
|
public function sql(ValueBinder $binder): string
|
||
|
{
|
||
|
$order = [];
|
||
|
foreach ($this->_conditions as $k => $direction) {
|
||
|
if ($direction instanceof ExpressionInterface) {
|
||
|
$direction = $direction->sql($binder);
|
||
|
}
|
||
|
$order[] = is_numeric($k) ? $direction : sprintf('%s %s', $k, $direction);
|
||
|
}
|
||
|
|
||
|
return sprintf('ORDER BY %s', implode(', ', $order));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Auxiliary function used for decomposing a nested array of conditions and
|
||
|
* building a tree structure inside this object to represent the full SQL expression.
|
||
|
*
|
||
|
* New order by expressions are merged to existing ones
|
||
|
*
|
||
|
* @param array $conditions list of order by expressions
|
||
|
* @param array $types list of types associated on fields referenced in $conditions
|
||
|
* @return void
|
||
|
*/
|
||
|
protected function _addConditions(array $conditions, array $types): void
|
||
|
{
|
||
|
foreach ($conditions as $key => $val) {
|
||
|
if (
|
||
|
is_string($key) &&
|
||
|
is_string($val) &&
|
||
|
!in_array(strtoupper($val), ['ASC', 'DESC'], true)
|
||
|
) {
|
||
|
throw new RuntimeException(
|
||
|
sprintf(
|
||
|
'Passing extra expressions by associative array (`\'%s\' => \'%s\'`) ' .
|
||
|
'is not allowed to avoid potential SQL injection. ' .
|
||
|
'Use QueryExpression or numeric array instead.',
|
||
|
$key,
|
||
|
$val
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->_conditions = array_merge($this->_conditions, $conditions);
|
||
|
}
|
||
|
}
|