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
1 change: 0 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
<exclude>./test/unit/Adapter/AdapterServiceFactoryTest.php</exclude>
<exclude>./test/unit/Adapter/Driver/Pdo/ConnectionIntegrationTest.php</exclude>
<exclude>./test/unit/Adapter/Driver/Pdo/StatementIntegrationTest.php</exclude>
<exclude>./test/unit/Adapter/AdapterAwareTraitTest.php</exclude>
</testsuite>
<testsuite name="integration test">
<directory>./test/integration</directory>
Expand Down
2 changes: 2 additions & 0 deletions src/Adapter/Driver/Pdo/AbstractPdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ public function getProfiler(): ?ProfilerInterface
public function checkEnvironment(): bool
{
if (! extension_loaded('PDO')) {
// @codeCoverageIgnoreStart
throw new Exception\RuntimeException(
'The PDO extension is required for this adapter but the extension is not loaded'
);
// @codeCoverageIgnoreEnd
}
return true;
}
Expand Down
13 changes: 2 additions & 11 deletions src/Adapter/Profiler/Profiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
namespace PhpDb\Adapter\Profiler;

use PhpDb\Adapter\Exception;
use PhpDb\Adapter\Exception\InvalidArgumentException;
use PhpDb\Adapter\StatementContainerInterface;

use function end;
use function is_string;
use function microtime;

class Profiler implements ProfilerInterface
Expand All @@ -20,10 +18,7 @@ class Profiler implements ProfilerInterface
/** @var int */
protected $currentIndex = 0;

/**
* @throws InvalidArgumentException
* @return $this Provides a fluent interface
*/
/** @return $this Provides a fluent interface */
public function profilerStart(string|StatementContainerInterface $target): ProfilerInterface
{
$profileInformation = [
Expand All @@ -39,12 +34,8 @@ public function profilerStart(string|StatementContainerInterface $target): Profi
if ($container !== null) {
$profileInformation['parameters'] = clone $container;
}
} elseif (is_string($target)) {
$profileInformation['sql'] = $target;
} else {
throw new Exception\InvalidArgumentException(
__FUNCTION__ . ' takes either a StatementContainer or a string'
);
$profileInformation['sql'] = $target;
}

$this->profiles[$this->currentIndex] = $profileInformation;
Expand Down
21 changes: 4 additions & 17 deletions src/ResultSet/AbstractResultSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use function gettype;
use function is_array;
use function is_object;
use function key;
use function method_exists;
use function reset;

Expand Down Expand Up @@ -80,12 +79,9 @@ public function initialize(iterable $dataSource): ResultSetInterface
} elseif ($dataSource instanceof IteratorAggregate) {
/** @phpstan-ignore assign.propertyType */
$this->dataSource = $dataSource->getIterator();
} elseif ($dataSource instanceof Iterator) {
$this->dataSource = $dataSource;
} else {
throw new InvalidArgumentException(
'DataSource provided is not an array, nor does it implement Iterator or IteratorAggregate'
);
/** @phpstan-ignore assign.propertyType */
$this->dataSource = $dataSource;
}

return $this;
Expand Down Expand Up @@ -214,12 +210,7 @@ public function valid(): bool
return true;
}

if ($this->dataSource instanceof Iterator) {
return $this->dataSource->valid();
} else {
$key = key($this->dataSource);
return $key !== null;
}
return $this->dataSource->valid();
}

/**
Expand All @@ -229,11 +220,7 @@ public function valid(): bool
public function rewind(): void
{
if (! is_array($this->buffer)) {
if ($this->dataSource instanceof Iterator) {
$this->dataSource->rewind();
} else {
reset($this->dataSource);
}
$this->dataSource->rewind();
}

$this->position = 0;
Expand Down
51 changes: 1 addition & 50 deletions src/Sql/AbstractSql.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@
use function count;
use function current;
use function get_object_vars;
use function gettype;
use function implode;
use function is_array;
use function is_callable;
use function is_object;
use function is_string;
use function key;
use function rtrim;
Expand Down Expand Up @@ -151,14 +148,6 @@ protected function processExpression(
: $platform->quoteValue((string) $argument->getValue()),
$argument instanceof Identifier => $platform->quoteIdentifierInFragment($argument->getValue()),
$argument instanceof Literal => $argument->getValue(),
$argument instanceof Values => $this->processValuesArgument(
$argument,
$expressionParamIndex,
$namedParameterPrefix,
$platform,
$driver,
$parameterContainer
),
$argument instanceof Identifiers => $this->processIdentifiersArgument($argument, $platform),
$argument instanceof SelectArgument => $this->processExpressionOrSelect(
$argument,
Expand Down Expand Up @@ -234,36 +223,6 @@ protected function processExpressionOrSelect(
};
}

protected function processValuesArgument(
ArgumentInterface $argument,
int &$expressionParamIndex,
string $namedParameterPrefix,
PlatformInterface $platform,
?DriverInterface $driver = null,
?ParameterContainer $parameterContainer = null
): string {
$values = $argument->getValue();
$processedValues = [];

if ($parameterContainer instanceof ParameterContainer) {
foreach ($values as $value) {
$processedValues[] = $this->processExpressionParameterName(
$value,
$namedParameterPrefix,
$expressionParamIndex,
$driver,
$parameterContainer
);
}
} else {
foreach ($values as $value) {
$processedValues[] = $platform->quoteValue((string) $value);
}
}

return implode(', ', $processedValues);
}

protected function processIdentifiersArgument(
ArgumentInterface $argument,
PlatformInterface $platform
Expand Down Expand Up @@ -419,13 +378,8 @@ protected function processJoin(
: '') . $platform->quoteIdentifier($joinName[0]);
} elseif ($joinName instanceof Select) {
$joinName = '(' . $this->processSubSelect($joinName, $platform, $driver, $parameterContainer) . ')';
} elseif (is_string($joinName) || (is_object($joinName) && is_callable([$joinName, '__toString']))) {
$joinName = $platform->quoteIdentifier($joinName);
} else {
throw new Exception\InvalidArgumentException(sprintf(
'Join name expected to be Expression|TableIdentifier|Select|string, "%s" given',
gettype($joinName)
));
$joinName = $platform->quoteIdentifier($joinName);
}

$joinSpecArgArray[$j] = [
Expand Down Expand Up @@ -511,9 +465,6 @@ protected function resolveTable(
return $table;
}

/**
* Copy variables from the subject into the local properties
*/
protected function localizeVariables(): void
{
if (! $this instanceof PlatformDecoratorInterface) {
Expand Down
19 changes: 7 additions & 12 deletions test/unit/Adapter/AdapterAwareTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,21 @@

use PhpDb\Adapter\Adapter;
use PhpDb\Adapter\AdapterAwareTrait;
use PhpDb\Adapter\AdapterInterface;
use PhpDb\Adapter\Driver\DriverInterface;
use PhpDb\Adapter\Platform\PlatformInterface;
use PhpDbTest\Adapter\TestAsset\ConcreteAdapterAwareObject;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;

#[CoversMethod(AdapterAwareTrait::class, 'setDbAdapter')]
#[Group('unit')]
class AdapterAwareTraitTest extends TestCase
{
public function testSetDbAdapter(): void
{
$object = new class {
use AdapterAwareTrait;

public function getAdapter(): ?AdapterInterface
{
return $this->adapter ?? null;
}
};
$object = new ConcreteAdapterAwareObject();

self::assertNull($object->getAdapter());

Expand All @@ -39,9 +36,7 @@ public function getAdapter(): ?AdapterInterface

public function testSetDbAdapterSetsProperty(): void
{
$object = new class {
use AdapterAwareTrait;
};
$object = new ConcreteAdapterAwareObject();

$driver = $this->createMock(DriverInterface::class);
$platform = $this->createMock(PlatformInterface::class);
Expand Down
96 changes: 94 additions & 2 deletions test/unit/Adapter/AdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use PhpDb\Adapter\Driver\DriverInterface;
use PhpDb\Adapter\Driver\ResultInterface;
use PhpDb\Adapter\Driver\StatementInterface;
use PhpDb\Adapter\Exception\InvalidArgumentException;
use PhpDb\Adapter\Exception\VunerablePlatformQuoteException;
use PhpDb\Adapter\ParameterContainer;
use PhpDb\Adapter\Platform\PlatformInterface;
use PhpDb\Adapter\Profiler;
Expand All @@ -26,15 +28,16 @@

#[CoversMethod(Adapter::class, 'setProfiler')]
#[CoversMethod(Adapter::class, 'getProfiler')]
#[CoversMethod(Adapter::class, 'createDriver')]
#[CoversMethod(Adapter::class, 'createPlatform')]
#[CoversMethod(Adapter::class, 'getDriver')]
#[CoversMethod(Adapter::class, 'getPlatform')]
#[CoversMethod(Adapter::class, 'getQueryResultSetPrototype')]
#[CoversMethod(Adapter::class, 'getCurrentSchema')]
#[CoversMethod(Adapter::class, 'query')]
#[CoversMethod(Adapter::class, 'createStatement')]
#[CoversMethod(Adapter::class, '__get')]
#[CoversMethod(Adapter::class, '__construct')]
#[CoversMethod(Adapter::class, 'getHelpers')]
#[Group('unit')]
final class AdapterTest extends TestCase
{
protected DriverInterface&MockObject $mockDriver;
Expand Down Expand Up @@ -236,4 +239,93 @@ public function test__get(): void
/** @phpstan-ignore property.notFound, expr.resultUnused */
$this->adapter->foo;
}

public function testGetHelpersReturnsQuoteIdentifierFunction(): void
{
$functions = $this->adapter->getHelpers(Adapter::FUNCTION_QUOTE_IDENTIFIER);

self::assertCount(1, $functions);
self::assertIsCallable($functions[0]);
}

public function testGetHelpersReturnsQuoteValueFunction(): void
{
$functions = $this->adapter->getHelpers(Adapter::FUNCTION_QUOTE_VALUE);

self::assertCount(1, $functions);
self::assertIsCallable($functions[0]);
}

public function testGetHelpersReturnsBothFunctions(): void
{
$functions = $this->adapter->getHelpers(
Adapter::FUNCTION_QUOTE_IDENTIFIER,
Adapter::FUNCTION_QUOTE_VALUE
);

self::assertCount(2, $functions);
self::assertIsCallable($functions[0]);
self::assertIsCallable($functions[1]);
}

public function testConstructorWithProfilerDelegatesToSetProfiler(): void
{
$profilerMock = $this->createMock(Profiler\ProfilerInterface::class);
$driverMock = $this->createMock(DriverInterface::class);
$platformMock = $this->createMock(PlatformInterface::class);

$adapter = new Adapter(
driver: $driverMock,
platform: $platformMock,
profiler: $profilerMock,
);

self::assertSame($profilerMock, $adapter->getProfiler());
}

public function testQueryThrowsOnInvalidParameterType(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Parameter 2 to this method must be a flag, an array, or ParameterContainer');

$this->adapter->query('SELECT 1', 'invalid_mode');
}

public function testSetProfilerDelegatesToDriverWhenProfilerAware(): void
{
$profiler = $this->createMock(Profiler\ProfilerInterface::class);
$driver = $this->createMockForIntersectionOfInterfaces(
[DriverInterface::class, Profiler\ProfilerAwareInterface::class]
);
$driver->expects($this->once())->method('setProfiler')->with($profiler);

$platform = $this->createMock(PlatformInterface::class);
$adapter = new Adapter(driver: $driver, platform: $platform);

$adapter->setProfiler($profiler);
}

public function testGetHelpersQuoteIdentifierClosureCallsPlatform(): void
{
$this->mockPlatform->method('quoteIdentifier')
->with('test')
->willReturn('"test"');

$functions = $this->adapter->getHelpers(Adapter::FUNCTION_QUOTE_IDENTIFIER);
$result = $functions[0]('test');

self::assertSame('"test"', $result);
}

public function testGetHelpersQuoteValueClosureCallsPlatform(): void
{
$this->mockPlatform->method('quoteValue')
->with('test')
->willThrowException(VunerablePlatformQuoteException::forPlatformAndMethod('test', 'test'));

$functions = $this->adapter->getHelpers(Adapter::FUNCTION_QUOTE_VALUE);

$this->expectException(VunerablePlatformQuoteException::class);
$functions[0]('test');
}
}
Loading