Skip to content

Commit 03d8358

Browse files
committed
Latest revisions - all factory changes
Signed-off-by: Joey Smith <jsmith@webinertia.net> Signed-off-by: Joey Smith <jsmith@webinertia.net>
1 parent 878a412 commit 03d8358

File tree

4 files changed

+264
-49
lines changed

4 files changed

+264
-49
lines changed

src/Container/AdapterFactory.php

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use PhpDb\Adapter\Exception\RuntimeException;
1313
use PhpDb\Adapter\Platform\PlatformInterface;
1414
use PhpDb\Adapter\Profiler\ProfilerInterface;
15-
use PhpDb\ResultSet\ResultSet;
1615
use PhpDb\ResultSet\ResultSetInterface;
1716
use Psr\Container\ContainerInterface;
1817

@@ -38,7 +37,7 @@ public function __invoke(ContainerInterface $container): AdapterInterface
3837

3938
if (! $container->has($driver)) {
4039
throw new ServiceNotFoundException(sprintf(
41-
'Database driver "%s" is not registered in the adapter manager.',
40+
'Database driver "%s" is not registered in the container.',
4241
$driver
4342
));
4443
}
@@ -48,28 +47,32 @@ public function __invoke(ContainerInterface $container): AdapterInterface
4847

4948
if (! $container->has(PlatformInterface::class)) {
5049
throw new ServiceNotFoundException(sprintf(
51-
'Database platform "%s" is not registered in the adapter manager.',
50+
'Database platform "%s" is not registered in the container.',
5251
PlatformInterface::class
5352
));
5453
}
5554

5655
/** @var PlatformInterface $platformInstance */
5756
$platformInstance = $container->get(PlatformInterface::class);
5857

59-
/** @var ResultSetInterface $resultSetInstance */
60-
$resultSetInstance = $container->has(ResultSetInterface::class)
61-
? $container->get(ResultSetInterface::class)
62-
: null;
63-
6458
/** @var ProfilerInterface|null $profilerInstanceOrNull */
6559
$profilerInstanceOrNull = $container->has(ProfilerInterface::class)
6660
? $container->get(ProfilerInterface::class)
6761
: null;
6862

63+
// If its not provided, use the default ResultSet
64+
if (! $container->has(ResultSetInterface::class)) {
65+
return new Adapter(
66+
driver: $driverInstance,
67+
platform: $platformInstance,
68+
profiler: $profilerInstanceOrNull
69+
);
70+
}
71+
6972
return new Adapter(
7073
driver: $driverInstance,
7174
platform: $platformInstance,
72-
queryResultSetPrototype: $resultSetInstance ?? new ResultSet(),
75+
queryResultSetPrototype: $container->get(ResultSetInterface::class),
7376
profiler: $profilerInstanceOrNull
7477
);
7578
}

src/Container/MysqliDriverFactory.php

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpDb\Adapter\Driver;
88
use PhpDb\Adapter\Mysql\Driver\Mysqli;
99
use Psr\Container\ContainerInterface;
10+
use RuntimeException;
1011

1112
/** @internal */
1213
final class MysqliDriverFactory
@@ -25,18 +26,32 @@ public function __invoke(ContainerInterface $container): Driver\DriverInterface&
2526
/** @var Driver\ConnectionInterface&Mysqli\Connection $connectionInstance */
2627
$connectionInstance = $container->get(Mysqli\Connection::class);
2728

28-
/** @var Driver\StatementInterface&Mysqli\Statement $statementInstance */
29-
$statementInstance = $container->get(Mysqli\Statement::class);
29+
$hasStatement = $container->has(Mysqli\Statement::class);
30+
$hasResult = $container->has(Mysqli\Result::class);
3031

31-
/** @var Driver\ResultInterface&Mysqli\Result $resultInstance */
32-
$resultInstance = $container->has(Mysqli\Result::class) ? $container->get(Mysqli\Result::class) : null;
33-
34-
return new Mysqli\Mysqli(
35-
connection: $connectionInstance,
36-
statementPrototype: $statementInstance,
37-
resultPrototype: $resultInstance ?? new Mysqli\Result(),
38-
options: $options
39-
);
32+
return match (true) {
33+
! $hasStatement && ! $hasResult => new Mysqli\Mysqli(
34+
connection: $connectionInstance,
35+
options: $options,
36+
),
37+
$hasStatement && ! $hasResult => new Mysqli\Mysqli(
38+
connection: $connectionInstance,
39+
statementPrototype: $container->get(Mysqli\Statement::class),
40+
options: $options,
41+
),
42+
! $hasStatement && $hasResult => new Mysqli\Mysqli(
43+
connection: $connectionInstance,
44+
resultPrototype: $container->get(Mysqli\Result::class),
45+
options: $options,
46+
),
47+
$hasStatement && $hasResult => new Mysqli\Mysqli(
48+
connection: $connectionInstance,
49+
statementPrototype: $container->get(Mysqli\Statement::class),
50+
resultPrototype: $container->get(Mysqli\Result::class),
51+
options: $options,
52+
),
53+
default => throw new RuntimeException('Unable to create PdoDriver from configuration.'),
54+
};
4055
}
4156

4257
public static function createFromConfig(
@@ -53,11 +68,34 @@ public static function createFromConfig(
5368
/** @var array $adapterConfig */
5469
$adapterConfig = $dbConfig['adapters'][$requestedName] ?? [];
5570

56-
return new Mysqli\Mysqli(
57-
$connectionFactory::createFromConfig($container, $requestedName),
58-
$container->get(Mysqli\Statement::class),
59-
$container->get(Mysqli\Result::class),
60-
$adapterConfig['options'] ?? []
61-
);
71+
/** @var Driver\ConnectionInterface&Mysqli\Connection $connectionInstance */
72+
$connectionInstance = $connectionFactory::createFromConfig($container, $requestedName);
73+
74+
$hasStatement = $container->has(Mysqli\Statement::class);
75+
$hasResult = $container->has(Mysqli\Result::class);
76+
77+
return match (true) {
78+
! $hasStatement && ! $hasResult => new Mysqli\Mysqli(
79+
connection: $connectionInstance,
80+
options: $adapterConfig['options'] ?? [],
81+
),
82+
$hasStatement && ! $hasResult => new Mysqli\Mysqli(
83+
connection: $connectionInstance,
84+
statementPrototype: $container->get(Mysqli\Statement::class),
85+
options: $adapterConfig['options'] ?? [],
86+
),
87+
! $hasStatement && $hasResult => new Mysqli\Mysqli(
88+
connection: $connectionInstance,
89+
resultPrototype: $container->get(Mysqli\Result::class),
90+
options: $adapterConfig['options'] ?? [],
91+
),
92+
$hasStatement && $hasResult => new Mysqli\Mysqli(
93+
connection: $connectionInstance,
94+
statementPrototype: $container->get(Mysqli\Statement::class),
95+
resultPrototype: $container->get(Mysqli\Result::class),
96+
options: $adapterConfig['options'] ?? [],
97+
),
98+
default => throw new RuntimeException('Unable to create PdoDriver from configuration.'),
99+
};
62100
}
63101
}

src/Container/PdoDriverFactory.php

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
use PhpDb\Adapter\Driver\Pdo\Result;
99
use PhpDb\Adapter\Driver\Pdo\Statement;
1010
use PhpDb\Adapter\Driver\PdoDriverInterface;
11-
use PhpDb\Adapter\Driver\ResultInterface;
12-
use PhpDb\Adapter\Driver\StatementInterface;
1311
use PhpDb\Adapter\Mysql\Driver\Pdo\Connection;
1412
use PhpDb\Adapter\Mysql\Driver\Pdo\Pdo as PdoDriver;
1513
use Psr\Container\ContainerInterface;
14+
use RuntimeException;
1615

1716
final class PdoDriverFactory
1817
{
@@ -21,17 +20,28 @@ public function __invoke(ContainerInterface $container): PdoDriverInterface&PdoD
2120
/** @var ConnectionInterface&Connection $connectionInstance */
2221
$connectionInstance = $container->get(Connection::class);
2322

24-
/** @var (StatementInterface&Statement)|null $statementInstance */
25-
$statementInstance = $container->has(Statement::class) ? $container->get(Statement::class) : null;
23+
$hasStatement = $container->has(Statement::class);
24+
$hasResult = $container->has(Result::class);
2625

27-
/** @var (ResultInterface&Result)|null $resultInstance */
28-
$resultInstance = $container->has(Result::class) ? $container->get(Result::class) : null;
29-
30-
return new PdoDriver(
31-
connection: $connectionInstance,
32-
statementPrototype: $statementInstance ?? new Statement(),
33-
resultPrototype: $resultInstance ?? new Result(),
34-
);
26+
return match (true) {
27+
! $hasStatement && ! $hasResult => new PdoDriver(
28+
connection: $connectionInstance,
29+
),
30+
$hasStatement && ! $hasResult => new PdoDriver(
31+
connection: $connectionInstance,
32+
statementPrototype: $container->get(Statement::class),
33+
),
34+
! $hasStatement && $hasResult => new PdoDriver(
35+
connection: $connectionInstance,
36+
resultPrototype: $container->get(Result::class),
37+
),
38+
$hasStatement && $hasResult => new PdoDriver(
39+
connection: $connectionInstance,
40+
statementPrototype: $container->get(Statement::class),
41+
resultPrototype: $container->get(Result::class),
42+
),
43+
default => throw new RuntimeException('Unable to create PdoDriver'),
44+
};
3545
}
3646

3747
public static function createFromConfig(
@@ -45,21 +55,31 @@ public static function createFromConfig(
4555
$config = $container->get('config');
4656
/** @var array $dbConfig */
4757
$dbConfig = $config['db'] ?? [];
48-
/** @var array $adapterConfig */
49-
$adapterConfig = $dbConfig['adapters'][$requestedName] ?? [];
5058

5159
/** @var ConnectionInterface&Connection $connectionInstance */
5260
$connectionInstance = $connectionFactory::createFromConfig($container, $requestedName);
5361

54-
/** @var (StatementInterface&Statement)|null $statementInstance */
55-
$statementInstance = $container->has(Statement::class) ? $container->get(Statement::class) : null;
62+
$hasStatement = $container->has(Statement::class);
63+
$hasResult = $container->has(Result::class);
5664

57-
/** @var (ResultInterface&Result)|null $resultInstance */
58-
$resultInstance = $container->has(Result::class) ? $container->get(Result::class) : null;
59-
return new PdoDriver(
60-
$connectionInstance,
61-
$statementInstance ?? new Statement(),
62-
$resultInstance ?? new Result(),
63-
);
65+
return match (true) {
66+
! $hasStatement && ! $hasResult => new PdoDriver(
67+
connection: $connectionInstance,
68+
),
69+
$hasStatement && ! $hasResult => new PdoDriver(
70+
connection: $connectionInstance,
71+
statementPrototype: $container->get(Statement::class),
72+
),
73+
! $hasStatement && $hasResult => new PdoDriver(
74+
connection: $connectionInstance,
75+
resultPrototype: $container->get(Result::class),
76+
),
77+
$hasStatement && $hasResult => new PdoDriver(
78+
connection: $connectionInstance,
79+
statementPrototype: $container->get(Statement::class),
80+
resultPrototype: $container->get(Result::class),
81+
),
82+
default => throw new RuntimeException('Unable to create PdoDriver from configuration.'),
83+
};
6484
}
6585
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpDbTest\Adapter;
6+
7+
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
8+
use Laminas\ServiceManager\ServiceManager;
9+
use Laminas\Stdlib\ArrayUtils;
10+
use Override;
11+
use PhpDb\Adapter\AdapterInterface;
12+
use PhpDb\Adapter\Mysql\ConfigProvider;
13+
use PhpDb\Adapter\Mysql\Driver\Mysqli\Mysqli;
14+
use PhpDb\Adapter\Mysql\Driver\Pdo\Pdo;
15+
use PhpDb\ConfigProvider as LaminasDbConfigProvider;
16+
use PhpDb\Container\AdapterAbstractServiceFactory;
17+
use PHPUnit\Framework\Attributes\CoversClass;
18+
use PHPUnit\Framework\Attributes\DataProvider;
19+
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
20+
use PHPUnit\Framework\TestCase;
21+
use Psr\Container\ContainerExceptionInterface;
22+
use Psr\Container\ContainerInterface;
23+
use Psr\Container\NotFoundExceptionInterface;
24+
25+
use function getenv;
26+
27+
#[RequiresPhpExtension('mysqli')]
28+
#[RequiresPhpExtension('pdo_mysql')]
29+
#[CoversClass(AdapterAbstractServiceFactory::class)]
30+
final class AdapterAbstractServiceFactoryTest extends TestCase
31+
{
32+
private ContainerInterface $serviceManager;
33+
34+
#[Override]
35+
protected function setUp(): void
36+
{
37+
$this->serviceManager = $this->buildContainer();
38+
parent::setUp();
39+
}
40+
41+
protected function buildContainer(array $config = []): ContainerInterface
42+
{
43+
$readAdapterConfig = [
44+
'db' => [
45+
'adapters' => [
46+
'PhpDb\Adapter\Reader' => [
47+
'driver' => Pdo::class,
48+
'connection' => [
49+
'hostname' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_HOSTNAME') ?: 'localhost',
50+
'username' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_USERNAME'),
51+
'password' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_PASSWORD'),
52+
'database' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_DATABASE'),
53+
'port' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_PORT') ?: '3306',
54+
'charset' => 'utf8',
55+
'driver_options' => [],
56+
],
57+
'options' => [
58+
'buffer_results' => false,
59+
],
60+
],
61+
],
62+
],
63+
];
64+
65+
$writeAdapterConfig = [
66+
'db' => [
67+
'adapters' => [
68+
'PhpDb\Adapter\Writer' => [
69+
'driver' => Mysqli::class,
70+
'connection' => [
71+
'hostname' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_HOSTNAME') ?: 'localhost',
72+
'username' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_USERNAME'),
73+
'password' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_PASSWORD'),
74+
'database' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_DATABASE'),
75+
'port' => (string) getenv('TESTS_PHPDB_ADAPTER_MYSQL_PORT') ?: '3306',
76+
'charset' => 'utf8',
77+
'driver_options' => [],
78+
],
79+
'options' => [
80+
'buffer_results' => false,
81+
],
82+
],
83+
],
84+
],
85+
];
86+
87+
$adapterConfig = ArrayUtils::merge($readAdapterConfig, $writeAdapterConfig);
88+
89+
// merge service config from both PhpDb and PhpDb\Adapter\Mysql
90+
$serviceManagerConfig = ArrayUtils::merge(
91+
(new LaminasDbConfigProvider())()['dependencies'],
92+
(new ConfigProvider())()['dependencies']
93+
);
94+
95+
$serviceManagerConfig = ArrayUtils::merge(
96+
$serviceManagerConfig,
97+
$adapterConfig
98+
);
99+
100+
// prefer passed config over environment variables
101+
if ($config !== []) {
102+
$serviceManagerConfig = ArrayUtils::merge($serviceManagerConfig, $config);
103+
}
104+
105+
$serviceManagerConfig = ArrayUtils::merge(
106+
$serviceManagerConfig,
107+
[
108+
'services' => [
109+
'config' => $serviceManagerConfig,
110+
],
111+
]
112+
);
113+
114+
$config = $serviceManagerConfig;
115+
return new ServiceManager($config);
116+
}
117+
118+
public static function providerValidService(): array
119+
{
120+
return [
121+
['PhpDb\Adapter\Writer'],
122+
['PhpDb\Adapter\Reader'],
123+
];
124+
}
125+
126+
public static function providerInvalidService(): array
127+
{
128+
return [
129+
['PhpDb\Adapter\Unknown'],
130+
];
131+
}
132+
133+
/**
134+
* @throws ContainerExceptionInterface
135+
* @throws NotFoundExceptionInterface
136+
*/
137+
#[DataProvider('providerValidService')]
138+
public function testValidService(string $service): void
139+
{
140+
$actual = $this->serviceManager->get($service);
141+
self::assertInstanceOf(AdapterInterface::class, $actual);
142+
}
143+
144+
/**
145+
* @throws ContainerExceptionInterface
146+
* @throws NotFoundExceptionInterface
147+
*/
148+
#[DataProvider('providerInvalidService')]
149+
public function testInvalidService(string $service): void
150+
{
151+
$this->expectException(ServiceNotFoundException::class);
152+
$this->serviceManager->get($service);
153+
}
154+
}

0 commit comments

Comments
 (0)