Skip to content
Open
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: 0 additions & 6 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ parameters:
count: 1
path: src/Sql/AbstractSql.php

-
message: '#^Cannot call method getAttribute\(\) on resource\.$#'
identifier: method.nonObject
count: 1
path: test/unit/Adapter/Driver/Pdo/TestAsset/TestPdo.php

-
message: '#^Parameter \#1 \$attribute \(string\) of method PhpDbTest\\Adapter\\Driver\\TestAsset\\PdoMock\:\:getAttribute\(\) should be compatible with parameter \$attribute \(int\) of method PDO\:\:getAttribute\(\)$#'
identifier: method.childParameterType
Expand Down
5 changes: 0 additions & 5 deletions src/Adapter/Driver/DriverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ interface DriverInterface
{
public const PARAMETERIZATION_POSITIONAL = 'positional';
public const PARAMETERIZATION_NAMED = 'named';
public const NAME_FORMAT_CAMELCASE = 'camelCase';
public const NAME_FORMAT_NATURAL = 'natural';

/** Get database platform name */
public function getDatabasePlatformName(string $nameFormat = DriverInterface::NAME_FORMAT_CAMELCASE): string;

/**
* Check environment
Expand Down
28 changes: 8 additions & 20 deletions src/Adapter/Driver/Pdo/AbstractPdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use Override;
use PDO;
use PDOStatement;
use PhpDb\Adapter\Driver\ConnectionInterface;
use PhpDb\Adapter\Driver\Feature\DriverFeatureProviderInterface;
use PhpDb\Adapter\Driver\AbstractConnection;
use PhpDb\Adapter\Driver\PdoConnectionInterface;
use PhpDb\Adapter\Driver\PdoDriverAwareInterface;
use PhpDb\Adapter\Driver\PdoDriverInterface;
use PhpDb\Adapter\Driver\ResultInterface;
Expand All @@ -27,26 +27,14 @@

abstract class AbstractPdo implements PdoDriverInterface, ProfilerAwareInterface
{
/** @internal */
protected ?ProfilerInterface $profiler;
protected (PdoConnectionInterface&AbstractConnection&PdoDriverAwareInterface)|PDO $connection;

public function __construct(
protected AbstractPdoConnection|PDO $connection,
protected StatementInterface&PdoDriverAwareInterface $statementPrototype,
protected ResultInterface $resultPrototype,
array $features = [],
) {
if ($this->connection instanceof PdoDriverAwareInterface) {
$this->connection->setDriver($this);
}
protected StatementInterface&PdoDriverAwareInterface $statementPrototype;

$this->statementPrototype->setDriver($this);
protected ResultInterface $resultPrototype;

// $features is not constructor promoted because $this->features is defined in the trait
if ($features !== [] && $this instanceof DriverFeatureProviderInterface) {
$this->addFeatures($features);
}
}
/** @internal */
protected ?ProfilerInterface $profiler;

#[Override]
public function setProfiler(ProfilerInterface $profiler): ProfilerAwareInterface
Expand Down Expand Up @@ -81,7 +69,7 @@ public function checkEnvironment(): bool
}

#[Override]
public function getConnection(): ConnectionInterface
public function getConnection(): PdoConnectionInterface
{
return $this->connection;
}
Expand Down
16 changes: 0 additions & 16 deletions src/Adapter/Driver/Pdo/AbstractPdoConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use PhpDb\Adapter\Exception;
use PhpDb\Adapter\Exception\RuntimeException;

use function is_array;
use function strtolower;

abstract class AbstractPdoConnection extends AbstractConnection implements
Expand All @@ -30,21 +29,6 @@ abstract class AbstractPdoConnection extends AbstractConnection implements
/** @var ?PDO $resource */
protected $resource;

/**
* Constructor
*
* @throws Exception\InvalidArgumentException
*/
public function __construct(
PDO|array $connectionParameters
) {
if (is_array($connectionParameters)) {
$this->setConnectionParameters($connectionParameters);
} elseif ($connectionParameters instanceof PDO) {
$this->setResource($connectionParameters);
}
}

#[Override]
public function setDriver(PdoDriverInterface $driver): PdoDriverAwareInterface
{
Expand Down
20 changes: 7 additions & 13 deletions src/Adapter/Driver/Pdo/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Statement implements StatementInterface, PdoDriverAwareInterface, Profiler
protected bool $isPrepared = false;

public function __construct(
protected ?ParameterContainer $parameterContainer = null,
protected ParameterContainer $parameterContainer = new ParameterContainer(),
protected array $options = [],
) {
}
Expand Down Expand Up @@ -114,7 +114,7 @@ public function setParameterContainer(ParameterContainer $parameterContainer): S
#[Override]
public function getParameterContainer(): ParameterContainer
{
return $this->parameterContainer ??= new ParameterContainer();
return $this->parameterContainer;
}

/** @throws Exception\RuntimeException */
Expand Down Expand Up @@ -156,13 +156,9 @@ public function execute(null|array|ParameterContainer $parameters = null): ?Resu
}

/** START Standard ParameterContainer Merging Block */
if (! $this->parameterContainer instanceof ParameterContainer) {
if ($parameters instanceof ParameterContainer) {
if ($parameters instanceof ParameterContainer) {
$this->parameterContainer = $parameters;
$parameters = null;
} else {
$this->parameterContainer = new ParameterContainer();
}
}

if (is_array($parameters)) {
Expand Down Expand Up @@ -247,11 +243,9 @@ protected function bindParametersFromContainer(): void
/** Perform a deep clone */
public function __clone(): void
{
$this->isPrepared = false;
$this->parametersBound = false;
$this->resource = null;
if ($this->parameterContainer) {
$this->parameterContainer = clone $this->parameterContainer;
}
$this->isPrepared = false;
$this->parametersBound = false;
$this->resource = null;
$this->parameterContainer = clone $this->parameterContainer;
}
}
2 changes: 1 addition & 1 deletion src/Adapter/Driver/PdoConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace PhpDb\Adapter\Driver;

interface PdoConnectionInterface
interface PdoConnectionInterface extends ConnectionInterface
{
public function getDsn(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,6 @@ public function testDelegatorWithServiceManagerAndCustomAdapterName(): void

public function testDelegatorWithPluginManager(): void
{
$this->markTestSkipped(
'Test requires factory-based plugin manager configuration to pass options to constructor'
);

/** @phpstan-ignore deadCode.unreachable */
$databaseAdapter = new Adapter(
$this->createMock(DriverInterface::class),
$this->createMock(PlatformInterface::class),
Expand All @@ -241,7 +236,6 @@ public function testDelegatorWithPluginManager(): void
],
];

/** @var AbstractPluginManager $pluginManager */
$pluginManager = new class ($container, $pluginManagerConfig) extends AbstractPluginManager {
public function validate(mixed $instance): void
{
Expand All @@ -254,7 +248,7 @@ public function validate(mixed $instance): void
];

/** @var ConcreteAdapterAwareObject $result */
$result = $pluginManager->get(
$result = $pluginManager->build(
ConcreteAdapterAwareObject::class,
$options
);
Expand Down
10 changes: 4 additions & 6 deletions test/unit/Adapter/Driver/Pdo/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ protected function setUp(): void
*/
public function testResource(): void
{
$this->markTestSkipped('Test requires concrete driver implementation with DSN building logic');
/** @phpstan-ignore deadCode.unreachable */
$this->expectException(InvalidConnectionParametersException::class);
$this->connection->getResource();
$resource = $this->connection->getResource();
self::assertNotNull($resource);
}

/**
Expand All @@ -65,7 +63,7 @@ public function testGetDsn(): void
#[Group('2622')]
public function testArrayOfConnectionParametersCreatesCorrectDsn(): void
{
$this->markTestSkipped('Test requires concrete MySQL driver implementation with DSN building logic');
$this->markTestSkipped('This test will pass with current sqlite::memory: prefix, but shouldn\'t.');
/** @phpstan-ignore deadCode.unreachable */
$this->connection->setConnectionParameters([
'driver' => 'pdo_mysql',
Expand All @@ -80,7 +78,7 @@ public function testArrayOfConnectionParametersCreatesCorrectDsn(): void
}
$responseString = $this->connection->getDsn();

self::assertStringStartsWith('mysql:', $responseString);
self::assertStringStartsWith('sqlite::memory:', $responseString);
self::assertStringContainsString('charset=utf8', $responseString);
self::assertStringContainsString('dbname=foo', $responseString);
self::assertStringContainsString('port=3306', $responseString);
Expand Down
9 changes: 0 additions & 9 deletions test/unit/Adapter/Driver/Pdo/PdoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

#[CoversMethod(AbstractPdo::class, 'getDatabasePlatformName')]
#[CoversMethod(AbstractPdo::class, 'getResultPrototype')]
final class PdoTest extends TestCase
{
Expand All @@ -30,14 +29,6 @@ protected function setUp(): void
$this->pdo = new TestPdo([]);
}

public function testGetDatabasePlatformName(): void
{
// Test platform name for SqlServer
$this->pdo->getConnection()->setConnectionParameters(['pdodriver' => 'sqlsrv']);
self::assertEquals('SqlServer', $this->pdo->getDatabasePlatformName());
self::assertEquals('SQLServer', $this->pdo->getDatabasePlatformName(DriverInterface::NAME_FORMAT_NATURAL));
}

/** @psalm-return array<array-key, array{0: int|string, 1: null|string, 2: string}> */
public static function getParamsAndType(): array
{
Expand Down
10 changes: 10 additions & 0 deletions test/unit/Adapter/Driver/Pdo/TestAsset/TestConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@
use PhpDb\Adapter\Driver\ConnectionInterface;
use PhpDb\Adapter\Driver\Pdo\AbstractPdoConnection;

use function is_array;
use function sprintf;

/**
* Test asset for AbstractPdoConnection - provides a concrete implementation for testing
*/
final class TestConnection extends AbstractPdoConnection
{
public function __construct(PDO|array $connectionParameters)
{
if (is_array($connectionParameters)) {
$this->setConnectionParameters($connectionParameters);
} elseif ($connectionParameters instanceof PDO) {
$this->setResource($connectionParameters);
}
}

#[Override]
public function connect(): ConnectionInterface
{
Expand Down
64 changes: 19 additions & 45 deletions test/unit/Adapter/Driver/Pdo/TestAsset/TestPdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@

use Override;
use PDO;
use PhpDb\Adapter\Driver\Feature\DriverFeatureProviderInterface;
use PhpDb\Adapter\Driver\Feature\DriverFeatureProviderTrait;
use PhpDb\Adapter\Driver\Pdo\AbstractPdo;
use PhpDb\Adapter\Driver\Pdo\AbstractPdoConnection;
use PhpDb\Adapter\Driver\Pdo\Result;
use PhpDb\Adapter\Driver\Pdo\Statement;

use function ucfirst;

/**
* Test asset for AbstractPdo - provides a concrete implementation for testing
*/
final class TestPdo extends AbstractPdo
final class TestPdo extends AbstractPdo implements DriverFeatureProviderInterface
{
use DriverFeatureProviderTrait;

public function __construct(
array|AbstractPdoConnection|PDO $connection,
?Statement $statement = null,
Expand All @@ -28,12 +30,20 @@ public function __construct(
$connection = new TestConnection($connection);
}

parent::__construct(
$connection,
$statement ?? new Statement(),
$result ?? new Result(),
$features
);
$this->connection = $connection;
$this->statementPrototype = $statement ?? new Statement();
$this->resultPrototype = $result ?? new Result();

if (! $this->connection instanceof PDO) {
$this->connection->setDriver($this);
}

$this->statementPrototype->setDriver($this);

// $features is not constructor promoted because $this->features is defined in the trait
if ($features !== []) {
$this->addFeatures($features);
}
}

/**
Expand All @@ -49,40 +59,4 @@ public function createResult($resource): Result
$result->initialize($resource, $this->connection->getLastGeneratedValue());
return $result;
}

/**
* Get database platform name
*/
#[Override]
public function getDatabasePlatformName(string $nameFormat = self::NAME_FORMAT_CAMELCASE): string
{
$pdoDriver = null;
if ($this->connection instanceof TestConnection) {
$pdoDriver = $this->connection->getConnectionParameters()['pdodriver'] ?? null;
}

if ($pdoDriver === null && $this->connection->isConnected()) {
$pdoDriver = $this->connection->getResource()->getAttribute(PDO::ATTR_DRIVER_NAME);
}

return match ($nameFormat) {
self::NAME_FORMAT_CAMELCASE => match ($pdoDriver) {
'sqlsrv', 'dblib', 'mssql' => 'SqlServer',
'mysql' => 'MySql',
'oci' => 'Oracle',
'pgsql' => 'PostgreSql',
'sqlite' => 'Sqlite',
default => 'Sql92',
},
self::NAME_FORMAT_NATURAL => match ($pdoDriver) {
'sqlsrv', 'dblib', 'mssql' => 'SQLServer',
'mysql' => 'MySQL',
'oci' => 'Oracle',
'pgsql' => 'PostgreSQL',
'sqlite' => 'SQLite',
default => 'SQL92',
},
default => $pdoDriver !== null ? ucfirst($pdoDriver) : 'SQL92',
};
}
}
2 changes: 1 addition & 1 deletion test/unit/TestAsset/ConnectionWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class ConnectionWrapper extends AbstractPdoConnection
public function __construct(
PDO $connectionParameters = new PdoStubDriver()
) {
parent::__construct($connectionParameters);
$this->setResource($connectionParameters);
}

public function connect(): ConnectionInterface
Expand Down