From 18ac071c5db05617ce01188bdf5c1a42f95fc567 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 27 Jul 2021 12:41:12 +0300 Subject: [PATCH] orm pdo provider --- .../Espo/Core/ORM/EntityManagerFactory.php | 66 ++++++--- application/Espo/ORM/DatabaseParams.php | 15 --- application/Espo/ORM/EntityManager.php | 113 ++-------------- .../Espo/ORM/PDO/DefaultPDOProvider.php | 126 ++++++++++++++++++ application/Espo/ORM/PDO/PDOProvider.php | 37 +++++ 5 files changed, 225 insertions(+), 132 deletions(-) create mode 100644 application/Espo/ORM/PDO/DefaultPDOProvider.php create mode 100644 application/Espo/ORM/PDO/PDOProvider.php diff --git a/application/Espo/Core/ORM/EntityManagerFactory.php b/application/Espo/Core/ORM/EntityManagerFactory.php index cf1735d13a..dcd2db0dd3 100644 --- a/application/Espo/Core/ORM/EntityManagerFactory.php +++ b/application/Espo/Core/ORM/EntityManagerFactory.php @@ -40,6 +40,10 @@ use Espo\ORM\Repository\RepositoryFactory as RepositoryFactoryInterface; use Espo\ORM\EntityFactory as EntityFactoryInteface; use Espo\ORM\Value\ValueFactoryFactory as ValueFactoryFactoryInteface; use Espo\ORM\Value\AttributeExtractorFactory as AttributeExtractorFactoryInteface; +use Espo\ORM\PDO\PDOProvider; +use Espo\ORM\PDO\DefaultPDOProvider; + +use RuntimeException; class EntityManagerFactory { @@ -51,6 +55,11 @@ class EntityManagerFactory private $eventDispatcher; + private $driverPlatformMap = [ + 'pdo_mysql' => 'Mysql', + 'mysqli' => 'Mysql', + ]; + public function __construct( Config $config, InjectableFactory $injectableFactory, @@ -74,23 +83,7 @@ class EntityManagerFactory ->build() ); - $config = $this->config; - - $databaseParams = DatabaseParams::create() - ->withHost($config->get('database.host')) - ->withPort($config->get('database.port') ? (int) $config->get('database.port') : null) - ->withName($config->get('database.dbname')) - ->withUsername($config->get('database.user')) - ->withPassword($config->get('database.password')) - ->withCharset($config->get('database.charset') ?? 'utf8') - ->withDriver($config->get('database.driver')) - ->withPlatform($config->get('database.platform')) - ->withSslCa($config->get('database.sslCA')) - ->withSslCert($config->get('database.sslCert')) - ->withSslKey($config->get('database.sslKey')) - ->withSslCaPath($config->get('database.sslCAPath')) - ->withSslCipher($config->get('database.sslCipher')) - ->withSslVerifyDisabled($config->get('database.sslVerifyDisabled') ?? false); + $databaseParams = $this->createDatabaseParams(); $metadata = new Metadata($this->metadataDataProvider, $this->eventDispatcher); @@ -116,8 +109,47 @@ class EntityManagerFactory ->bindInstance(ValueFactoryFactoryInteface::class, $valueFactoryFactory) ->bindInstance(AttributeExtractorFactoryInteface::class, $attributeExtractorFactory) ->bindInstance(EventDispatcher::class, $this->eventDispatcher) + ->bindImplementation(PDOProvider::class, DefaultPDOProvider::class) ->build(); return $this->injectableFactory->createWithBinding(EntityManager::class, $binding); } + + private function createDatabaseParams(): DatabaseParams + { + $config = $this->config; + + $databaseParams = DatabaseParams::create() + ->withHost($config->get('database.host')) + ->withPort($config->get('database.port') ? (int) $config->get('database.port') : null) + ->withName($config->get('database.dbname')) + ->withUsername($config->get('database.user')) + ->withPassword($config->get('database.password')) + ->withCharset($config->get('database.charset') ?? 'utf8') + ->withPlatform($config->get('database.platform')) + ->withSslCa($config->get('database.sslCA')) + ->withSslCert($config->get('database.sslCert')) + ->withSslKey($config->get('database.sslKey')) + ->withSslCaPath($config->get('database.sslCAPath')) + ->withSslCipher($config->get('database.sslCipher')) + ->withSslVerifyDisabled($config->get('database.sslVerifyDisabled') ?? false); + + if (!$databaseParams->getPlatform()) { + $driver = $config->get('database.driver'); + + if (!$driver) { + throw new RuntimeException('No database driver specified.'); + } + + $platform = $this->driverPlatformMap[$driver] ?? null; + + if (!$platform) { + throw new RuntimeException("Database driver '{$driver}' is not supported."); + } + + $databaseParams = $databaseParams->withPlatform($platform); + } + + return $databaseParams; + } } diff --git a/application/Espo/ORM/DatabaseParams.php b/application/Espo/ORM/DatabaseParams.php index f2f0693b04..45233937c1 100644 --- a/application/Espo/ORM/DatabaseParams.php +++ b/application/Espo/ORM/DatabaseParams.php @@ -45,8 +45,6 @@ class DatabaseParams private $charset = null; - private $driver = null; - private $sslCa = null; private $sslCert = null; @@ -99,11 +97,6 @@ class DatabaseParams return $this->charset; } - public function getDriver(): ?string - { - return $this->driver; - } - public function getSslCa(): ?string { return $this->sslCa; @@ -190,14 +183,6 @@ class DatabaseParams return $obj; } - public function withDriver(?string $driver): self - { - $obj = clone $this; - $obj->driver = $driver; - - return $obj; - } - public function withSslCa(?string $sslCa): self { $obj = clone $this; diff --git a/application/Espo/ORM/EntityManager.php b/application/Espo/ORM/EntityManager.php index 603f6c292c..e393003646 100644 --- a/application/Espo/ORM/EntityManager.php +++ b/application/Espo/ORM/EntityManager.php @@ -47,6 +47,8 @@ use Espo\ORM\Value\ValueAccessorFactory; use Espo\ORM\Value\ValueFactoryFactory; use Espo\ORM\Value\AttributeExtractorFactory; +use Espo\ORM\PDO\PDOProvider; + use PDO; use RuntimeException; @@ -55,8 +57,6 @@ use RuntimeException; */ class EntityManager { - private $pdo = null; - private $entityFactory; private $collectionFactory; @@ -88,12 +88,9 @@ class EntityManager private $locker; - private const RDB_MAPPER_NAME = 'RDB'; + private $pdoProvider; - protected $driverPlatformMap = [ - 'pdo_mysql' => 'Mysql', - 'mysqli' => 'Mysql', - ]; + private const RDB_MAPPER_NAME = 'RDB'; public function __construct( DatabaseParams $databaseParams, @@ -103,6 +100,7 @@ class EntityManager ValueFactoryFactory $valueFactoryFactory, AttributeExtractorFactory $attributeExtractorFactory, EventDispatcher $eventDispatcher, + PDOProvider $pdoProvider, ?MapperFactory $mapperFactory = null ) { $this->databaseParams = $databaseParams; @@ -111,21 +109,10 @@ class EntityManager $this->entityFactory = $entityFactory; $this->repositoryFactory = $repositoryFactory; $this->mapperFactory = $mapperFactory; + $this->pdoProvider = $pdoProvider; if (!$this->databaseParams->getPlatform()) { - $driver = $this->databaseParams->getDriver(); - - if (!$driver) { - throw new RuntimeException('No database driver specified.'); - } - - $platform = $this->driverPlatformMap[$driver] ?? null; - - if (!$platform) { - throw new RuntimeException("Database driver '{$driver}' is not supported."); - } - - $this->databaseParams = $this->databaseParams->withPlatform($platform); + throw new RuntimeException("No 'platform' parameter."); } $valueAccessorFactory = new ValueAccessorFactory( @@ -139,11 +126,11 @@ class EntityManager $this->initQueryComposer(); - $this->sqlExecutor = new SqlExecutor($this->getPDO()); + $this->sqlExecutor = new SqlExecutor($this->pdoProvider->get()); $this->queryExecutor = new QueryExecutor($this->sqlExecutor, $this->queryComposer); $this->queryBuilder = new QueryBuilder(); $this->collectionFactory = new CollectionFactory($this); - $this->transactionManager = new TransactionManager($this->getPDO(), $this->queryComposer); + $this->transactionManager = new TransactionManager($this->pdoProvider->get(), $this->queryComposer); $this->initLocker(); } @@ -158,7 +145,7 @@ class EntityManager throw new RuntimeException("Query composer for '{$platform}' platform does not exits."); } - $this->queryComposer = new $className($this->getPDO(), $this->entityFactory, $this->metadata); + $this->queryComposer = new $className($this->pdoProvider->get(), $this->entityFactory, $this->metadata); } private function initLocker(): void @@ -171,7 +158,7 @@ class EntityManager $className = BaseLocker::class; } - $this->locker = new $className($this->getPDO(), $this->queryComposer, $this->transactionManager); + $this->locker = new $className($this->pdoProvider->get(), $this->queryComposer, $this->transactionManager); } /** @@ -216,7 +203,7 @@ class EntityManager $className = $this->getRDBMapperClassName(); $this->mappers[$name] = new $className( - $this->getPDO(), + $this->pdoProvider->get(), $this->entityFactory, $this->collectionFactory, $this->getQueryComposer(), @@ -247,76 +234,6 @@ class EntityManager return $className; } - private function initPDO(): void - { - $platform = strtolower($this->databaseParams->getPlatform() ?? ''); - - $host = $this->databaseParams->getHost(); - $port = $this->databaseParams->getPort(); - $dbname = $this->databaseParams->getName(); - $charset = $this->databaseParams->getCharset(); - $username = $this->databaseParams->getUsername(); - $password = $this->databaseParams->getPassword(); - - if (!$platform) { - throw new RuntimeException("No 'platform' parameter."); - } - - if (!$host) { - throw new RuntimeException("No 'host' parameter."); - } - - if (!$dbname) { - throw new RuntimeException("No 'dbname' parameter."); - } - - $dsn = - $platform . ':' . - 'host=' . $host; - - if ($port) { - $dsn .= ';' . 'port=' . (string) $port; - } - - if ($dbname) { - $dsn .= ';' . 'dbname=' . $dbname; - } - - if ($charset) { - $dsn .= ';' . 'charset=' . $charset; - } - - $options = []; - - if ($this->databaseParams->getSslCa()) { - $options[PDO::MYSQL_ATTR_SSL_CA] = $this->databaseParams->getSslCa(); - } - - if ($this->databaseParams->getSslCert()) { - $options[PDO::MYSQL_ATTR_SSL_CERT] = $this->databaseParams->getSslCert(); - } - - if ($this->databaseParams->getSslKey()) { - $options[PDO::MYSQL_ATTR_SSL_KEY] = $this->databaseParams->getSslKey(); - } - - if ($this->databaseParams->getSslCaPath()) { - $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->databaseParams->getSslCaPath(); - } - - if ($this->databaseParams->getSslCipher()) { - $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->databaseParams->getSslCipher(); - } - - if ($this->databaseParams->isSslVerifyDisabled()) { - $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; - } - - $this->pdo = new PDO($dsn, $username, $password, $options); - - $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } - /** * Get an entity. If $id is null, a new entity instance is created. * If an entity with a specified ID does not exist, then NULL is returned. @@ -458,11 +375,7 @@ class EntityManager */ public function getPDO(): PDO { - if ($this->pdo === null) { - $this->initPDO(); - } - - return $this->pdo; + return $this->pdoProvider->get(); } /** diff --git a/application/Espo/ORM/PDO/DefaultPDOProvider.php b/application/Espo/ORM/PDO/DefaultPDOProvider.php new file mode 100644 index 0000000000..782a446537 --- /dev/null +++ b/application/Espo/ORM/PDO/DefaultPDOProvider.php @@ -0,0 +1,126 @@ +databaseParams = $databaseParams; + } + + public function get(): PDO + { + if (!$this->pdo) { + $this->intPDO(); + } + + return $this->pdo; + } + + private function intPDO(): void + { + $platform = strtolower($this->databaseParams->getPlatform() ?? ''); + + $host = $this->databaseParams->getHost(); + $port = $this->databaseParams->getPort(); + $dbname = $this->databaseParams->getName(); + $charset = $this->databaseParams->getCharset(); + $username = $this->databaseParams->getUsername(); + $password = $this->databaseParams->getPassword(); + + if (!$platform) { + throw new RuntimeException("No 'platform' parameter."); + } + + if (!$host) { + throw new RuntimeException("No 'host' parameter."); + } + + if (!$dbname) { + throw new RuntimeException("No 'dbname' parameter."); + } + + $dsn = + $platform . ':' . + 'host=' . $host; + + if ($port) { + $dsn .= ';' . 'port=' . (string) $port; + } + + if ($dbname) { + $dsn .= ';' . 'dbname=' . $dbname; + } + + if ($charset) { + $dsn .= ';' . 'charset=' . $charset; + } + + $options = []; + + if ($this->databaseParams->getSslCa()) { + $options[PDO::MYSQL_ATTR_SSL_CA] = $this->databaseParams->getSslCa(); + } + + if ($this->databaseParams->getSslCert()) { + $options[PDO::MYSQL_ATTR_SSL_CERT] = $this->databaseParams->getSslCert(); + } + + if ($this->databaseParams->getSslKey()) { + $options[PDO::MYSQL_ATTR_SSL_KEY] = $this->databaseParams->getSslKey(); + } + + if ($this->databaseParams->getSslCaPath()) { + $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->databaseParams->getSslCaPath(); + } + + if ($this->databaseParams->getSslCipher()) { + $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->databaseParams->getSslCipher(); + } + + if ($this->databaseParams->isSslVerifyDisabled()) { + $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; + } + + $this->pdo = new PDO($dsn, $username, $password, $options); + + $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } +} diff --git a/application/Espo/ORM/PDO/PDOProvider.php b/application/Espo/ORM/PDO/PDOProvider.php new file mode 100644 index 0000000000..e9e392c7c7 --- /dev/null +++ b/application/Espo/ORM/PDO/PDOProvider.php @@ -0,0 +1,37 @@ +