[FEATURE] Lazy database connection 25/19525/13
authorChristian Kuhn <lolli@schwarzbu.ch>
Tue, 2 Apr 2013 23:00:59 +0000 (01:00 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 14 Apr 2013 08:42:29 +0000 (10:42 +0200)
The patch implements "lazy" database connection, a connection
will be established by database connection class on demand.

Bootstrap now just sets credentials of the database connection
class after LocalConfiguration file was read, but does not
initialize the connection on its own anymore.

* Separation of concerns - Bootstrap does not take care of connection
  initialization, the db class will handle it on its own if needed.
* Database connection class got setters for options and credentials,
  it knows the details and can create, sleep and wake up a connection.
* Tests do not need to take care of a special db connection backup
  anymore, mocking / serializing $GLOBALS['TYPO3_DB'] and connection
  is handled by the class automatically.
* eID scripts do not need to call connectDB() anymore: The according
  method in eid handling is obsolete and developers do not need to
  think about it anymore.
* Simplification of bootstrap cross-dependencies.

With the patch only the frontend explicitly calls connectDB(). This
cannot be changed by this patch and needs some more thoughts.

Exception and logging handling is not fully cleaned up and should
be done at a later point. Still, the patch should be fully backward
compatible and dbal should work too, if related patch is applied.

After mysqli switch, main method connectDB() now handles different
port settings correctly and fixes the related issue.

Change-Id: Id977228a525dc2c80085ad21c78a7b7d4044160e
Resolves: #46880
Related: #46825
Releases: 6.1
Reviewed-on: https://review.typo3.org/19525
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
25 files changed:
typo3/cli_dispatch.phpsh
typo3/init.php
typo3/install/index.php
typo3/sysext/cms/tslib/index_ts.php
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Database/DatabaseConnection.php
typo3/sysext/core/Classes/Error/AbstractExceptionHandler.php
typo3/sysext/core/Classes/Error/ErrorHandler.php
typo3/sysext/core/Tests/BaseTestCase.php
typo3/sysext/core/Tests/Integrity/IntegrityTest.php
typo3/sysext/core/Tests/Unit/Cache/Backend/Typo3DatabaseBackendTest.php
typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php
typo3/sysext/core/Tests/Unit/Database/PreparedStatementTest.php
typo3/sysext/core/Tests/Unit/Log/Writer/DatabaseTest.php
typo3/sysext/core/Tests/Unit/RegistryTest.php
typo3/sysext/core/Tests/Unit/Resource/Service/IndexerServiceTest.php
typo3/sysext/felogin/Tests/Unit/Controller/FrontendLoginControllerTest.php
typo3/sysext/frontend/Classes/Controller/ExtDirectEidController.php
typo3/sysext/frontend/Classes/Controller/ShowImageController.php
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Classes/Utility/EidUtility.php
typo3/sysext/install/Classes/Installer.php
typo3/sysext/install/Classes/Sql/SchemaMigrator.php
typo3/sysext/openid/Classes/OpenidEid.php
typo3/sysext/rtehtmlarea/pi1/class.tx_rtehtmlarea_pi1.php

index 50c9c4d..f441339 100755 (executable)
@@ -48,7 +48,7 @@ require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
        ->loadConfigurationAndInitialize()
        ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
        ->applyAdditionalConfigurationSettings()
-       ->initializeTypo3DbGlobal(TRUE);
+       ->initializeTypo3DbGlobal();
 
 \TYPO3\CMS\Core\Core\CliBootstrap::initializeCliKeyOrDie();
 
index 76077a9..f67017a 100644 (file)
@@ -61,12 +61,11 @@ require 'sysext/core/Classes/Core/Bootstrap.php';
        ->loadConfigurationAndInitialize()
        ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
        ->applyAdditionalConfigurationSettings()
-       ->initializeTypo3DbGlobal(FALSE)
+       ->initializeTypo3DbGlobal()
        ->checkLockedBackendAndRedirectOrDie()
        ->checkBackendIpOrDie()
        ->checkSslBackendAndRedirectIfNeeded()
        ->checkValidBrowserOrDie()
-       ->establishDatabaseConnection()
        ->loadExtensionTables(TRUE)
        ->initializeSpriteManager()
        ->initializeBackendUser()
index 08a402b..31e5320 100755 (executable)
@@ -46,7 +46,7 @@ require '../sysext/install/Classes/InstallBootstrap.php';
        ->loadConfigurationAndInitialize()
        ->loadTypo3LoadedExtAndExtLocalconf(FALSE)
        ->applyAdditionalConfigurationSettings()
-       ->initializeTypo3DbGlobal(FALSE)
+       ->initializeTypo3DbGlobal()
        ->checkLockedBackendAndRedirectOrDie()
        ->checkBackendIpOrDie()
        ->checkSslBackendAndRedirectIfNeeded();
index 94ce86e..8f1c97e 100644 (file)
@@ -51,7 +51,8 @@ if ($_COOKIE[\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::getCookie
 }
 
 $TT->start();
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->initializeTypo3DbGlobal(FALSE);
+
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->initializeTypo3DbGlobal();
 // Hook to preprocess the current request:
 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'])) {
        foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'] as $hookFunction) {
@@ -70,17 +71,31 @@ if ($temp_extId = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('eID')) {
        }
        die;
 }
-// Create $TSFE object (TSFE = TypoScript Front End)
-// Connecting to database
-/**
- * @var $TSFE \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
- */
-$TSFE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController', $TYPO3_CONF_VARS, \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('type'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('no_cache'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('cHash'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('jumpurl'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('MP'), \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RDCT'));
-if ($TYPO3_CONF_VARS['FE']['pageUnavailable_force'] && !\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $TYPO3_CONF_VARS['SYS']['devIPmask'])) {
+
+/** @var $TSFE \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
+$TSFE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+       'TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController',
+       $TYPO3_CONF_VARS,
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('type'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('no_cache'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('cHash'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('jumpurl'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('MP'),
+       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RDCT')
+);
+
+if ($TYPO3_CONF_VARS['FE']['pageUnavailable_force']
+       && !\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(
+               \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'),
+               $TYPO3_CONF_VARS['SYS']['devIPmask'])
+) {
        $TSFE->pageUnavailableAndExit('This page is temporarily unavailable.');
 }
+
 $TSFE->connectToDB();
 $TSFE->sendRedirect();
+
 // Output compression
 // Remove any output produced until now
 ob_clean();
@@ -233,4 +248,4 @@ if (TYPO3_DLOG) {
        \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, array('_FLUSH' => TRUE));
 }
 \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
-?>
\ No newline at end of file
+?>
index e5e2e03..b0e1ef9 100644 (file)
@@ -499,7 +499,8 @@ class Bootstrap {
         * @return \TYPO3\CMS\Core\Core\Bootstrap
         */
        protected function registerSwiftMailer() {
-               $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'][] = 'TYPO3\\CMS\\Core\\Mail\\SwiftMailerAdapter';
+               $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'][] =
+                       'TYPO3\\CMS\\Core\\Mail\\SwiftMailerAdapter';
                return $this;
        }
 
@@ -678,13 +679,50 @@ class Bootstrap {
         * @return \TYPO3\CMS\Core\Core\Bootstrap
         * @internal This is not a public API method, do not use in own extensions
         */
-       public function initializeTypo3DbGlobal($connect = TRUE) {
-               /** @var TYPO3_DB TYPO3\CMS\Core\Database\DatabaseConnection */
-               $GLOBALS['TYPO3_DB'] = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\DatabaseConnection');
-               $GLOBALS['TYPO3_DB']->debugOutput = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sqlDebug'];
-               if ($connect) {
-                       $this->establishDatabaseConnection();
+       public function initializeTypo3DbGlobal() {
+               /** @var $databaseConnection \TYPO3\CMS\Core\Database\DatabaseConnection */
+               $databaseConnection = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\DatabaseConnection');
+               $databaseConnection->setDatabaseName(TYPO3_db);
+               $databaseConnection->setDatabaseUsername(TYPO3_db_username);
+               $databaseConnection->setDatabasePassword(TYPO3_db_password);
+
+               $databaseHost = TYPO3_db_host;
+               // Check if a port was specified
+               if (strpos(':', $databaseHost) > 0) {
+                       list($databaseHost, $databasePort) = explode(':', $databaseHost);
+                       $databaseConnection->setDatabasePort($databasePort);
                }
+               $databaseConnection->setDatabaseHost($databaseHost);
+
+               $databaseConnection->debugOutput = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sqlDebug'];
+
+               if (
+                       isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect'])
+                       && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']
+               ) {
+                       $databaseConnection->setPersistentDatabaseConnection(TRUE);
+               }
+
+               $isDatabaseHostLocalHost = $databaseHost === 'localhost' || $databaseHost === '127.0.0.1' || $databaseHost === '::1';
+               if (
+                       isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'])
+                       && $GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress']
+                       && !$isDatabaseHostLocalHost
+               ) {
+                       $databaseConnection->setConnectionCompression(TRUE);
+               }
+
+               if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'])) {
+                       $commandsAfterConnect = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(
+                               LF,
+                               str_replace('\' . LF . \'', LF, $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']),
+                               TRUE
+                       );
+                       $databaseConnection->setInitializeCommandsAfterConnect($commandsAfterConnect);
+               }
+
+               $GLOBALS['TYPO3_DB'] = $databaseConnection;
+
                return $this;
        }
 
@@ -778,17 +816,6 @@ class Bootstrap {
        }
 
        /**
-        * Establish connection to the database
-        *
-        * @return \TYPO3\CMS\Core\Core\Bootstrap
-        * @internal This is not a public API method, do not use in own extensions
-        */
-       public function establishDatabaseConnection() {
-               $GLOBALS['TYPO3_DB']->connectDB();
-               return $this;
-       }
-
-       /**
         * Load TCA for frontend
         *
         * This method is *only* executed in frontend scope. The idea is to execute the
index f60d9da..a2dd865 100644 (file)
@@ -96,6 +96,52 @@ class DatabaseConnection {
        public $explainOutput = 0;
 
        /**
+        * @var string Database host to connect to
+        */
+       protected $databaseHost = '';
+
+       /**
+        * @var integer Database port to connect to
+        */
+       protected $databasePort = 3306;
+
+       /**
+        * @var string Database name to connect to
+        */
+       protected $databaseName = '';
+
+       /**
+        * @var string Database user to connect with
+        */
+       protected $databaseUsername = '';
+
+       /**
+        * @var string Database password to connect with
+        */
+       protected $databaseUserPassword = '';
+
+       /**
+        * @var boolean TRUE if database connection should be persistent
+        * @see http://php.net/manual/de/mysqli.persistconns.php
+        */
+       protected $persistentDatabaseConnection = FALSE;
+
+       /**
+        * @var boolean TRUE if connection between client and sql server is compressed
+        */
+       protected $connectionCompression = FALSE;
+
+       /**
+        * @var array List of commands executed after connection was established
+        */
+       protected $initializeCommandsAfterConnect = array();
+
+       /**
+        * @var boolean TRUE if database connection is established
+        */
+       protected $isConnected = FALSE;
+
+       /**
         * @var \mysqli $link Default database link object
         */
        protected $link = NULL;
@@ -139,6 +185,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function exec_INSERTquery($table, $fields_values, $no_quote_fields = FALSE) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($this->INSERTquery($table, $fields_values, $no_quote_fields));
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTquery');
@@ -160,6 +209,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($this->INSERTmultipleRows($table, $fields, $rows, $no_quote_fields));
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTmultipleRows');
@@ -182,6 +234,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields = FALSE) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($this->UPDATEquery($table, $where, $fields_values, $no_quote_fields));
                if ($this->debugOutput) {
                        $this->debug('exec_UPDATEquery');
@@ -201,6 +256,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function exec_DELETEquery($table, $where) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($this->DELETEquery($table, $where));
                if ($this->debugOutput) {
                        $this->debug('exec_DELETEquery');
@@ -225,6 +283,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
                $res = $this->link->query($query);
                if ($this->debugOutput) {
@@ -373,6 +434,9 @@ class DatabaseConnection {
         * @return mixed Result from handler
         */
        public function exec_TRUNCATEquery($table) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($this->TRUNCATEquery($table));
                if ($this->debugOutput) {
                        $this->debug('exec_TRUNCATEquery');
@@ -689,6 +753,9 @@ class DatabaseConnection {
         * @return resource MySQL result object / DBAL object
         */
        public function exec_PREPAREDquery($query, array $queryComponents) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($query);
                if ($this->debugOutput) {
                        $this->debug('stmt_execute', $query);
@@ -716,6 +783,9 @@ class DatabaseConnection {
         * @see quoteStr()
         */
        public function fullQuoteStr($str, $table, $allowNull = FALSE) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                if ($allowNull && $str === NULL) {
                        return 'NULL';
                }
@@ -728,7 +798,7 @@ class DatabaseConnection {
         *
         * @param array $arr Array with values (either associative or non-associative array)
         * @param string $table Table name for which to quote
-        * @param boolean $noQuote List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
+        * @param boolean|array $noQuote List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
         * @param boolean $allowNull Whether to allow NULL values
         * @return array The input array with the values quoted
         * @see cleanIntArray()
@@ -758,6 +828,9 @@ class DatabaseConnection {
         * @see quoteStr()
         */
        public function quoteStr($str, $table) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                return $this->link->real_escape_string($str);
        }
 
@@ -902,6 +975,9 @@ class DatabaseConnection {
         * @return boolean|\mysqli_result|object MySQLi result object / DBAL object
         */
        public function sql_query($query) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($query);
                if ($this->debugOutput) {
                        $this->debug('sql_query', $query);
@@ -1075,50 +1151,64 @@ class DatabaseConnection {
        /**
         * Open a (persistent) connection to a MySQL server
         *
-        * @param string $TYPO3_db_host Database host IP/domain
-        * @param string $TYPO3_db_username Username to connect with.
-        * @param string $TYPO3_db_password Password to connect with.
+        * @param string $host Deprecated since 6.1, will be removed in two versions. Database host IP/domain[:port]
+        * @param string $username Deprecated since 6.1, will be removed in two versions. Username to connect with.
+        * @param string $password Deprecated since 6.1, will be removed in two versions. Password to connect with.
         * @return boolean|void
         * @throws \RuntimeException
         */
-       public function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) {
-               // Check if MySQLi extension is loaded
+       public function sql_pconnect($host = NULL, $username = NULL, $password = NULL) {
+               if ($this->isConnected) {
+                       return $this->link;
+               }
+
                if (!extension_loaded('mysqli')) {
-                       $message = 'Database Error: It seems that MySQLi support for PHP is not installed!';
-                       throw new \RuntimeException($message, 1271492607);
+                       throw new \RuntimeException(
+                               'Database Error: PHP mysqli extension not loaded. This is a must have for TYPO3 CMS!',
+                               1271492607
+                       );
                }
-               // Check for client compression
-               $isLocalhost = $TYPO3_db_host == 'localhost' || $TYPO3_db_host == '127.0.0.1';
-               $this->link = mysqli_init();
-               $connected = FALSE;
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
-                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
-                               // use default-port to connect to MySQL
-                               $connected = $this->link->real_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, NULL, MYSQLI_CLIENT_COMPRESS);
-                       } else {
-                               $connected = $this->link->real_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
-                       }
-               } else {
-                       // prepend 'p:' to host to use a persistent connection
-                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
-                               // use default-port to connect to MySQL
-                               $connected = $this->link->real_connect('p:' . $TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, NULL, MYSQLI_CLIENT_COMPRESS);
-                       } else {
-                               $connected = $this->link->real_connect('p:' . $TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
-                       }
+
+               if ($host || $username || $password) {
+                       $this->handleDeprecatedConnectArguments($host, $username, $password);
                }
-               $error_msg = $this->link->connect_error;
-               if (!$connected) {
-                       $this->link = FALSE;
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('Could not connect to MySQL server ' . $TYPO3_db_host . ' with user ' . $TYPO3_db_username . ': ' . $error_msg, 'Core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_FATAL);
-               } else {
-                       $setDBinit = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, str_replace('\' . LF . \'', LF, $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']), TRUE);
-                       foreach ($setDBinit as $v) {
-                               if ($this->link->query($v) === FALSE) {
-                                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('Could not initialize DB connection with query "' . $v . '": ' . $this->sql_error(), 'Core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
+
+               $host = $this->persistentDatabaseConnection
+                       ? 'p:' . $this->databaseHost
+                       : $this->databaseHost;
+
+               $this->link = mysqli_init();
+               $connected = $this->link->real_connect(
+                       $this->databaseHost,
+                       $this->databaseUsername,
+                       $this->databaseUserPassword,
+                       NULL,
+                       $this->databasePort,
+                       NULL,
+                       $this->connectionCompression ? MYSQLI_CLIENT_COMPRESS : 0
+               );
+
+               if ($connected) {
+                       $this->isConnected = TRUE;
+                       foreach ($this->initializeCommandsAfterConnect as $command) {
+                               if ($this->link->query($command) === FALSE) {
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
+                                               'Could not initialize DB connection with query "' . $command . '": ' . $this->sql_error(),
+                                               'Core',
+                                               \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR
+                                       );
                                }
                        }
                        $this->setSqlMode();
+               } else {
+                       // @TODO: This should raise an exception. Would be useful especially to work during installation.
+                       $error_msg = $this->link->connect_error;
+                       $this->link = NULL;
+                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
+                               'Could not connect to MySQL server ' . $host . ' with user ' . $username . ': ' . $error_msg,
+                               'Core',
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_FATAL
+                       );
                }
                return $this->link;
        }
@@ -1130,13 +1220,17 @@ class DatabaseConnection {
         */
        protected function setSqlMode() {
                $resource = $this->sql_query('SELECT @@SESSION.sql_mode;');
-               if (is_resource($resource)) {
+               if ($resource) {
                        $result = $this->sql_fetch_row($resource);
                        if (isset($result[0]) && $result[0] && strpos($result[0], 'NO_BACKSLASH_ESCAPES') !== FALSE) {
                                $modes = array_diff(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $result[0]), array('NO_BACKSLASH_ESCAPES'));
                                $query = 'SET sql_mode=\'' . $this->link->real_escape_string(implode(',', $modes)) . '\';';
-                               $success = $this->sql_query($query);
-                               \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('NO_BACKSLASH_ESCAPES could not be removed from SQL mode: ' . $this->sql_error(), 'Core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
+                               $this->sql_query($query);
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
+                                       'NO_BACKSLASH_ESCAPES could not be removed from SQL mode: ' . $this->sql_error(),
+                                       'Core',
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR
+                               );
                        }
                }
        }
@@ -1144,13 +1238,30 @@ class DatabaseConnection {
        /**
         * Select a SQL database
         *
-        * @param string $TYPO3_db Database to connect to.
+        * @param string $TYPO3_db Deprecated since 6.1, will be removed in two versions. Database to connect to.
         * @return boolean Returns TRUE on success or FALSE on failure.
         */
-       public function sql_select_db($TYPO3_db) {
+       public function sql_select_db($TYPO3_db = NULL) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
+
+               if ($TYPO3_db) {
+                       \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog(
+                               'DatabaseConnection->sql_select_db() should be called without arguments.' .
+                                       ' Use the setDatabaseName() before. Will be removed two versions after 6.1.'
+                       );
+               } else {
+                       $TYPO3_db = $this->databaseName;
+               }
+
                $ret = $this->link->select_db($TYPO3_db);
                if (!$ret) {
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('Could not select MySQL database ' . $TYPO3_db . ': ' . $this->sql_error(), 'Core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_FATAL);
+                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
+                               'Could not select MySQL database ' . $TYPO3_db . ': ' . $this->sql_error(),
+                               'Core',
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_FATAL
+                       );
                }
                return $ret;
        }
@@ -1170,10 +1281,14 @@ class DatabaseConnection {
         * @return array Each entry represents a database name
         */
        public function admin_get_dbs() {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $dbArr = array();
                $db_list = $this->link->query("SHOW DATABASES");
                while ($row = $db_list->fetch_object()) {
-                       if ($this->sql_select_db($row->Database)) {
+                       $this->setDatabaseName($row->Database);
+                       if ($this->sql_select_db()) {
                                $dbArr[] = $row->Database;
                        }
                }
@@ -1188,6 +1303,9 @@ class DatabaseConnection {
         * @return array Array with tablenames as key and arrays with status information as value
         */
        public function admin_get_tables() {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $whichTables = array();
                $tables_result = $this->link->query('SHOW TABLE STATUS FROM `' . TYPO3_db . '`');
                if ($tables_result !== FALSE) {
@@ -1211,6 +1329,9 @@ class DatabaseConnection {
         * @return array Field information in an associative array with fieldname => field row
         */
        public function admin_get_fields($tableName) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $output = array();
                $columns_res = $this->link->query('SHOW COLUMNS FROM `' . $tableName . '`');
                while ($fieldRow = $columns_res->fetch_assoc()) {
@@ -1228,6 +1349,9 @@ class DatabaseConnection {
         * @return array Key information in a numeric array
         */
        public function admin_get_keys($tableName) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $output = array();
                $keyRes = $this->link->query('SHOW KEYS FROM `' . $tableName . '`');
                while ($keyRow = $keyRes->fetch_assoc()) {
@@ -1250,6 +1374,9 @@ class DatabaseConnection {
         * @return array Array with Charset as key and an array of "Charset", "Description", "Default collation", "Maxlen" as values
         */
        public function admin_get_charsets() {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $output = array();
                $columns_res = $this->link->query('SHOW CHARACTER SET');
                if ($columns_res !== FALSE) {
@@ -1268,6 +1395,9 @@ class DatabaseConnection {
         * @return resource Result pointer (MySQLi result object)
         */
        public function admin_query($query) {
+               if (!$this->isConnected) {
+                       $this->connectDB();
+               }
                $res = $this->link->query($query);
                if ($this->debugOutput) {
                        $this->debug('admin_query', $query);
@@ -1277,39 +1407,148 @@ class DatabaseConnection {
 
        /******************************
         *
-        * Connecting service
+        * Connect handling
         *
         ******************************/
+
        /**
-        * Connects to database for TYPO3 sites:
+        * Set database host
         *
         * @param string $host
-        * @param string $user
+        */
+       public function setDatabaseHost($host = 'localhost') {
+               $this->disconnectIfConnected();
+               $this->databaseHost = $host;
+       }
+
+       /**
+        * Set database port
+        *
+        * @param integer $port
+        */
+       public function setDatabasePort($port = 3306) {
+               $this->disconnectIfConnected();
+               $this->databasePort = (int)$port;
+       }
+
+       /**
+        * Set database name
+        *
+        * @param string $name
+        */
+       public function setDatabaseName($name) {
+               $this->disconnectIfConnected();
+               $this->databaseName = $name;
+       }
+
+       /**
+        * Set database username
+        *
+        * @param string $username
+        */
+       public function setDatabaseUsername($username) {
+               $this->disconnectIfConnected();
+               $this->databaseUsername = $username;
+       }
+
+       /**
+        * Set database password
+        *
         * @param string $password
-        * @param string $db
+        */
+       public function setDatabasePassword($password) {
+               $this->disconnectIfConnected();
+               $this->databaseUserPassword = $password;
+       }
+
+       /**
+        * Set persistent database connection
+        *
+        * @param boolean $persistentDatabaseConnection
+        * @see http://php.net/manual/de/mysqli.persistconns.php
+        */
+       public function setPersistentDatabaseConnection($persistentDatabaseConnection) {
+               $this->disconnectIfConnected();
+               $this->persistentDatabaseConnection = (bool)$persistentDatabaseConnection;
+       }
+
+       /**
+        * Set connection compression. Might be an advantage, if SQL server is not on localhost
+        *
+        * @param bool $connectionCompression TRUE if connection should be compressed
+        */
+       public function setConnectionCompression($connectionCompression) {
+               $this->disconnectIfConnected();
+               $this->connectionCompression = (bool)$connectionCompression;
+       }
+
+       /**
+        * Set commands to be fired after connection was established
+        *
+        * @param array $commands List of SQL commands to be executed after connect
+        */
+       public function setInitializeCommandsAfterConnect(array $commands) {
+               $this->disconnectIfConnected();
+               $this->initializeCommandsAfterConnect = $commands;
+       }
+
+       /**
+        * Connects to database for TYPO3 sites:
+        *
+        * @param string $host Deprecated since 6.1, will be removed in two versions Database. host IP/domain[:port]
+        * @param string $username Deprecated since 6.1, will be removed in two versions. Username to connect with
+        * @param string $password Deprecated since 6.1, will be removed in two versions. Password to connect with
+        * @param string $db Deprecated since 6.1, will be removed in two versions. Database name to connect to
         * @throws \RuntimeException
         * @throws \UnexpectedValueException
+        * @internal param string $user Username to connect with.
         * @return void
         */
-       public function connectDB($host = TYPO3_db_host, $user = TYPO3_db_username, $password = TYPO3_db_password, $db = TYPO3_db) {
-               if (!$db) {
-                       throw new \RuntimeException('TYPO3 Fatal Error: No database selected!', 1270853882);
+       public function connectDB($host = NULL, $username = NULL, $password = NULL, $db = NULL) {
+               // Early return if connected already
+               if ($this->isConnected) {
+                       return;
+               }
+
+               if (!$this->databaseName && !$db) {
+                       throw new \RuntimeException(
+                               'TYPO3 Fatal Error: No database selected!',
+                               1270853882
+                       );
                }
-               if ($this->sql_pconnect($host, $user, $password)) {
-                       if (!$this->sql_select_db($db)) {
-                               throw new \RuntimeException('TYPO3 Fatal Error: Cannot connect to the current database, "' . $db . '"!', 1270853883);
+
+               if ($host || $username || $password || $db) {
+                       $this->handleDeprecatedConnectArguments($host, $username, $password, $db);
+               }
+
+               if ($this->sql_pconnect()) {
+                       if (!$this->sql_select_db()) {
+                               throw new \RuntimeException(
+                                       'TYPO3 Fatal Error: Cannot connect to the current database, "' . $this->databaseName . '"!',
+                                       1270853883
+                               );
                        }
                } else {
-                       throw new \RuntimeException('TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!', 1270853884);
+                       throw new \RuntimeException(
+                               'TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!',
+                               1270853884
+                       );
                }
+
                // Prepare user defined objects (if any) for hooks which extend query methods
                $this->preProcessHookObjects = array();
                $this->postProcessHookObjects = array();
                if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'])) {
                        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'] as $classRef) {
                                $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classRef);
-                               if (!($hookObject instanceof \TYPO3\CMS\Core\Database\PreProcessQueryHookInterface || $hookObject instanceof \TYPO3\CMS\Core\Database\PostProcessQueryHookInterface)) {
-                                       throw new \UnexpectedValueException('$hookObject must either implement interface TYPO3\\CMS\\Core\\Database\\PreProcessQueryHookInterface or interface TYPO3\\CMS\\Core\\Database\\PostProcessQueryHookInterface', 1299158548);
+                               if (!(
+                                       $hookObject instanceof \TYPO3\CMS\Core\Database\PreProcessQueryHookInterface
+                                       || $hookObject instanceof \TYPO3\CMS\Core\Database\PostProcessQueryHookInterface
+                               )) {
+                                       throw new \UnexpectedValueException(
+                                               '$hookObject must either implement interface TYPO3\\CMS\\Core\\Database\\PreProcessQueryHookInterface or interface TYPO3\\CMS\\Core\\Database\\PostProcessQueryHookInterface',
+                                               1299158548
+                                       );
                                }
                                if ($hookObject instanceof \TYPO3\CMS\Core\Database\PreProcessQueryHookInterface) {
                                        $this->preProcessHookObjects[] = $hookObject;
@@ -1327,7 +1566,19 @@ class DatabaseConnection {
         * @return boolean
         */
        public function isConnected() {
-               return is_object($this->link);
+               return $this->isConnected;
+       }
+
+       /**
+        * Disconnect from database if connected
+        *
+        * @return void
+        */
+       protected function disconnectIfConnected() {
+               if ($this->isConnected()) {
+                       $this->link->close();
+                       $this->isConnected = FALSE;
+               }
        }
 
        /**
@@ -1348,6 +1599,39 @@ class DatabaseConnection {
                $this->link = $handle;
        }
 
+       /**
+        * Handle deprecated arguments for sql_pconnect() and connectDB()
+        *
+        * @param string|null $host Database host[:port]
+        * @param string|null $username Database user name
+        * @param string|null $password User password
+        * @param string|null $db Database
+        */
+       protected function handleDeprecatedConnectArguments($host = NULL, $username = NULL, $password = NULL, $db = NULL) {
+               \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog(
+                       'DatabaseConnection->sql_pconnect() and DatabaseConnection->connectDB() should be ' .
+                       'called without arguments. Use the setters instead.'
+               );
+               if ($host) {
+                       if (strpos(':', $host) > 0) {
+                               list($databaseHost, $databasePort) = explode(':', $host);
+                               $this->setDatabaseHost($databaseHost);
+                               $this->setDatabasePort($databasePort);
+                       } else {
+                               $this->setDatabaseHost($host);
+                       }
+               }
+               if ($username) {
+                       $this->setDatabaseUsername($username);
+               }
+               if ($password) {
+                       $this->setDatabasePassword($password);
+               }
+               if ($db) {
+                       $this->setDatabaseName($db);
+               }
+       }
+
        /******************************
         *
         * Debugging
@@ -1364,12 +1648,18 @@ class DatabaseConnection {
        public function debug($func, $query = '') {
                $error = $this->sql_error();
                if ($error || (int) $this->debugOutput === 2) {
-                       \TYPO3\CMS\Core\Utility\DebugUtility::debug(array(
-                               'caller' => 'TYPO3\\CMS\\Core\\Database\\DatabaseConnection::' . $func,
-                               'ERROR' => $error,
-                               'lastBuiltQuery' => $query ? $query : $this->debug_lastBuiltQuery,
-                               'debug_backtrace' => \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail()
-                       ), $func, is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debug')) ? '' : 'DB Error');
+                       \TYPO3\CMS\Core\Utility\DebugUtility::debug(
+                               array(
+                                       'caller' => 'TYPO3\\CMS\\Core\\Database\\DatabaseConnection::' . $func,
+                                       'ERROR' => $error,
+                                       'lastBuiltQuery' => $query ? $query : $this->debug_lastBuiltQuery,
+                                       'debug_backtrace' => \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail()
+                               ),
+                               $func,
+                               is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debug'))
+                                       ? ''
+                                       : 'DB Error'
+                       );
                }
        }
 
@@ -1395,7 +1685,11 @@ class DatabaseConnection {
                        }
                }
                $msg .= ': function TYPO3\\CMS\\Core\\Database\\DatabaseConnection->' . $trace[0]['function'] . ' called from file ' . substr($trace[0]['file'], (strlen(PATH_site) + 2)) . ' in line ' . $trace[0]['line'];
-               \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog($msg . '. Use a devLog extension to get more details.', 'Core/t3lib_db', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
+               \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
+                       $msg . '. Use a devLog extension to get more details.',
+                       'Core/t3lib_db',
+                       \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR
+               );
                // Send to devLog if enabled
                if (TYPO3_DLOG) {
                        $debugLogData = array(
@@ -1423,7 +1717,14 @@ class DatabaseConnection {
         * @return boolean TRUE if explain was run, FALSE otherwise
         */
        protected function explain($query, $from_table, $row_count) {
-               if ((int) $this->explainOutput == 1 || (int) $this->explainOutput == 2 && \TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'])) {
+               $debugAllowedForIp = \TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(
+                       \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'),
+                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']
+               );
+               if (
+                       (int)$this->explainOutput == 1
+                       || ((int)$this->explainOutput == 2 && $debugAllowedForIp)
+               ) {
                        // Raw HTML output
                        $explainMode = 1;
                } elseif ((int) $this->explainOutput == 3 && is_object($GLOBALS['TT'])) {
@@ -1446,7 +1747,10 @@ class DatabaseConnection {
                }
                $indices_output = array();
                // Notice: Rows are skipped if there is only one result, or if no conditions are set
-               if ($explain_output[0]['rows'] > 1 || \TYPO3\CMS\Core\Utility\GeneralUtility::inList('ALL', $explain_output[0]['type'])) {
+               if (
+                       $explain_output[0]['rows'] > 1
+                       || \TYPO3\CMS\Core\Utility\GeneralUtility::inList('ALL', $explain_output[0]['type'])
+               ) {
                        // Only enable output if it's really useful
                        $debug = TRUE;
                        foreach ($explain_tables as $table) {
@@ -1492,7 +1796,26 @@ class DatabaseConnection {
                return FALSE;
        }
 
+       /**
+        * Serialize destructs current connection
+        *
+        * @return array All protected properties that should be saved
+        */
+       public function __sleep() {
+               $this->disconnectIfConnected();
+               return array(
+                       'debugOutput',
+                       'explainOutput',
+                       'databaseHost',
+                       'databasePort',
+                       'databaseName',
+                       'databaseUsername',
+                       'databaseUserPassword',
+                       'persistentDatabaseConnection',
+                       'connectionCompression',
+                       'initializeCommandsAfterConnect',
+                       'default_charset',
+               );
+       }
 }
-
-
 ?>
index 2ac5062..e8affde 100644 (file)
@@ -73,11 +73,6 @@ abstract class AbstractExceptionHandler implements \TYPO3\CMS\Core\Error\Excepti
                // caused by this. Therefor we cannot do any database operation,
                // otherwise this will lead into recurring exceptions.
                try {
-                       // In case an error occurs before a database connection exists, try
-                       // to connect to the DB to be able to write the devlog/sys_log entry
-                       if (isset($GLOBALS['TYPO3_DB']) && is_object($GLOBALS['TYPO3_DB']) && empty($GLOBALS['TYPO3_DB']->link)) {
-                               $GLOBALS['TYPO3_DB']->connectDB();
-                       }
                        // Write error message to devlog
                        // see: $TYPO3_CONF_VARS['SYS']['enable_exceptionDLOG']
                        if (TYPO3_EXCEPTION_DLOG) {
index 9e48965..bc4be49 100644 (file)
@@ -128,15 +128,6 @@ class ErrorHandler implements \TYPO3\CMS\Core\Error\ErrorHandlerInterface {
                        if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['syslogErrorReporting']) {
                                \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog($message, $logTitle, $severity);
                        }
-                       // In case an error occurs before a database connection exists, try
-                       // to connect to the DB to be able to write an entry to devlog/sys_log
-                       if (is_object($GLOBALS['TYPO3_DB']) && empty($GLOBALS['TYPO3_DB']->link)) {
-                               try {
-                                       $GLOBALS['TYPO3_DB']->connectDB();
-                               } catch (\Exception $e) {
-
-                               }
-                       }
                        // Write error message to devlog extension(s),
                        // see: $TYPO3_CONF_VARS['SYS']['enable_errorDLOG']
                        if (TYPO3_ERROR_DLOG) {
@@ -148,7 +139,12 @@ class ErrorHandler implements \TYPO3\CMS\Core\Error\ErrorHandlerInterface {
                        }
                        // Write error message to sys_log table (ext: belog, Tools->Log)
                        if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['belogErrorReporting']) {
-                               $this->writeLog($logTitle . ': ' . $message, $severity);
+                               // Silently catch in case an error occurs before a database connection exists,
+                               // but DatabaseConnection fails to connect.
+                               try {
+                                       $this->writeLog($logTitle . ': ' . $message, $severity);
+                               } catch (\Exception $e) {
+                               }
                        }
                        // Add error message to the flashmessageQueue
                        if (defined('TYPO3_ERRORHANDLER_MODE') && TYPO3_ERRORHANDLER_MODE == 'debug') {
index 0ac3b31..6925173 100644 (file)
@@ -32,29 +32,22 @@ namespace TYPO3\CMS\Core\Tests;
  *
  */
 abstract class BaseTestCase extends \PHPUnit_Framework_TestCase {
+
        /**
-        * whether global variables should be backuped
+        * Whether global variables should be backed up
         *
         * @var boolean
         */
        protected $backupGlobals = TRUE;
 
        /**
-        * whether static attributes should be backuped
+        * Whether static attributes should be backed up
         *
         * @var boolean
         */
        protected $backupStaticAttributes = FALSE;
 
        /**
-        * Exclude TYPO3_DB from backup/restore of $GLOBALS
-        * because resource types cannot be handled during serializing
-        *
-        * @var array
-        */
-       protected $backupGlobalsBlacklist = array('TYPO3_DB');
-
-       /**
         * Creates a mock object which allows for calling protected methods and access of protected properties.
         *
         * @param string $originalClassName name of class to create the mock object of, must not be empty
index 4baace7..2bd6e89 100644 (file)
@@ -35,19 +35,6 @@ namespace TYPO3\CMS\Core\Tests\Integrity;
 class IntegrityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * This test fails if some test before either set
-        * $backupGlobals to TRUE and did not add TYPO3_DB to
-        * $backupGlobalsBlacklist, or if it mocked
-        * TYPO3\CMS\Core\Database\DatabaseConnection and
-        * did not reconstitute the existing connection.
-        *
-        * @test
-        */
-       public function globalsTypo3DbDatabaseLinkIsAObject() {
-               $this->assertTrue(is_object($GLOBALS['TYPO3_DB']->getDatabaseHandle()));
-       }
-
-       /**
         * This test fails if some test before mocked or substituted
         * $GLOBALS['typo3CacheManager'] but did not reconstitute correctly.
         *
index d1e141f..1c5f41f 100644 (file)
@@ -32,11 +32,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Cache\Backend;
 class Typo3DatabaseBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * @var \TYPO3\CMS\Core\Database\DatabaseConnection Backup of original TYPO3_DB instance
-        */
-       protected $typo3DbBackup;
-
-       /**
         * @var string Name of the testing data table
         */
        protected $testingCacheTable;
@@ -50,7 +45,6 @@ class Typo3DatabaseBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * Set up testcases
         */
        public function setUp() {
-               $this->typo3DbBackup = $GLOBALS['TYPO3_DB'];
                $tablePrefix = 'cf_';
                $this->testingCacheTable = $tablePrefix . 'Testing';
                $this->testingTagsTable = $tablePrefix . 'Testing_tags';
@@ -101,7 +95,6 @@ class Typo3DatabaseBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
         */
        public function tearDown() {
-               $GLOBALS['TYPO3_DB'] = $this->typo3DbBackup;
                $GLOBALS['TYPO3_DB']->sql_query('DROP TABLE IF EXISTS ' . $this->testingCacheTable . ';');
                $GLOBALS['TYPO3_DB']->sql_query('DROP TABLE IF EXISTS ' . $this->testingTagsTable . ';');
        }
index c25deee..1503e76 100644 (file)
@@ -32,13 +32,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\DataHandler;
 class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * a backup of the global database
-        *
-        * @var \TYPO3\CMS\Core\Database\DatabaseConnection
-        */
-       protected $databaseBackup = NULL;
-
-       /**
         * @var array A backup of registered singleton instances
         */
        protected $singletonInstances = array();
@@ -55,7 +48,6 @@ class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        public function setUp() {
                $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
-               $this->databaseBackup = $GLOBALS['TYPO3_DB'];
                $this->backEndUser = $this->getMock('TYPO3\\CMS\\Core\\Authentication\\BackendUserAuthentication');
                $this->fixture = new \TYPO3\CMS\Core\DataHandling\DataHandler();
                $this->fixture->start(array(), '', $this->backEndUser);
@@ -63,8 +55,7 @@ class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        public function tearDown() {
                \TYPO3\CMS\Core\Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
-               $GLOBALS['TYPO3_DB'] = $this->databaseBackup;
-               unset($this->fixture->BE_USER, $this->fixture, $this->backEndUser, $this->databaseBackup);
+               unset($this->fixture->BE_USER, $this->fixture, $this->backEndUser);
        }
 
        //////////////////////////////////////
index 8141e5b..04370eb 100644 (file)
@@ -32,13 +32,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Database;
 class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * Backup and restore of the $GLOBALS array.
-        *
-        * @var boolean
-        */
-       protected $backupGlobalsArray = array();
-
-       /**
         * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Database\DatabaseConnection
         */
        private $databaseStub;
@@ -50,19 +43,9 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @return void
         */
        protected function setUp() {
-               $this->backupGlobalsArray['TYPO3_DB'] = $GLOBALS['TYPO3_DB'];
                $this->databaseStub = $this->setUpAndReturnDatabaseStub();
        }
 
-       /**
-        * Restore global database object.
-        *
-        * @return void
-        */
-       protected function tearDown() {
-               $GLOBALS['TYPO3_DB'] = $this->backupGlobalsArray['TYPO3_DB'];
-       }
-
        //////////////////////
        // Utility functions
        //////////////////////
@@ -72,8 +55,17 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @return \PHPUnit_Framework_MockObject_MockObject
         */
        private function setUpAndReturnDatabaseStub() {
+               $GLOBALS['TYPO3_DB']->connectDB();
                $databaseLink = $GLOBALS['TYPO3_DB']->getDatabaseHandle();
-               $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('exec_PREPAREDquery'), array(), '', FALSE, FALSE);
+               $GLOBALS['TYPO3_DB'] = $this->getAccessibleMock(
+                       'TYPO3\\CMS\\Core\\Database\\DatabaseConnection',
+                       array('exec_PREPAREDquery'),
+                       array(),
+                       '',
+                       FALSE,
+                       FALSE
+               );
+               $GLOBALS['TYPO3_DB']->_set('isConnected', TRUE);
                $GLOBALS['TYPO3_DB']->setDatabaseHandle($databaseLink);
                return $GLOBALS['TYPO3_DB'];
        }
index 4392d8a..0af807a 100644 (file)
@@ -32,13 +32,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Log\Writer;
 class DatabaseTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * Backup and restore of the $GLOBALS array.
-        *
-        * @var boolean
-        */
-       protected $backupGlobalsArray = array();
-
-       /**
         * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Database\DatabaseConnection
         */
        private $databaseStub;
@@ -50,19 +43,9 @@ class DatabaseTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @return void
         */
        public function setUp() {
-               $this->backupGlobalsArray['TYPO3_DB'] = $GLOBALS['TYPO3_DB'];
                $this->databaseStub = $this->setUpAndReturnDatabaseStub();
        }
 
-       /**
-        * Restore global database object.
-        *
-        * @return void
-        */
-       protected function tearDown() {
-               $GLOBALS['TYPO3_DB'] = $this->backupGlobalsArray['TYPO3_DB'];
-       }
-
        //////////////////////
        // Utility functions
        //////////////////////
index 96cad68..3e2f74f 100644 (file)
@@ -37,28 +37,15 @@ class RegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        protected $registry;
 
        /**
-        * @var \TYPO3\CMS\Core\Database\DatabaseConnection
-        */
-       protected $typo3DbBackup;
-
-       /**
         * Sets up this testcase
         */
        public function setUp() {
-               $this->typo3DbBackup = $GLOBALS['TYPO3_DB'];
                $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array());
                $GLOBALS['TYPO3_DB']->expects($this->any())->method('fullQuoteStr')->will($this->onConsecutiveCalls('\'tx_phpunit\'', '\'someKey\'', '\'tx_phpunit\'', '\'someKey\''));
                $this->registry = new \TYPO3\CMS\Core\Registry();
        }
 
        /**
-        * Tears down this testcase
-        */
-       public function tearDown() {
-               $GLOBALS['TYPO3_DB'] = $this->typo3DbBackup;
-       }
-
-       /**
         * @test
         * @expectedException \InvalidArgumentException
         */
index ae2af81..cbb8bc3 100644 (file)
@@ -35,27 +35,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Resource\Service;
 class IndexerServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * @var Store backup of TYPO3_DB
-        */
-       protected $dbBackup;
-
-       /**
-        * Set up this test case
-        */
-       public function setUp() {
-                       // Store TYPO3_DB in local var, it is substituted with a mock in this test
-               $this->dbBackup = $GLOBALS['TYPO3_DB'];
-       }
-
-       /**
-        * Tear down this test case
-        */
-       public function tearDown() {
-                       // Re constitute TYPO3_DB from backup
-               $GLOBALS['TYPO3_DB'] = $this->dbBackup;
-       }
-
-       /**
         * @test
         */
        public function indexFileUpdatesFileProperties() {
index d7a4cde..83c20c0 100644 (file)
@@ -35,11 +35,6 @@ namespace TYPO3\CMS\Felogin\Tests\Unit\Controller;
 class FrontendLoginTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
-        * @var \TYPO3\CMS\Core\Database\DatabaseConnection
-        */
-       protected $typo3DbBackup;
-
-       /**
         * @var \TYPO3\CMS\Felogin\Controller\FrontendLoginController|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface
         */
        protected $accessibleFixture;
@@ -63,7 +58,6 @@ class FrontendLoginTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * Set up
         */
        public function setUp() {
-               $this->typo3DbBackup = $GLOBALS['TYPO3_DB'];
                $this->testTableName = 'sys_domain';
                $this->testHostName = 'hostname.tld';
                $this->testSitePath = '/';
@@ -77,7 +71,6 @@ class FrontendLoginTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * Tear down
         */
        public function tearDown() {
-               $GLOBALS['TYPO3_DB'] = $this->typo3DbBackup;
                $this->accessibleFixture = NULL;
        }
 
index df7a1e5..7ea2d18 100644 (file)
@@ -46,7 +46,6 @@ class ExtDirectEidController {
         */
        public function routeAction() {
                \TYPO3\CMS\Frontend\Utility\EidUtility::initLanguage();
-               \TYPO3\CMS\Frontend\Utility\EidUtility::connectDB();
                $ajaxID = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('action');
                $ajaxScript = $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']['ExtDirect::' . $ajaxID];
                $this->ajaxObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Http\\AjaxRequestHandler', 'ExtDirect::' . $ajaxID);
index 1cf57ce..07ee365 100644 (file)
@@ -158,8 +158,6 @@ class ShowImageController {
                if ($this->alternativeTempPath && \TYPO3\CMS\Core\Utility\GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['allowedTempPaths'], $this->alternativeTempPath)) {
                        $img->tempPath = $this->alternativeTempPath;
                }
-               // Need to connect to database, because this is used (typo3temp_db_tracking, cached image dimensions).
-               $GLOBALS['TYPO3_DB']->connectDB();
                if (strstr($this->width . $this->height, 'm')) {
                        $max = 'm';
                } else {
index 3cf2e2a..034a864 100644 (file)
@@ -28,7 +28,8 @@ namespace TYPO3\CMS\Frontend\Controller;
  ***************************************************************/
 
 /**
- * Class for the built TypoScript based Front End
+ * Class for the built TypoScript based Front End. Instantiated in
+ * index_ts.php script as the global object TSFE
  * Main frontend class, instantiated in the index_ts.php script as the global object TSFE
  *
  * This class has a lot of functions and internal variable which are use from index_ts.php.
@@ -795,6 +796,8 @@ class TypoScriptFrontendController {
         * Connect to SQL database. May exit after outputting an error message
         * or some JavaScript redirecting to the install tool.
         *
+        * @throws \RuntimeException
+        * @throws \TYPO3\CMS\Core\Error\Http\ServiceUnavailableException
         * @return void
         */
        public function connectToDB() {
@@ -1830,7 +1833,13 @@ class TypoScriptFrontendController {
         * @todo Define visibility
         */
        public function checkPageUnavailableHandler() {
-               if ($this->TYPO3_CONF_VARS['FE']['pageUnavailable_handling'] && !\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $this->TYPO3_CONF_VARS['SYS']['devIPmask'])) {
+               if (
+                       $this->TYPO3_CONF_VARS['FE']['pageUnavailable_handling']
+                       && !\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'),
+                               $this->TYPO3_CONF_VARS['SYS']['devIPmask']
+                       )
+               ) {
                        $checkPageUnavailableHandler = TRUE;
                } else {
                        $checkPageUnavailableHandler = FALSE;
index 4eff39d..02eb32a 100644 (file)
@@ -26,6 +26,7 @@ namespace TYPO3\CMS\Frontend\Utility;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+
 /**
  * Tools for scripts using the eID feature of index.php
  * Included from index_ts.php
@@ -36,11 +37,6 @@ namespace TYPO3\CMS\Frontend\Utility;
  * eg. Frontend User session, Database connection etc.
  *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
- */
-/**
- * Tools for scripts using the eID feature of index.php
- *
- * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  * @author Dmitry Dulepov <dmitry@typo3.org>
  */
 class EidUtility {
@@ -52,9 +48,6 @@ class EidUtility {
         * @return object Frontend User object (usually known as TSFE->fe_user)
         */
        static public function initFeUser() {
-               // Initialize the database. Do not use TSFE method as it may redirect to
-               // Install tool and call hooks, which do not expect to be called from eID
-               self::connectDB();
                // Get TSFE instance. It knows how to initialize the user. We also
                // need TCA because services may need extra tables!
                self::initTCA();
@@ -70,14 +63,10 @@ class EidUtility {
         * can be retrieved using $GLOBALS['TYPO3_DB']->sql_error().
         *
         * @return boolean TRUE if connection was successful
+        * @deprecated since 6.1, database will connect itself if needed. Will be removed two versions later
         */
        static public function connectDB() {
-               if (!$GLOBALS['TYPO3_DB']->isConnected()) {
-                       // Attempt to connect to the database
-                       $GLOBALS['TYPO3_DB']->connectDB();
-               }
-               // connectDB() throws exceptions if something went wrong,
-               // so we are sure that connect was successful here.
+               \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
                return TRUE;
        }
 
index 61c9300..23e3435 100644 (file)
@@ -944,7 +944,7 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                // Add header marker for main template
                                $markers['header'] = 'Select database';
                                // There should be a database host connection at this point
-                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                                        // Get the subpart for the third step
                                        $step3SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP3###');
                                        // Get the subpart for the database options
@@ -1021,9 +1021,9 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                // Add header marker for main template
                                $markers['header'] = 'Import the Database Tables';
                                // There should be a database host connection at this point
-                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                                        // The selected database should be accessible
-                                       if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
+                                       if ($GLOBALS['TYPO3_DB']->sql_select_db()) {
                                                // Get the subpart for the fourth step
                                                $step4SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP4###');
                                                // Get the subpart for the database type options
@@ -1080,9 +1080,9 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                // Add header marker for main template
                                $markers['header'] = 'Congratulations!';
                                // There should be a database host connection at this point
-                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                                        // The selected database should be accessible
-                                       if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
+                                       if ($GLOBALS['TYPO3_DB']->sql_select_db()) {
                                                // The database should contain tables
                                                if (count($whichTables)) {
                                                        // Get the subpart for the go step
@@ -2329,7 +2329,7 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                        </p>
                                ', 2);
                        }
-                       if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+                       if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                                $this->message($ext, 'Connected to SQL database successfully', '
                                        <dl id="t3-install-databaseconnected">
                                                <dt>
@@ -2356,7 +2356,7 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                                </p>
                                        ', 3);
                                        $this->config_array['no_database'] = 1;
-                               } elseif (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
+                               } elseif (!$GLOBALS['TYPO3_DB']->sql_select_db()) {
                                        $this->message($ext, 'Database', '
                                                <p>
                                                        \'' . htmlspecialchars(TYPO3_db) . '\' could not be selected as database!
@@ -2697,7 +2697,7 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
                                        $newDatabaseName = trim($this->INSTALL['Database']['NEW_DATABASE_NAME']);
                                                // Hyphen is not allowed in unquoted database names (at least for MySQL databases)
                                        if (!preg_match('/[^[:alnum:]_]/', $newDatabaseName)) {
-                                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+                                               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                                                        if ($GLOBALS['TYPO3_DB']->admin_query('CREATE DATABASE ' . $newDatabaseName . ' CHARACTER SET utf8')) {
                                                                $this->INSTALL['Database']['typo_db'] = $newDatabaseName;
                                                                $this->messages[] = 'Database \'' . $newDatabaseName . '\' created';
@@ -2979,7 +2979,7 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
         */
        public function getDatabaseList() {
                $dbArr = array();
-               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
+               if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect()) {
                        $dbArr = $GLOBALS['TYPO3_DB']->admin_get_dbs();
                }
                // remove some database names that MySQL uses internally from the list of choosable DB names
@@ -6602,4 +6602,4 @@ REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE
        }
 
 }
-?>
\ No newline at end of file
+?>
index a50a4cd..be60a5a 100644 (file)
@@ -270,9 +270,9 @@ class SchemaMigrator {
                $total = array();
                $tempKeys = array();
                $tempKeysPrefix = array();
-               $GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db);
+               $GLOBALS['TYPO3_DB']->sql_select_db();
                echo $GLOBALS['TYPO3_DB']->sql_error();
-               $tables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db);
+               $tables = $GLOBALS['TYPO3_DB']->admin_get_tables();
                foreach ($tables as $tableName => $tableStatus) {
                        // Fields
                        $fieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields($tableName);
index 1f86d4d..710e38e 100644 (file)
@@ -43,7 +43,6 @@ class OpenidEid {
                // the user.
                $GLOBALS['TYPO3_CONF_VARS']['SVCONF']['auth']['FE_fetchUserIfNoSession'] = TRUE;
                // Initialize Frontend user
-               \TYPO3\CMS\Frontend\Utility\EidUtility::connectDB();
                \TYPO3\CMS\Frontend\Utility\EidUtility::initFeUser();
                // Redirect to the original location in any case (authenticated or not)
                @ob_end_clean();
index 951c3bc..843f975 100644 (file)
@@ -6,7 +6,6 @@
  */
 require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('rtehtmlarea') . 'Classes/Controller/SpellCheckingController.php';
 if (TYPO3_MODE == 'FE') {
-       \TYPO3\CMS\Frontend\Utility\EidUtility::connectDB();
        $spellChecker = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Rtehtmlarea\\Controller\\SpellCheckingController');
        $spellChecker->main();
 }