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

Update documentation & possibility to setup sqlProcessorFactory #208

Merged
merged 1 commit into from
May 13, 2023
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
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
"autoload": {
"psr-4": { "Nextras\\Dbal\\": "src/" }
},
"autoload-dev": {
"classmap": ["tests/inc/"]
},
"scripts": {
"phpstan": "phpstan analyze -c .phpstan.neon --memory-limit=512M",
"tests": "tester -C --colors 1 --setup ./tests/inc/setup.php ./tests/cases"
Expand Down
7 changes: 6 additions & 1 deletion docs/config-nette.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ nextras.dbal:
username: db-username
password: db-password
connectionTz: Europe/Prague
sqlProcessorFactory: @Custom\SqlProcessorFactory

services:
- Custom\SqlProcessorFactory
```

If you need multiple connections, install the extension once again with a different name and choose which connection
Expand All @@ -37,7 +41,8 @@ nextras.dbal2:

**Configuration keys** are those accepted by `Connection` instance, the actual driver respectively. See [Connection](default) chapter.

The extension takes two additional configurations:
The extension takes additional configurations:

- `panelQueryExplain` (default `true` if Tracy is available): enables/disables panel for Trace.
- `maxQueries` (default `100`): number of logged queries in the Tracy panel.
- `sqlProcessorFactory` a reference to `Nextras\Dbal\ISqlProcessorFactory` service.
4 changes: 3 additions & 1 deletion docs/config-symfony.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ nextras_dbal:

**Configuration keys** are those accepted by `Connection` instance, the actual driver respectively. See [Connection](default) chapter.

The bundle takes an additional configuration:
The bundle takes additional configurations:

- `maxQueries` (default `100`): number of logged queries into QueryDataCollector.

The define custom `Nextras\Dbal\ISqlProcessorFactory` instance, define `nextras_dbal.default.sqlProcessorFactory` named service, where the `default` is the name of relevant connection.
6 changes: 4 additions & 2 deletions docs/param-modifiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class SqlProcessorFactory implements ISqlProcessorFactory
}
```

Use `sqlProcessorFactory` configuration key to pass a factory instance. See configuration chapters.

### Modifier Resolver

SqlProcessor allows setting custom modifier resolver for any values passed for both implicit and explicit `%any` modifier. This way you may introduce custom processing for your custom types. For safety reasons it is possible to override only the `%any` modifier. To do so, implement `ISqlProcessorModifierResolver` interface and return the modifier name for the passed value. Finally, register the custom modifier resolver into SqlProcessor. This API is especially powerful in combination with custom modifiers.
Expand All @@ -163,7 +165,7 @@ class BrickSqlProcessorModifierResolver implements ISqlProcessorModifierResolver
public function resolve($value): ?string
{
if ($value instanceof \Brick\DayOfWeek) {
return 'brickDoW';
return 'brickDayOfWeek';
}
return null;
}
Expand All @@ -175,7 +177,7 @@ class SqlProcessorFactory implements ISqlProcessorFactory
{
$processor = new SqlProcessor($driver);
$processor->setCustomModifier(
'brickDoW',
'brickDayOfWeek',
function (SqlProcessor $processor, $value) {
assert($value instanceof \Brick\DayOfWeek);
return $processor->processModifier('s', $value->getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Nextras\Dbal\Connection;
use Nextras\Dbal\IConnection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
Expand Down Expand Up @@ -53,6 +54,11 @@ private function loadConnection(
int $maxQueries,
): void
{
$config['sqlProcessorFactory'] = new Reference(
"nextras_dbal.$name.sqlProcessorFactory",
ContainerInterface::NULL_ON_INVALID_REFERENCE,
);

$connectionDefinition = new Definition(Connection::class);
$connectionDefinition->setArgument('$config', $config);
$connectionDefinition->setPublic(true);
Expand Down
5 changes: 3 additions & 2 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use Nextras\Dbal\Utils\MultiLogger;
use Nextras\Dbal\Utils\StrictObjectTrait;
use function array_unshift;
use function assert;
use function is_array;
use function spl_object_hash;
use function str_replace;
Expand Down Expand Up @@ -349,7 +348,9 @@ private function createSqlProcessor(): SqlProcessor
{
if (isset($this->config['sqlProcessorFactory'])) {
$factory = $this->config['sqlProcessorFactory'];
assert($factory instanceof ISqlProcessorFactory);
if (!$factory instanceof ISqlProcessorFactory) {
throw new InvalidArgumentException("Connection's 'sqlProcessorFactory' configuration key does not contain an instance of " . ISqlProcessorFactory::class . '.');
}
return $factory->create($this);
} else {
return new SqlProcessor($this->getPlatform());
Expand Down
8 changes: 1 addition & 7 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace NextrasTests\Dbal;


use Tester\Environment;


Expand All @@ -10,18 +11,11 @@
exit(1);
}

require_once __DIR__ . '/inc/TestCase.php';
require_once __DIR__ . '/inc/TestLogger.php';
require_once __DIR__ . '/inc/QueryBuilderTestCase.php';
require_once __DIR__ . '/inc/IntegrationTestCase.php';


define('TEMP_DIR', __DIR__ . '/temp');
date_default_timezone_set('Europe/Prague');

Environment::setup();


if (getenv(Environment::RUNNER)) {
# Runner
header('Content-type: text/plain');
Expand Down
15 changes: 11 additions & 4 deletions tests/cases/integration/DbalBundleTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ namespace NextrasTests\Dbal;
use Nextras\Dbal\Bridges\SymfonyBundle\DependencyInjection\NextrasDbalExtension;
use Nextras\Dbal\Connection;
use Nextras\Dbal\IConnection;
use Nextras\Dbal\ISqlProcessorFactory;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Tester\Assert;

Expand All @@ -36,6 +38,9 @@ class DbalBundleTest extends IntegrationTestCase
],
],
]);
$containerBuilder->addDefinitions([
'nextras_dbal.default.sqlProcessorFactory' => new Definition(SqlProcessorFactory::class),
]);

$containerBuilder->compile();

Expand All @@ -49,11 +54,13 @@ class DbalBundleTest extends IntegrationTestCase
/** @var \Symfony\Component\DependencyInjection\Container $container */
$container = new $dicClass;

$connectionClass = $container->get('nextras_dbal.default.connection');
Assert::type(Connection::class, $connectionClass);
$connection = $container->get('nextras_dbal.default.connection');
Assert::type(Connection::class, $connection);

$connection = $container->get(IConnection::class);
Assert::type(Connection::class, $connection);

$connectionClass = $container->get(IConnection::class);
Assert::type(Connection::class, $connectionClass);
Assert::type(ISqlProcessorFactory::class, $connection->getConfig()["sqlProcessorFactory"]);
}
}

Expand Down
4 changes: 4 additions & 0 deletions tests/cases/integration/DbalExtensionTest.configD.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ dbal:
driver: mysqli
username: bar
password: foo
sqlProcessorFactory: @NextrasTests\Dbal\SqlProcessorFactory

dbal2:
driver: mysqli
username: bar2
password: foo2
autowired: false

services:
- NextrasTests\Dbal\SqlProcessorFactory
1 change: 1 addition & 0 deletions tests/cases/integration/DbalExtensionTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class DbalExtensionTest extends IntegrationTestCase
$connection = $dic->getByType(Connection::class);
Assert::type(Connection::class, $connection);
Assert::equal('bar', $connection->getConfig()['username']);
Assert::type(SqlProcessorFactory::class, $connection->getConfig()['sqlProcessorFactory']);

$connection = $dic->getService('dbal2.connection');
Assert::type(Connection::class, $connection);
Expand Down
26 changes: 3 additions & 23 deletions tests/cases/integration/sqlPreprocessor.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@
namespace NextrasTests\Dbal;


use Nextras\Dbal\Exception\InvalidArgumentException;
use Nextras\Dbal\IConnection;
use Nextras\Dbal\ISqlProcessorFactory;
use Nextras\Dbal\Platforms\PostgreSqlPlatform;
use Nextras\Dbal\Result\Row;
use Nextras\Dbal\SqlProcessor;
use Tester\Assert;


Expand Down Expand Up @@ -56,28 +53,11 @@ class SqlPreprocessorIntegrationTest extends IntegrationTestCase

public function testCustomModifier()
{
$sqlProcessorFactory = new class implements ISqlProcessorFactory {
public function create(IConnection $connection): SqlProcessor
{
$sqlProcessor = new SqlProcessor($connection->getPlatform());
$sqlProcessor->setCustomModifier(
'%test',
function (SqlProcessor $sqlProcessor, $value, string $type) {
if (!is_array($value)) throw new InvalidArgumentException('%test modifer accepts only array.');
return 'ARRAY[' .
implode(', ', array_map(function ($subValue) use ($sqlProcessor): string {
return $sqlProcessor->processModifier('any', $subValue);
}, $value)) .
']';
}
);
return $sqlProcessor;
}
};

$this->connection->connect();
/** @var ISqlProcessorFactory $sqlProcessorFactory */
$sqlProcessorFactory = $this->connection->getConfig()['sqlProcessorFactory'];
$sqlProcessor = $sqlProcessorFactory->create($this->connection);
$result = $sqlProcessor->processModifier('%test', [1, '2', false, null]);
$result = $sqlProcessor->processModifier('%pgArray', [1, '2', false, null]);
if ($this->connection->getPlatform()->getName() === PostgreSqlPlatform::NAME) {
Assert::same("ARRAY[1, '2', FALSE, NULL]", $result);
} else {
Expand Down
1 change: 1 addition & 0 deletions tests/inc/IntegrationTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ protected function createConnection($params = [])
'user' => null,
'password' => null,
'searchPath' => ['public'],
'sqlProcessorFactory' => new SqlProcessorFactory(),
], Environment::loadData(), $params);
return new Connection($options);
}
Expand Down
30 changes: 30 additions & 0 deletions tests/inc/SqlProcessorFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);

namespace NextrasTests\Dbal;


use Nextras\Dbal\Exception\InvalidArgumentException;
use Nextras\Dbal\IConnection;
use Nextras\Dbal\ISqlProcessorFactory;
use Nextras\Dbal\SqlProcessor;


class SqlProcessorFactory implements ISqlProcessorFactory
{
public function create(IConnection $connection): SqlProcessor
{
$sqlProcessor = new SqlProcessor($connection->getPlatform());
$sqlProcessor->setCustomModifier(
'%pgArray',
function(SqlProcessor $sqlProcessor, $value, string $type) {
if (!is_array($value)) throw new InvalidArgumentException('%pgArray modifier accepts an array only.');
return 'ARRAY[' .
implode(', ', array_map(function($subValue) use ($sqlProcessor): string {
return $sqlProcessor->processModifier('any', $subValue);
}, $value)) .
']';
},
);
return $sqlProcessor;
}
}
Loading