TestUtil.php 5.41 KB
Newer Older
1
<?php
romanb's avatar
romanb committed
2

3
namespace Doctrine\Tests;
romanb's avatar
romanb committed
4

5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\DriverManager;
7
use PHPUnit\Framework\Assert;
8 9 10
use function explode;
use function extension_loaded;
use function unlink;
11

romanb's avatar
romanb committed
12 13 14
/**
 * TestUtil is a class with static utility methods used during tests.
 */
15
class TestUtil
16
{
Sergei Morozov's avatar
Sergei Morozov committed
17
    /** @var bool Whether the database schema is initialized. */
18 19
    private static $initialized = false;

romanb's avatar
romanb committed
20
    /**
21
     * Creates a new <b>test</b> database connection using the following parameters
romanb's avatar
romanb committed
22
     * of the $GLOBALS array:
23
     *
24 25 26 27 28 29 30 31
     * '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.
32
     *
romanb's avatar
romanb committed
33 34 35
     * 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.
36
     *
37
     * @return Connection The database connection instance.
romanb's avatar
romanb committed
38
     */
39
    public static function getConnection() : Connection
romanb's avatar
romanb committed
40
    {
41 42 43 44 45
        if (self::hasRequiredConnectionParams() && ! self::$initialized) {
            self::initializeDatabase();
            self::$initialized = true;
        }

46
        $conn = DriverManager::getConnection(self::getConnectionParams());
47

48
        self::addDbEventSubscribers($conn);
49

50 51
        return $conn;
    }
52

53 54 55 56
    /**
     * @return mixed[]
     */
    public static function getConnectionParams() : array
Sergei Morozov's avatar
Sergei Morozov committed
57
    {
58
        if (self::hasRequiredConnectionParams()) {
59
            return self::getTestConnectionParameters();
60 61
        }

62
        return self::getFallbackConnectionParams();
romanb's avatar
romanb committed
63
    }
64

65
    private static function hasRequiredConnectionParams() : bool
66
    {
67
        return isset($GLOBALS['db_driver']);
68 69
    }

70
    private static function initializeDatabase() : void
Sergei Morozov's avatar
Sergei Morozov committed
71
    {
72 73
        $testConnParams = self::getTestConnectionParameters();
        $privConnParams = self::getPrivilegedConnectionParameters();
74

75
        $testConn = DriverManager::getConnection($testConnParams);
76

77 78
        // Connect as a privileged user to create and drop the test database.
        $privConn = DriverManager::getConnection($privConnParams);
79

80
        $platform = $privConn->getDatabasePlatform();
81

82
        if ($platform->supportsCreateDropDatabase()) {
83 84
            $dbname = $testConn->getDatabase();
            $testConn->close();
85

86
            $privConn->getSchemaManager()->dropAndCreateDatabase($dbname);
87

88
            $privConn->close();
89
        } else {
90
            $sm = $testConn->getSchemaManager();
91

92
            $schema = $sm->createSchema();
93
            $stmts  = $schema->toDropSql($testConn->getDatabasePlatform());
94

95
            foreach ($stmts as $stmt) {
96
                $testConn->exec($stmt);
97 98 99 100
            }
        }
    }

101 102 103 104
    /**
     * @return mixed[]
     */
    private static function getFallbackConnectionParams() : array
105
    {
Sergei Morozov's avatar
Sergei Morozov committed
106
        if (! extension_loaded('pdo_sqlite')) {
107 108 109
            Assert::markTestSkipped('PDO SQLite extension is not loaded');
        }

Sergei Morozov's avatar
Sergei Morozov committed
110
        $params = [
111
            'driver' => 'pdo_sqlite',
Sergei Morozov's avatar
Sergei Morozov committed
112 113
            'memory' => true,
        ];
114 115 116 117 118 119 120 121 122

        if (isset($GLOBALS['db_path'])) {
            $params['path'] = $GLOBALS['db_path'];
            unlink($GLOBALS['db_path']);
        }

        return $params;
    }

123
    private static function addDbEventSubscribers(Connection $conn) : void
Sergei Morozov's avatar
Sergei Morozov committed
124 125 126 127 128 129 130 131 132
    {
        if (! isset($GLOBALS['db_event_subscribers'])) {
            return;
        }

        $evm = $conn->getEventManager();
        foreach (explode(',', $GLOBALS['db_event_subscribers']) as $subscriberClass) {
            $subscriberInstance = new $subscriberClass();
            $evm->addEventSubscriber($subscriberInstance);
133 134 135
        }
    }

136 137 138
    /**
     * @return mixed[]
     */
139
    private static function getPrivilegedConnectionParameters() : array
140
    {
141 142
        if (isset($GLOBALS['tmpdb_driver'])) {
            return self::mapConnectionParameters($GLOBALS, 'tmpdb_');
143 144
        }

145 146
        $parameters = self::mapConnectionParameters($GLOBALS, 'db_');
        unset($parameters['dbname']);
147

148
        return $parameters;
149 150
    }

151 152 153
    /**
     * @return mixed[]
     */
154
    private static function getTestConnectionParameters() : array
155
    {
156 157
        return self::mapConnectionParameters($GLOBALS, 'db_');
    }
158

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    /**
     * @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;
            }
181

182
            $parameters[$parameter] = $configuration[$prefix . $parameter];
183 184
        }

185
        return $parameters;
186 187
    }

188
    public static function getPrivilegedConnection() : Connection
189
    {
190
        return DriverManager::getConnection(self::getPrivilegedConnectionParameters());
191
    }
192
}