Skip to content

Commit

Permalink
Improve consistency of exception message formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
jwage committed May 1, 2019
1 parent e46c09b commit 5ba53f9
Show file tree
Hide file tree
Showing 77 changed files with 376 additions and 232 deletions.
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Cache/ArrayStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function rowCount() : int
public function setFetchMode($fetchMode, ...$args) : void
{
if (count($args) > 0) {
throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()');
throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode().');
}

$this->defaultFetchMode = $fetchMode;
Expand Down
55 changes: 15 additions & 40 deletions lib/Doctrine/DBAL/DBALException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@
use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\FormatArray;
use Exception;
use Throwable;
use function array_map;
use function bin2hex;
use function implode;
use function is_resource;
use function is_string;
use function json_encode;
use function preg_replace;
use function sprintf;

class DBALException extends Exception
Expand All @@ -28,21 +22,28 @@ class DBALException extends Exception
*/
public static function driverExceptionDuringQuery(Driver $driver, Throwable $driverEx, $sql, array $params = [])
{
$msg = "An exception occurred while executing '" . $sql . "'";
if ($params) {
$msg .= ' with params ' . self::formatParameters($params);
}
$msg .= ":\n\n" . $driverEx->getMessage();
$messageFormat = <<<'MESSAGE'
An exception occurred while executing "%s"%s:
%s
MESSAGE;

return static::wrapException($driver, $driverEx, $msg);
$message = sprintf(
$messageFormat,
$sql,
$params !== [] ? sprintf(' with params %s', (new FormatArray())->__invoke($params)) : '',
$driverEx->getMessage()
);

return static::wrapException($driver, $driverEx, $message);
}

/**
* @return self
*/
public static function driverException(Driver $driver, Throwable $driverEx)
{
return static::wrapException($driver, $driverEx, 'An exception occurred in driver: ' . $driverEx->getMessage());
return static::wrapException($driver, $driverEx, sprintf('An exception occurred in driver with message: %s', $driverEx->getMessage()));
}

/**
Expand All @@ -59,30 +60,4 @@ private static function wrapException(Driver $driver, Throwable $driverEx, $msg)

return new self($msg, 0, $driverEx);
}

/**
* Returns a human-readable representation of an array of parameters.
* This properly handles binary data by returning a hex representation.
*
* @param mixed[] $params
*
* @return string
*/
private static function formatParameters(array $params)
{
return '[' . implode(', ', array_map(static function ($param) {
if (is_resource($param)) {
return (string) $param;
}

$json = @json_encode($param);

if (! is_string($json) || $json === 'null' && is_string($param)) {
// JSON encoding failed, this is not a UTF-8 string.
return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param)));
}

return $json;
}, $params)) . ']';
}
}
8 changes: 4 additions & 4 deletions lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l
assert(is_int($column));

if (! isset(self::$_paramTypeMap[$type])) {
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
throw new MysqliException(sprintf('Unknown type, "%s" given.', $type));
}

$this->_bindedValues[$column] =& $variable;
Expand All @@ -124,7 +124,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING) : void
assert(is_int($param));

if (! isset(self::$_paramTypeMap[$type])) {
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
throw new MysqliException(sprintf('Unknown type, "%s" given.', $type));
}

$this->_values[$param] = $value;
Expand Down Expand Up @@ -250,7 +250,7 @@ private function sendLongData($streams)
$chunk = fread($stream, 8192);

if ($chunk === false) {
throw new MysqliException("Failed reading the stream resource for parameter offset ${paramNr}.");
throw new MysqliException(sprintf('Failed reading the stream resource for parameter offset %d.', $paramNr));
}

if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
Expand Down Expand Up @@ -344,7 +344,7 @@ public function fetch($fetchMode = null, ...$args)
return (object) $assoc;

default:
throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode));
throw new MysqliException(sprintf('Unknown fetch mode %d.', $fetchMode));
}
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public static function convertPositionalToNamedPlaceholders($statement)

if ($currentLiteralDelimiter) {
throw new OCI8Exception(sprintf(
'The statement contains non-terminated string literal starting at offset %d',
'The statement contains non-terminated string literal starting at offset %d.',
$tokenOffset - 1
));
}
Expand Down Expand Up @@ -407,7 +407,7 @@ public function fetch($fetchMode = null, ...$args)
}

if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode);
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
}

return oci_fetch_array(
Expand All @@ -434,7 +434,7 @@ public function fetchAll($fetchMode = null, ...$args)
}

if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode);
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
}

if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) {
Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/DBAL/Driver/PDOStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ private function convertParamType(int $type) : int
if (! isset(self::PARAM_TYPE_MAP[$type])) {
// TODO: next major: throw an exception
@trigger_error(sprintf(
'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0',
'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0.',
$type
), E_USER_DEPRECATED);

Expand All @@ -227,7 +227,7 @@ private function convertFetchMode(int $fetchMode) : int
// TODO: next major: throw an exception
@trigger_error(sprintf(
'Using a PDO fetch mode or their combination (%d given)' .
' is deprecated and will cause an error in Doctrine 3.0',
' is deprecated and will cause an error in Doctrine 3.0.',
$fetchMode
), E_USER_DEPRECATED);

Expand Down
15 changes: 9 additions & 6 deletions lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\FormatVariable;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
Expand All @@ -17,7 +18,6 @@
use function array_key_exists;
use function count;
use function func_get_args;
use function gettype;
use function is_array;
use function is_int;
use function is_object;
Expand Down Expand Up @@ -73,7 +73,10 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
public function __construct($conn, $sql)
{
if (! is_resource($conn)) {
throw new SQLAnywhereException('Invalid SQL Anywhere connection resource: ' . $conn);
throw new SQLAnywhereException(sprintf(
'Invalid SQL Anywhere connection resource, "%s" given.',
(new FormatVariable())->__invoke($conn)
));
}

$this->conn = $conn;
Expand Down Expand Up @@ -108,7 +111,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l
break;

default:
throw new SQLAnywhereException('Unknown type: ' . $type);
throw new SQLAnywhereException(sprintf('Unknown type %d.', $type));
}

$this->boundValues[$column] =& $variable;
Expand Down Expand Up @@ -215,7 +218,7 @@ public function fetch($fetchMode = null, ...$args)
return sasql_fetch_object($this->result);

default:
throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode);
throw new SQLAnywhereException(sprintf('Fetch mode is not supported %d.', $fetchMode));
}
}

Expand Down Expand Up @@ -314,8 +317,8 @@ private function castObject(stdClass $sourceObject, $destinationClass, array $ct
if (! is_string($destinationClass)) {
if (! is_object($destinationClass)) {
throw new SQLAnywhereException(sprintf(
'Destination class has to be of type string or object, %s given.',
gettype($destinationClass)
'Destination class has to be of type string or object, "%s" given.',
(new FormatVariable())->__invoke($destinationClass)
));
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Driver extends AbstractSQLServerDriver
public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
{
if (! isset($params['host'])) {
throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver.");
throw new SQLSrvException('Missing "host" in configuration for sqlsrv driver.');
}

$serverName = $params['host'];
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ public function fetch($fetchMode = null, ...$args)
return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false;
}

throw new SQLSrvException('Fetch mode is not supported!');
throw new SQLSrvException('Fetch mode is not supported.');
}

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/Doctrine/DBAL/Exception/DriverRequired.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ public static function new(?string $url = null) : self
if ($url !== null) {
return new self(
sprintf(
"The options 'driver' or 'driverClass' are mandatory if a connection URL without scheme "
. 'is given to DriverManager::getConnection(). Given URL: %s',
'The options "driver" or "driverClass" are mandatory if a connection URL without scheme '
. 'is given to DriverManager::getConnection(). Given URL "%s".',
$url
)
);
}

return new self(
"The options 'driver' or 'driverClass' are mandatory if no PDO "
'The options "driver" or "driverClass" are mandatory if no PDO '
. 'instance is given to DriverManager::getConnection().'
);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Exception/EmptyCriteriaNotAllowed.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ final class EmptyCriteriaNotAllowed extends InvalidArgumentException
{
public static function new() : self
{
return new self('Empty criteria was used, expected non-empty criteria');
return new self('Empty criteria was used, expected non-empty criteria.');
}
}
41 changes: 41 additions & 0 deletions lib/Doctrine/DBAL/Exception/FormatArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Exception;

use function array_map;
use function bin2hex;
use function implode;
use function is_resource;
use function is_string;
use function json_encode;
use function preg_replace;
use function sprintf;

final class FormatArray
{
/**
* Returns a human-readable representation of an array of parameters.
* This properly handles binary data by returning a hex representation.
*
* @param array<mixed, mixed> $array
*/
public function __invoke(array $array) : string
{
return '[' . implode(', ', array_map(static function ($param) {
if (is_resource($param)) {
return (string) $param;
}

$json = @json_encode($param);

if (! is_string($json) || $json === 'null' && is_string($param)) {
// JSON encoding failed, this is not a UTF-8 string.
return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param)));
}

return $json;
}, $array)) . ']';
}
}
51 changes: 51 additions & 0 deletions lib/Doctrine/DBAL/Exception/FormatVariable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Exception;

use InvalidArgumentException;
use function get_class;
use function get_resource_type;
use function gettype;
use function is_array;
use function is_bool;
use function is_object;
use function is_resource;
use function is_string;
use function sprintf;

final class FormatVariable
{
/**
* @param mixed $value
*/
public function __invoke($value) : string
{
if ($value === null) {
return 'NULL';
}

if (is_object($value)) {
return get_class($value);
}

if (is_resource($value)) {
return get_resource_type($value);
}

if (is_bool($value)) {
return $value === true ? 'true' : 'false';
}

if (is_array($value)) {
return 'array';
}

if (is_string($value)) {
return $value;
}

throw new InvalidArgumentException(sprintf('Could not format value of type "%s".', gettype($value)));
}
}
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Exception/InvalidDriverClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static function new(string $driverClass) : self
{
return new self(
sprintf(
"The given 'driverClass' %s has to implement the %s interface.",
'The given "driverClass" "%s" has to implement the "%s" interface.',
$driverClass,
Driver::class
)
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Exception/InvalidPdoInstance.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ final class InvalidPdoInstance extends DBALException
{
public static function new() : self
{
return new self("The 'pdo' option was used in DriverManager::getConnection() but no instance of PDO was given.");
return new self('The "pdo" option was used in DriverManager::getConnection() but no instance of PDO was given.');
}
}
Loading

0 comments on commit 5ba53f9

Please sign in to comment.