Skip to content

Commit

Permalink
Update to Doctrine ORM 3.2 #10257
Browse files Browse the repository at this point in the history
  • Loading branch information
PowerKiKi committed Jul 12, 2024
1 parent 945706b commit 6eb09c5
Show file tree
Hide file tree
Showing 34 changed files with 396 additions and 475 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
"ext-pdo": "*",
"ext-readline": "*",
"cakephp/chronos": "^3.0.3",
"doctrine/dbal": "^3.8",
"doctrine/dbal": "^4.0",
"doctrine/migrations": "^3.8",
"ecodev/graphql-doctrine": "^10.0",
"ecodev/graphql-doctrine": "dev-doctrine3",
"imagine/imagine": "^1.3",
"laminas/laminas-diactoros": "^3.3",
"laminas/laminas-log": "^2.17",
Expand Down
447 changes: 123 additions & 324 deletions composer.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ parameters:
count: 1
path: src/Api/Enum/PhpEnumType.php

-
message: "#^Parameter \\#1 \\$className of method Ecodev\\\\Felix\\\\Api\\\\Input\\\\Operator\\\\SearchOperatorType\\:\\:fieldToDql\\(\\) expects ReflectionClass, ReflectionClass\\<object\\>\\|null given\\.$#"
count: 1
path: src/Api/Input/Operator/SearchOperatorType.php

-
message: "#^Method Ecodev\\\\Felix\\\\DBAL\\\\Types\\\\PhpEnumType\\:\\:convertToDatabaseValue\\(\\) should return string\\|null but returns int\\|string\\.$#"
count: 1
Expand Down
9 changes: 2 additions & 7 deletions src/Acl/Acl.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Ecodev\Felix\Acl;

use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
use Ecodev\Felix\Model\CurrentUser;
use Ecodev\Felix\Model\Model;
use Exception;
Expand Down Expand Up @@ -110,7 +110,7 @@ public function isAllowed($role = null, $resource = null, $privilege = null): bo
*/
public function isCurrentUserAllowed(Model|string $modelOrResource, string $privilege): bool
{
$resource = is_string($modelOrResource) ? $modelOrResource : new ModelResource($this->getClass($modelOrResource), $modelOrResource);
$resource = is_string($modelOrResource) ? $modelOrResource : new ModelResource(DefaultProxyClassNameResolver::getClass($modelOrResource), $modelOrResource);
$role = $this->getCurrentRole();
$this->reasons = [];

Expand All @@ -134,11 +134,6 @@ public function reject(string $reason): false
return false;
}

private function getClass(Model $resource): string
{
return ClassUtils::getRealClass($resource::class);
}

private function getCurrentRole(): MultipleRoles|string
{
$user = CurrentUser::get();
Expand Down
5 changes: 3 additions & 2 deletions src/Acl/ModelResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Ecodev\Felix\Acl;

use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
use Ecodev\Felix\Model\Model;
use Ecodev\Felix\Utility;
use InvalidArgumentException;
Expand Down Expand Up @@ -34,7 +34,8 @@ public function __construct(
throw new InvalidArgumentException('The class name must be an implementation of Model but given: ' . $class);
}

$class = ClassUtils::getRealClass($class);
$resolver = new DefaultProxyClassNameResolver();
$class = $resolver->resolveClassName($class);

parent::__construct($class);
}
Expand Down
6 changes: 3 additions & 3 deletions src/Api/Input/Operator/SearchOperatorType.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ private function getSearchableFields(ClassMetadata $metadata, string $alias): ar
// Find most textual fields for the entity
$fields = [];
foreach ($metadata->fieldMappings as $mapping) {
if (in_array($mapping['fieldName'], $whitelistedFields, true)) {
$fieldName = $mapping['fieldName'];
if (in_array($mapping->fieldName, $whitelistedFields, true)) {
$fieldName = $mapping->fieldName;
$field = $alias . '.' . $fieldName;

$fields[] = $this->fieldToDql($metadata->getReflectionClass(), $fieldName, $field);
Expand Down Expand Up @@ -115,7 +115,7 @@ private function getSearchableFieldsOnJoin(UniqueNameFactory $uniqueNameFactory,
private function searchOnJoinedEntity(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $fieldName): array
{
$association = $metadata->getAssociationMapping($fieldName);
$targetEntity = $association['targetEntity'];
$targetEntity = $association->targetEntity;

$joinedMetadata = $queryBuilder->getEntityManager()->getMetadataFactory()->getMetadataFor($targetEntity);
$joinedAlias = $uniqueNameFactory->createAliasName($targetEntity);
Expand Down
2 changes: 1 addition & 1 deletion src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function __invoke(): array
],
'dependencies' => [
'invokables' => [
DBAL\Logging\ForwardSQLLogger::class,
DBAL\Logging\Middleware::class,
Log\Formatter\Extras::class,
],
'factories' => [
Expand Down
58 changes: 58 additions & 0 deletions src/DBAL/Logging/Connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Ecodev\Felix\DBAL\Logging;

use Doctrine\DBAL\Driver\Connection as ConnectionInterface;
use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement as DriverStatement;

final class Connection extends AbstractConnectionMiddleware
{
public function __construct(ConnectionInterface $connection)
{
parent::__construct($connection);
}

public function prepare(string $sql): DriverStatement
{
return new Statement(parent::prepare($sql), $sql);
}

public function query(string $sql): Result
{
_log()->debug('Executing query: {sql}', ['sql' => $sql]);

return parent::query($sql);
}

public function exec(string $sql): int|string
{
_log()->debug('Executing statement: {sql}', ['sql' => $sql]);

return parent::exec($sql);
}

public function beginTransaction(): void
{
_log()->debug('Beginning transaction');

parent::beginTransaction();
}

public function commit(): void
{
_log()->debug('Committing transaction');

parent::commit();
}

public function rollBack(): void
{
_log()->debug('Rolling back transaction');

parent::rollBack();
}
}
38 changes: 38 additions & 0 deletions src/DBAL/Logging/Driver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Ecodev\Felix\DBAL\Logging;

use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use SensitiveParameter;

final class Driver extends AbstractDriverMiddleware
{
public function __construct(DriverInterface $driver)
{
parent::__construct($driver);
}

public function connect(#[SensitiveParameter] array $params): Connection
{
_log()->debug('Connecting to DB', $this->maskPassword($params));

return new Connection(parent::connect($params));
}

/**
* @param array<string,mixed> $params
*
* @return array<string,mixed>
*/
private function maskPassword(#[SensitiveParameter] array $params): array
{
if (isset($params['password'])) {
$params['password'] = '***REDACTED***';
}

return $params;
}
}
39 changes: 0 additions & 39 deletions src/DBAL/Logging/ForwardSQLLogger.php

This file was deleted.

19 changes: 19 additions & 0 deletions src/DBAL/Logging/Middleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Ecodev\Felix\DBAL\Logging;

use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\Middleware as MiddlewareInterface;

/**
* Log SQL queries including their timing (so the query will be logged after its execution).
*/
final class Middleware implements MiddlewareInterface
{
public function wrap(DriverInterface $driver): DriverInterface
{
return new Driver($driver);
}
}
46 changes: 46 additions & 0 deletions src/DBAL/Logging/Statement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Ecodev\Felix\DBAL\Logging;

use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;

final class Statement extends AbstractStatementMiddleware
{
/**
* @var array<int,mixed>|array<string,mixed>
*/
private array $params = [];

public function __construct(
StatementInterface $statement,
private readonly string $sql,
) {
parent::__construct($statement);
}

public function bindValue(int|string $param, mixed $value, ParameterType $type): void
{
$this->params[$param] = $value;

parent::bindValue($param, $value, $type);
}

public function execute(): Result
{
$start = microtime(true);
$result = parent::execute();
$end = microtime(true);

_log()->debug($this->sql, [
'params' => $this->params,
'time' => number_format(($end - $start) / 1000, 6),
]);

return $result;
}
}
20 changes: 13 additions & 7 deletions src/DBAL/Types/AbstractMoneyType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@

namespace Ecodev\Felix\DBAL\Types;

use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\IntegerType;
use Doctrine\DBAL\Types\Type;
use InvalidArgumentException;
use Money\Money;

abstract class AbstractMoneyType extends IntegerType
abstract class AbstractMoneyType extends Type
{
abstract protected function createMoney(string $value): Money;

public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getIntegerTypeDeclarationSQL($column);
}

public function getBindingType(): ParameterType
{
return ParameterType::INTEGER;
}

public function getName(): string
{
return 'Money';
Expand Down Expand Up @@ -44,9 +55,4 @@ public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform)

throw new InvalidArgumentException('Cannot convert to database value: ' . var_export($value, true));
}

public function requiresSQLCommentHint(AbstractPlatform $platform): bool
{
return true;
}
}
20 changes: 13 additions & 7 deletions src/DBAL/Types/ChronosType.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
use Cake\Chronos\Chronos;
use DateTimeInterface;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\DateTimeType;
use Doctrine\DBAL\Types\Exception\InvalidFormat;
use Doctrine\DBAL\Types\Exception\InvalidType;
use Doctrine\DBAL\Types\Type;

final class ChronosType extends DateTimeType
final class ChronosType extends Type
{
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getDateTimeTypeDeclarationSQL($column);
}

/**
* @return ($value is null ? null : string)
*/
Expand All @@ -25,7 +31,7 @@ public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform)
return $value->format($platform->getDateTimeFormatString());
}

throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'Chronos']);
throw InvalidType::new($value, self::class, ['null', 'Chronos']);
}

/**
Expand All @@ -38,9 +44,9 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Ch
}

if (!is_string($value) && !$value instanceof DateTimeInterface) {
throw ConversionException::conversionFailedFormat(
$value,
$this->getName(),
throw InvalidFormat::new(
(string) $value,
self::class,
$platform->getDateTimeFormatString(),
);
}
Expand Down
Loading

0 comments on commit 6eb09c5

Please sign in to comment.