<?php namespace Doctrine\Tests; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Platforms\AbstractPlatform; use PHPUnit\Framework\Assert; use function array_keys; use function array_map; use function array_values; use function explode; use function extension_loaded; use function implode; use function is_string; use function unlink; /** * TestUtil is a class with static utility methods used during tests. */ class TestUtil { /** @var bool Whether the database schema is initialized. */ private static $initialized = false; /** * Creates a new <b>test</b> database connection using the following parameters * of the $GLOBALS array: * * 'db_driver': The name of the Doctrine DBAL database driver to use. * 'db_user': The username to use for connecting. * 'db_password': The password to use for connecting. * 'db_host': The hostname of the database to connect to. * 'db_server': The server name of the database to connect to * (optional, some vendors allow multiple server instances with different names on the same host). * 'db_dbname': The name of the database to connect to. * 'db_port': The port of the database to connect to. * * Usually these variables of the $GLOBALS array are filled by PHPUnit based * on an XML configuration file. If no such parameters exist, an SQLite * in-memory database is used. * * @return Connection The database connection instance. */ public static function getConnection(): Connection { if (self::hasRequiredConnectionParams() && ! self::$initialized) { self::initializeDatabase(); self::$initialized = true; } $conn = DriverManager::getConnection(self::getConnectionParams()); self::addDbEventSubscribers($conn); return $conn; } /** * @return mixed[] */ public static function getConnectionParams(): array { if (self::hasRequiredConnectionParams()) { return self::getTestConnectionParameters(); } return self::getFallbackConnectionParams(); } private static function hasRequiredConnectionParams(): bool { return isset($GLOBALS['db_driver']); } private static function initializeDatabase(): void { $testConnParams = self::getTestConnectionParameters(); $privConnParams = self::getPrivilegedConnectionParameters(); $testConn = DriverManager::getConnection($testConnParams); // Connect as a privileged user to create and drop the test database. $privConn = DriverManager::getConnection($privConnParams); $platform = $privConn->getDatabasePlatform(); if ($platform->supportsCreateDropDatabase()) { $dbname = $testConn->getDatabase(); $testConn->close(); $privConn->getSchemaManager()->dropAndCreateDatabase($dbname); $privConn->close(); } else { $sm = $testConn->getSchemaManager(); $schema = $sm->createSchema(); $stmts = $schema->toDropSql($testConn->getDatabasePlatform()); foreach ($stmts as $stmt) { $testConn->exec($stmt); } } } /** * @return mixed[] */ private static function getFallbackConnectionParams(): array { if (! extension_loaded('pdo_sqlite')) { Assert::markTestSkipped('PDO SQLite extension is not loaded'); } $params = [ 'driver' => 'pdo_sqlite', 'memory' => true, ]; if (isset($GLOBALS['db_path'])) { $params['path'] = $GLOBALS['db_path']; unlink($GLOBALS['db_path']); } return $params; } private static function addDbEventSubscribers(Connection $conn): void { if (! isset($GLOBALS['db_event_subscribers'])) { return; } $evm = $conn->getEventManager(); foreach (explode(',', $GLOBALS['db_event_subscribers']) as $subscriberClass) { $subscriberInstance = new $subscriberClass(); $evm->addEventSubscriber($subscriberInstance); } } /** * @return mixed[] */ private static function getPrivilegedConnectionParameters(): array { if (isset($GLOBALS['tmpdb_driver'])) { return self::mapConnectionParameters($GLOBALS, 'tmpdb_'); } $parameters = self::mapConnectionParameters($GLOBALS, 'db_'); unset($parameters['dbname']); return $parameters; } /** * @return mixed[] */ private static function getTestConnectionParameters(): array { return self::mapConnectionParameters($GLOBALS, 'db_'); } /** * @param array<string,mixed> $configuration * * @return array<string,mixed> */ private static function mapConnectionParameters(array $configuration, string $prefix): array { $parameters = []; foreach ( [ 'driver', 'user', 'password', 'host', 'dbname', 'port', 'server', 'unix_socket', ] as $parameter ) { if (! isset($configuration[$prefix . $parameter])) { continue; } $parameters[$parameter] = $configuration[$prefix . $parameter]; } return $parameters; } public static function getPrivilegedConnection(): Connection { return DriverManager::getConnection(self::getPrivilegedConnectionParameters()); } /** * Generates a query that will return the given rows without the need to create a temporary table. * * @param array<int,array<string,mixed>> $rows */ public static function generateResultSetQuery(array $rows, AbstractPlatform $platform): string { return implode(' UNION ALL ', array_map(static function (array $row) use ($platform): string { return $platform->getDummySelectSQL( implode(', ', array_map(static function (string $column, $value) use ($platform): string { if (is_string($value)) { $value = $platform->quoteStringLiteral($value); } return $value . ' ' . $platform->quoteIdentifier($column); }, array_keys($row), array_values($row))) ); }, $rows)); } }