87 lines
2.3 KiB
PHP
87 lines
2.3 KiB
PHP
<?php declare (strict_types = 1);
|
|
|
|
namespace MailPoet\Doctrine\WPDB;
|
|
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
|
|
use MailPoet\Doctrine\WPDB\Exceptions\MissingParameterException;
|
|
use MailPoetVendor\Doctrine\DBAL\ParameterType;
|
|
use MailPoetVendor\Doctrine\DBAL\SQL\Parser\Visitor;
|
|
|
|
class ConvertParameters implements Visitor {
|
|
private const PARAM_TYPE_MAP = [
|
|
ParameterType::STRING => '%s',
|
|
ParameterType::INTEGER => '%d',
|
|
ParameterType::ASCII => '%s',
|
|
ParameterType::BINARY => '%s',
|
|
ParameterType::BOOLEAN => '%d',
|
|
ParameterType::NULL => '%s',
|
|
ParameterType::LARGE_OBJECT => '%s',
|
|
];
|
|
|
|
/** @var list<string> */
|
|
private array $buffer = [];
|
|
|
|
/** @var array<array-key, array{0: string, 1: mixed, 2: int}> */
|
|
private array $params;
|
|
|
|
private array $values = [];
|
|
|
|
private int $cursor = 1;
|
|
|
|
public function __construct(
|
|
array $params
|
|
) {
|
|
$this->params = $params;
|
|
}
|
|
|
|
public function acceptPositionalParameter(string $sql): void {
|
|
$position = $this->cursor++;
|
|
$this->acceptParameter($position);
|
|
}
|
|
|
|
public function acceptNamedParameter(string $sql): void {
|
|
$this->acceptParameter(trim($sql, ':'));
|
|
}
|
|
|
|
public function acceptOther(string $sql): void {
|
|
$this->buffer[] = $sql;
|
|
}
|
|
|
|
public function getSQL(): string {
|
|
return implode('', $this->buffer);
|
|
}
|
|
|
|
public function getValues(): array {
|
|
return $this->values;
|
|
}
|
|
|
|
/** @param array-key $key */
|
|
private function acceptParameter($key): void {
|
|
if (!array_key_exists($key, $this->params)) {
|
|
throw new MissingParameterException(sprintf("Parameter '%s' was defined in the query, but not provided.", $key));
|
|
}
|
|
[, $value, $type] = $this->params[$key];
|
|
|
|
// WPDB doesn't support NULL values. We need to handle them explicitly.
|
|
if ($value === null) {
|
|
$this->buffer[] = 'NULL';
|
|
return;
|
|
}
|
|
|
|
// WPDB doesn't accept non-scalar values. We need to cast them (PDO-like behavior).
|
|
if (!is_scalar($value)) {
|
|
if ($type === ParameterType::INTEGER) {
|
|
$value = (int)$value; // @phpstan-ignore-line -- cast may fail and that's OK
|
|
} elseif ($type === ParameterType::BOOLEAN) {
|
|
$value = (bool)$value;
|
|
} else {
|
|
$value = (string)$value; // @phpstan-ignore-line -- cast may fail and that's OK
|
|
}
|
|
}
|
|
|
|
$this->values[] = $value;
|
|
$this->buffer[] = self::PARAM_TYPE_MAP[$type] ?? '%s';
|
|
}
|
|
}
|