TestUtil.php 6.17 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 22
    /**
     * Gets a <b>real</b> database connection using the following parameters
     * of the $GLOBALS array:
23
     *
romanb's avatar
romanb committed
24 25 26 27
     * 'db_type' : The name of the Doctrine DBAL database driver to use.
     * 'db_username' : The username to use for connecting.
     * 'db_password' : The password to use for connecting.
     * 'db_host' : The hostname of the database to connect to.
28 29
     * '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).
romanb's avatar
romanb committed
30 31
     * 'db_name' : 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
     * IMPORTANT: Each invocation of this method returns a NEW database connection.
38
     *
39
     * @return Connection The database connection instance.
romanb's avatar
romanb committed
40
     */
41
    public static function getConnection() : Connection
romanb's avatar
romanb committed
42
    {
43 44 45 46 47
        if (self::hasRequiredConnectionParams() && ! self::$initialized) {
            self::initializeDatabase();
            self::$initialized = true;
        }

48
        $conn = DriverManager::getConnection(self::getConnectionParams());
49

50
        self::addDbEventSubscribers($conn);
51

52 53
        return $conn;
    }
54

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

64
        return self::getFallbackConnectionParams();
romanb's avatar
romanb committed
65
    }
66

67
    private static function hasRequiredConnectionParams() : bool
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    {
        return isset(
            $GLOBALS['db_type'],
            $GLOBALS['db_username'],
            $GLOBALS['db_password'],
            $GLOBALS['db_host'],
            $GLOBALS['db_name'],
            $GLOBALS['db_port']
        )
        && isset(
            $GLOBALS['tmpdb_type'],
            $GLOBALS['tmpdb_username'],
            $GLOBALS['tmpdb_password'],
            $GLOBALS['tmpdb_host'],
            $GLOBALS['tmpdb_port']
        );
    }

86
    private static function initializeDatabase() : void
Sergei Morozov's avatar
Sergei Morozov committed
87
    {
88
        $realDbParams = self::getParamsForMainConnection();
Sergei Morozov's avatar
Sergei Morozov committed
89
        $tmpDbParams  = self::getParamsForTemporaryConnection();
90 91 92 93 94 95

        $realConn = DriverManager::getConnection($realDbParams);

        // Connect to tmpdb in order to drop and create the real test db.
        $tmpConn = DriverManager::getConnection($tmpDbParams);

Sergei Morozov's avatar
Sergei Morozov committed
96
        $platform = $tmpConn->getDatabasePlatform();
97

98 99 100
        if ($platform->supportsCreateDropDatabase()) {
            $dbname = $realConn->getDatabase();
            $realConn->close();
101

102
            $tmpConn->getSchemaManager()->dropAndCreateDatabase($dbname);
103

104 105 106
            $tmpConn->close();
        } else {
            $sm = $realConn->getSchemaManager();
107

108 109
            $schema = $sm->createSchema();
            $stmts  = $schema->toDropSql($realConn->getDatabasePlatform());
110

111 112
            foreach ($stmts as $stmt) {
                $realConn->exec($stmt);
113 114 115 116
            }
        }
    }

117 118 119 120
    /**
     * @return mixed[]
     */
    private static function getFallbackConnectionParams() : array
121
    {
Sergei Morozov's avatar
Sergei Morozov committed
122
        if (! extension_loaded('pdo_sqlite')) {
123 124 125
            Assert::markTestSkipped('PDO SQLite extension is not loaded');
        }

Sergei Morozov's avatar
Sergei Morozov committed
126
        $params = [
127
            'driver' => 'pdo_sqlite',
Sergei Morozov's avatar
Sergei Morozov committed
128 129
            'memory' => true,
        ];
130 131 132 133 134 135 136 137 138

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

        return $params;
    }

139
    private static function addDbEventSubscribers(Connection $conn) : void
Sergei Morozov's avatar
Sergei Morozov committed
140 141 142 143 144 145 146 147 148
    {
        if (! isset($GLOBALS['db_event_subscribers'])) {
            return;
        }

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

152 153 154 155
    /**
     * @return mixed[]
     */
    private static function getParamsForTemporaryConnection() : array
156
    {
Sergei Morozov's avatar
Sergei Morozov committed
157
        $connectionParams = [
158 159 160 161
            'driver' => $GLOBALS['tmpdb_type'],
            'user' => $GLOBALS['tmpdb_username'],
            'password' => $GLOBALS['tmpdb_password'],
            'host' => $GLOBALS['tmpdb_host'],
162
            'dbname' => null,
Sergei Morozov's avatar
Sergei Morozov committed
163 164
            'port' => $GLOBALS['tmpdb_port'],
        ];
165

166 167 168 169
        if (isset($GLOBALS['tmpdb_name'])) {
            $connectionParams['dbname'] = $GLOBALS['tmpdb_name'];
        }

170
        if (isset($GLOBALS['tmpdb_server'])) {
171 172 173 174 175 176 177 178 179 180
            $connectionParams['server'] = $GLOBALS['tmpdb_server'];
        }

        if (isset($GLOBALS['tmpdb_unix_socket'])) {
            $connectionParams['unix_socket'] = $GLOBALS['tmpdb_unix_socket'];
        }

        return $connectionParams;
    }

181 182 183 184
    /**
     * @return mixed[]
     */
    private static function getParamsForMainConnection() : array
185
    {
Sergei Morozov's avatar
Sergei Morozov committed
186
        $connectionParams = [
187 188 189 190 191
            'driver' => $GLOBALS['db_type'],
            'user' => $GLOBALS['db_username'],
            'password' => $GLOBALS['db_password'],
            'host' => $GLOBALS['db_host'],
            'dbname' => $GLOBALS['db_name'],
Sergei Morozov's avatar
Sergei Morozov committed
192 193
            'port' => $GLOBALS['db_port'],
        ];
194 195 196 197 198 199 200

        if (isset($GLOBALS['db_server'])) {
            $connectionParams['server'] = $GLOBALS['db_server'];
        }

        if (isset($GLOBALS['db_unix_socket'])) {
            $connectionParams['unix_socket'] = $GLOBALS['db_unix_socket'];
201 202
        }

203 204 205
        return $connectionParams;
    }

206
    public static function getTempConnection() : Connection
207
    {
208
        return DriverManager::getConnection(self::getParamsForTemporaryConnection());
209
    }
210
}