Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use closures in portability converter #5936

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,18 @@
<errorLevel type="suppress">
<!-- lastInsertId has a return type that does not match the one defined in the interface-->
<file name="src/Driver/Mysqli/Connection.php"/>

<!-- See https://github.com/vimeo/psalm/issues/5472 -->
<file name="src/Portability/Converter.php"/>
</errorLevel>
</InvalidReturnStatement>
<InvalidReturnType>
<errorLevel type="suppress">
<!-- lastInsertId has a return type that does not match the one defined in the interface-->
<file name="src/Driver/Mysqli/Connection.php"/>

<!-- See https://github.com/vimeo/psalm/issues/5472 -->
<file name="src/Portability/Converter.php"/>
</errorLevel>
</InvalidReturnType>
<InvalidScalarArgument>
Expand Down
85 changes: 37 additions & 48 deletions src/Portability/Converter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Doctrine\DBAL\Portability;

use Closure;

use function array_change_key_case;
use function array_map;
use function array_reduce;
Expand All @@ -12,23 +14,12 @@

final class Converter
{
/** @var callable */
private $convertNumeric;

/** @var callable */
private $convertAssociative;

/** @var callable */
private $convertOne;

/** @var callable */
private $convertAllNumeric;

/** @var callable */
private $convertAllAssociative;

/** @var callable */
private $convertFirstColumn;
private readonly Closure $convertNumeric;
private readonly Closure $convertAssociative;
private readonly Closure $convertOne;
private readonly Closure $convertAllNumeric;
private readonly Closure $convertAllAssociative;
private readonly Closure $convertFirstColumn;

/**
* @param bool $convertEmptyStringToNull Whether each empty string should be converted to NULL
Expand All @@ -42,13 +33,13 @@ public function __construct(bool $convertEmptyStringToNull, bool $rightTrimStrin
$convertNumeric = $this->createConvertRow($convertValue, null);
$convertAssociative = $this->createConvertRow($convertValue, $case);

$this->convertNumeric = $this->createConvert($convertNumeric, [self::class, 'id']);
$this->convertAssociative = $this->createConvert($convertAssociative, [self::class, 'id']);
$this->convertOne = $this->createConvert($convertValue, [self::class, 'id']);
$this->convertNumeric = $this->createConvert($convertNumeric);
$this->convertAssociative = $this->createConvert($convertAssociative);
$this->convertOne = $this->createConvert($convertValue);

$this->convertAllNumeric = $this->createConvertAll($convertNumeric, [self::class, 'id']);
$this->convertAllAssociative = $this->createConvertAll($convertAssociative, [self::class, 'id']);
$this->convertFirstColumn = $this->createConvertAll($convertValue, [self::class, 'id']);
$this->convertAllNumeric = $this->createConvertAll($convertNumeric);
$this->convertAllAssociative = $this->createConvertAll($convertAssociative);
$this->convertFirstColumn = $this->createConvertAll($convertValue);
}

/**
Expand Down Expand Up @@ -157,18 +148,18 @@ private static function rightTrimString(mixed $value): mixed
* @param bool $convertEmptyStringToNull Whether each empty string should be converted to NULL
* @param bool $rightTrimString Whether each string should right-trimmed
*
* @return callable|null The resulting function or NULL if no conversion is needed
* @return Closure|null The resulting function or NULL if no conversion is needed
*/
private function createConvertValue(bool $convertEmptyStringToNull, bool $rightTrimString): ?callable
private function createConvertValue(bool $convertEmptyStringToNull, bool $rightTrimString): ?Closure
{
$functions = [];

if ($convertEmptyStringToNull) {
$functions[] = [self::class, 'convertEmptyStringToNull'];
$functions[] = self::convertEmptyStringToNull(...);
}

if ($rightTrimString) {
$functions[] = [self::class, 'rightTrimString'];
$functions[] = self::rightTrimString(...);
}

return $this->compose(...$functions);
Expand All @@ -177,12 +168,12 @@ private function createConvertValue(bool $convertEmptyStringToNull, bool $rightT
/**
* Creates a function that will convert each array-row retrieved from the database
*
* @param callable|null $function The function that will convert each value
* @param int|null $case Column name case
* @param Closure|null $function The function that will convert each value
* @param int|null $case Column name case
*
* @return callable|null The resulting function or NULL if no conversion is needed
* @return Closure|null The resulting function or NULL if no conversion is needed
*/
private function createConvertRow(?callable $function, ?int $case): ?callable
private function createConvertRow(?Closure $function, ?int $case): ?Closure
{
$functions = [];

Expand All @@ -191,9 +182,7 @@ private function createConvertRow(?callable $function, ?int $case): ?callable
}

if ($case !== null) {
$functions[] = static function (array $row) use ($case): array {
return array_change_key_case($row, $case);
};
$functions[] = static fn (array $row): array => array_change_key_case($row, $case);
}

return $this->compose(...$functions);
Expand All @@ -203,13 +192,12 @@ private function createConvertRow(?callable $function, ?int $case): ?callable
* Creates a function that will be applied to the return value of Statement::fetch*()
* or an identity function if no conversion is needed
*
* @param callable|null $function The function that will convert each tow
* @param callable $id Identity function
* @param Closure|null $function The function that will convert each tow
*/
private function createConvert(?callable $function, callable $id): callable
private function createConvert(?Closure $function): Closure
{
if ($function === null) {
return $id;
return self::id(...);
}

return /**
Expand All @@ -232,13 +220,12 @@ static function (mixed $value) use ($function): mixed {
* Creates a function that will be applied to the return value of Statement::fetchAll*()
* or an identity function if no transformation is required
*
* @param callable|null $function The function that will transform each value
* @param callable $id Identity function
* @param Closure|null $function The function that will transform each value
*/
private function createConvertAll(?callable $function, callable $id): callable
private function createConvertAll(?Closure $function): Closure
{
if ($function === null) {
return $id;
return self::id(...);
}

return $this->createMapper($function);
Expand All @@ -247,25 +234,27 @@ private function createConvertAll(?callable $function, callable $id): callable
/**
* Creates a function that maps each value of the array using the given function
*
* @param callable $function The function that maps each value of the array
* @param Closure $function The function that maps each value of the array
*
* @return Closure(array):array
*/
private function createMapper(callable $function): callable
private function createMapper(Closure $function): Closure
{
return static fn (array $array): array => array_map($function, $array);
}

/**
* Creates a composition of the given set of functions
*
* @param callable(T):T ...$functions The functions to compose
* @param Closure(T):T ...$functions The functions to compose
*
* @return callable(T):T|null
* @return Closure(T):T|null
*
* @template T
*/
private function compose(callable ...$functions): ?callable
private function compose(Closure ...$functions): ?Closure
{
return array_reduce($functions, static function (?callable $carry, callable $item): callable {
return array_reduce($functions, static function (?Closure $carry, Closure $item): Closure {
if ($carry === null) {
return $item;
}
Expand Down