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
20 changes: 18 additions & 2 deletions src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,34 @@

final class ConfigProvider
{
public const NAMED_ADAPTER_KEY = 'adapters';
public function __invoke(): array
{
return [
'dependencies' => $this->getDependencies(),
'dependencies' => $this->getDependencies(),
Adapter\AdapterInterface::class => $this->getConfig(),
];
}

public function getConfig(): array
{
// supported configuration structure
return [
// Adapter\Adapter::class => [],
// Adapter\AdapterInterface::class => [],
// self::NAMED_ADAPTER_KEY => [
// Adapter\Adapter::class => [],
// Adapter\AdapterInterface::class => [],
// 'Custom\Name' => [],
// ],
];
}

public function getDependencies(): array
{
return [
'abstract_factories' => [
Container\AdapterAbstractServiceFactory::class,
Container\AbstractAdapterInterfaceFactory::class,
],
'aliases' => [
Adapter\AdapterInterface::class => Adapter\Adapter::class,
Expand Down
129 changes: 129 additions & 0 deletions src/Container/AbstractAdapterInterfaceFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

declare(strict_types=1);

namespace PhpDb\Container;

use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
use Laminas\ServiceManager\ServiceManager;
use PhpDb\Adapter\Adapter;
use PhpDb\Adapter\AdapterInterface;
use PhpDb\Adapter\Driver\DriverInterface;
use PhpDb\Adapter\Driver\PdoDriverInterface;
use PhpDb\Adapter\Platform\PlatformInterface;
use PhpDb\Adapter\Profiler\ProfilerInterface;
use PhpDb\ConfigProvider;
use PhpDb\Exception\ContainerException;
use PhpDb\ResultSet\ResultSetInterface;
use Psr\Container\ContainerInterface;

use function is_array;

/**
* Database adapter abstract service factory.
*
* Allows configuring several database instances (such as writer and reader).
*
* @internal
*/
class AbstractAdapterInterfaceFactory implements AbstractFactoryInterface
{
protected ?array $config = null;

/**
* Can we create an adapter by the requested name?
*
* @param string $requestedName
*/
public function canCreate(ContainerInterface $container, $requestedName): bool
{
$config = $this->getConfig($container);

if ($config === []) {
return false;
}

return isset($config[$requestedName])
&& is_array($config[$requestedName])
&& ! empty($config[$requestedName]);
}

/**
* Create a DB adapter
*
* @phpstan-param ContainerInterface&ServiceManager $container
* @param string $requestedName
*/
public function __invoke(
ContainerInterface|ServiceManager $container,
$requestedName,
?array $options = null
): AdapterInterface&Adapter {
/** @var string|null $driverClass */
$driverClass = $this->config[$requestedName]['driver'] ?? null;

if ($driverClass === null) {
throw ContainerException::forService(
$requestedName,
self::class,
'no driver configured'
);
}

/** @var DriverInterface|PdoDriverInterface $driver */
$driver = $container->build($driverClass, $this->config[$requestedName]);
/** @var PlatformInterface $platform */
$platform = $container->build(PlatformInterface::class, ['driver' => $driver]);
/** @var ResultSetInterface|null $resultSet */
$resultSet = $container->has(ResultSetInterface::class)
? $container->build(ResultSetInterface::class)
: null;
/** @var ProfilerInterface|null $profiler */
$profiler = $container->has(ProfilerInterface::class)
? $container->build(ProfilerInterface::class)
: null;

return match (true) {
$resultSet !== null && $profiler !== null => new Adapter(
driver: $driver,
platform: $platform,
queryResultSetPrototype: $resultSet,
profiler: $profiler,
),
$resultSet !== null => new Adapter(
driver: $driver,
platform: $platform,
queryResultSetPrototype: $resultSet,
),
$profiler !== null => new Adapter(
driver: $driver,
platform: $platform,
profiler: $profiler,
),
default => new Adapter(
driver: $driver,
platform: $platform,
),
};
}

/**
* Get db configuration, if any
* todo: refactor to use PhpDb\ConfigProvider::NAMED_ADAPTER_KEY instead of hardcoding 'adapters'
*/
protected function getConfig(ContainerInterface $container): array
{
if ($this->config !== null) {
return $this->config;
}

if (! $container->has('config')) {
$this->config = [];
return $this->config;
}

$config = $container->get('config');
$this->config = $config[AdapterInterface::class][ConfigProvider::NAMED_ADAPTER_KEY] ?? [];
return $this->config;
}
}
127 changes: 0 additions & 127 deletions src/Container/AdapterAbstractServiceFactory.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/Container/ConnectionInterfaceFactoryFactoryInterface.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/Container/DriverInterfaceFactoryFactoryInterface.php

This file was deleted.

10 changes: 0 additions & 10 deletions src/Container/FactoryFactoryInterface.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/Container/PlatformInterfaceFactoryFactoryInterface.php

This file was deleted.

29 changes: 29 additions & 0 deletions src/Exception/ContainerException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace PhpDb\Exception;

use Psr\Container\ContainerExceptionInterface;
use RuntimeException as SplRuntimeException;

use function sprintf;

final class ContainerException extends SplRuntimeException implements ContainerExceptionInterface
{
public static function forService(
string $serviceName,
string $factoryClass,
string $reason
): self {
return new self(
sprintf(
'Failed to create service "%s" in factory %s Reason: %s',
$serviceName,
$factoryClass,
$reason
),
0,
);
}
}
Loading