diff --git a/lib/Config/Database.php b/lib/Config/Database.php index e2865d29a0..5cfe4e79e5 100644 --- a/lib/Config/Database.php +++ b/lib/Config/Database.php @@ -1,64 +1,23 @@ setupConnection(); + function init(PDO $pdo) { + ORM::setDb($pdo); $this->setupLogging(); - $this->setupDriverOptions(); $this->defineTables(); } - function setupConnection() { - ORM::configure(Env::$db_source_name); - ORM::configure('username', Env::$db_username); - ORM::configure('password', Env::$db_password); - } - function setupLogging() { ORM::configure('logging', WP_DEBUG); } - function setupDriverOptions() { - $driver_options = [ - 'TIME_ZONE = "' . Env::$db_timezone_offset . '"', - 'sql_mode=(SELECT REPLACE(@@sql_mode,"ONLY_FULL_GROUP_BY",""))', - ]; - - if (!empty(Env::$db_charset)) { - $character_set = 'NAMES ' . Env::$db_charset; - if (!empty(Env::$db_collation)) { - $character_set .= ' COLLATE ' . Env::$db_collation; - } - $driver_options[] = $character_set; - } - - ORM::configure('driver_options', [ - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET ' . implode(', ', $driver_options), - ]); - - try { - $current_options = ORM::for_table("") - ->raw_query('SELECT @@session.wait_timeout as wait_timeout') - ->findOne(); - if ($current_options && (int)$current_options->wait_timeout < $this->driver_option_wait_timeout) { - ORM::raw_execute('SET SESSION wait_timeout = ' . $this->driver_option_wait_timeout); - } - } catch (\PDOException $e) { - // Rethrow PDOExceptions to prevent exposing sensitive data in stack traces - throw new \Exception($e->getMessage()); - } - } - function defineTables() { if (!defined('MP_SETTINGS_TABLE')) { define('MP_SETTINGS_TABLE', Env::$db_prefix . 'settings'); diff --git a/lib/Config/DatabaseInitializer.php b/lib/Config/DatabaseInitializer.php new file mode 100644 index 0000000000..5fad965e2b --- /dev/null +++ b/lib/Config/DatabaseInitializer.php @@ -0,0 +1,24 @@ +di_container = $di_container; + } + + function initializeConnection() { + $connection = $this->di_container->get(Connection::class); + + // pass the same PDO connection to legacy Database object + $database = new Database(); + $database->init($connection->getWrappedConnection()); + } +} diff --git a/lib/Config/Env.php b/lib/Config/Env.php index 533b8f3bd9..c5e08b2856 100644 --- a/lib/Config/Env.php +++ b/lib/Config/Env.php @@ -25,7 +25,6 @@ class Env { static $lib_path; static $plugin_prefix; static $db_prefix; - static $db_source_name; static $db_host; static $db_socket; static $db_port; @@ -79,33 +78,9 @@ class Env { self::$db_charset = $wpdb->charset; self::$db_collation = $wpdb->collate; self::$db_charset_collate = $wpdb->get_charset_collate(); - self::$db_source_name = self::dbSourceName(self::$db_host, self::$db_socket, self::$db_port, self::$db_charset, self::$db_name, $is_ipv6); self::$db_timezone_offset = self::getDbTimezoneOffset(); } - private static function dbSourceName($host, $socket, $port, $charset, $db_name, $is_ipv6) { - if ($is_ipv6) { - $host = "[$host]"; - } - $source_name = [ - 'mysql:host=', - $host, - ';', - 'port=', - $port, - ';', - 'dbname=', - $db_name, - ]; - if (!empty($socket)) { - $source_name[] = ';unix_socket=' . $socket; - } - if (!empty($charset)) { - $source_name[] = ';charset=' . $charset; - } - return implode('', $source_name); - } - static function getDbTimezoneOffset($offset = false) { $offset = ($offset) ? $offset : WPFunctions::get()->getOption('gmt_offset'); $mins = $offset * 60; diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php index 408f8658dd..4f5f5157bd 100644 --- a/lib/Config/Initializer.php +++ b/lib/Config/Initializer.php @@ -57,6 +57,9 @@ class Initializer { /** @var Shortcodes */ private $shortcodes; + /** @var DatabaseInitializer */ + private $database_initializer; + const INITIALIZED = 'MAILPOET_INITIALIZED'; function __construct( @@ -71,7 +74,8 @@ class Initializer { Menu $menu, CronTrigger $cron_trigger, PermanentNotices $permanent_notices, - Shortcodes $shortcodes + Shortcodes $shortcodes, + DatabaseInitializer $database_initializer ) { $this->renderer_factory = $renderer_factory; $this->access_control = $access_control; @@ -85,6 +89,7 @@ class Initializer { $this->cron_trigger = $cron_trigger; $this->permanent_notices = $permanent_notices; $this->shortcodes = $shortcodes; + $this->database_initializer = $database_initializer; } function init() { @@ -100,7 +105,7 @@ class Initializer { $this->setupLocalizer(); try { - $this->setupDB(); + $this->database_initializer->initializeConnection(); } catch (\Exception $e) { return WPNotice::displayError(Helpers::replaceLinkTags( WPFunctions::get()->__('Unable to connect to the database (the database is unable to open a file or folder), the connection is likely not configured correctly. Please read our [link] Knowledge Base article [/link] for steps how to resolve it.', 'mailpoet'), @@ -158,11 +163,6 @@ class Initializer { return $this->activator->activate(); } - function setupDB() { - $database = new Database(); - $database->init(); - } - function preInitialize() { try { $this->renderer = $this->renderer_factory->getRenderer(); diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 75e3b6a939..f799e56d93 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -80,6 +80,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Config\Activator::class)->setPublic(true); $container->autowire(\MailPoet\Config\Populator::class); $container->autowire(\MailPoet\Config\Changelog::class)->setPublic(true); + $container->autowire(\MailPoet\Config\DatabaseInitializer::class); $container->autowire(\MailPoet\Config\Hooks::class)->setPublic(true); $container->autowire(\MailPoet\Config\Initializer::class)->setPublic(true); $container->autowire(\MailPoet\Config\Menu::class)->setPublic(true); diff --git a/tests/integration/Config/DatabaseTest.php b/tests/integration/Config/DatabaseTest.php index aea794e9d6..b2cecc246e 100644 --- a/tests/integration/Config/DatabaseTest.php +++ b/tests/integration/Config/DatabaseTest.php @@ -1,7 +1,7 @@ equals(WP_DEBUG); } - function testItSetsUpConnection() { - expect(\ORM::get_config('username'))->equals(Env::$db_username); - expect(\ORM::get_config('password'))->equals(Env::$db_password); - } - - function testItSelectivelyUpdatesDriverTimeoutOption() { - $database = $this->database; - $database->setupDriverOptions(); - $current_setting = \ORM::for_table("") - ->raw_query('SELECT @@session.wait_timeout as wait_timeout') - ->findOne(); - expect($current_setting->wait_timeout)->greaterThan($database->driver_option_wait_timeout); - $this->_before(); - $database->driver_option_wait_timeout = 99999; - $database->setupDriverOptions(); - $current_setting = \ORM::for_table("") - ->raw_query('SELECT @@session.wait_timeout as wait_timeout') - ->findOne(); - expect($current_setting->wait_timeout)->equals(99999); - } - function testItSetsDBDriverOptions() { - $this->database->init(); + $this->database->init($this->connection->getWrappedConnection()); $result = \ORM::for_table("") ->raw_query( 'SELECT ' . @@ -61,26 +40,4 @@ class DatabaseTest extends \MailPoetTest { // time zone should be set based on WP's time zone expect($result->time_zone)->equals(Env::$db_timezone_offset); } - - function testItRethrowsPDOExceptions() { - $message = 'Error message'; - $pdo = Stub::make( - 'PDO', - [ - 'prepare' => function() use ($message) { - throw new \PDOException($message); - }, - ] - ); - \ORM::setDb($pdo); - try { - $this->database->setupDriverOptions(); - $this->fail('Exception was not thrown'); - } catch (\Exception $e) { - expect($e instanceof \PDOException)->false(); - expect($e->getMessage())->equals($message); - } - // Remove the DB stub - $this->_before(); - } } diff --git a/tests/integration/Config/EnvTest.php b/tests/integration/Config/EnvTest.php index 8f115d286f..f97482b180 100644 --- a/tests/integration/Config/EnvTest.php +++ b/tests/integration/Config/EnvTest.php @@ -26,33 +26,28 @@ class EnvTest extends \MailPoetTest { Env::init('file', '1.0.0', 'localhost', 'db_user', 'pass123', 'db_name'); expect(Env::$db_host)->equals('localhost'); expect(Env::$db_port)->equals('3306'); - expect(Env::$db_source_name)->equals('mysql:host=localhost;port=3306;dbname=db_name;charset=' . ENV::$db_charset); Env::init('file', '1.0.0', 'localhost:3307', 'db_user', 'pass123', 'db_name'); expect(Env::$db_host)->equals('localhost'); expect(Env::$db_port)->equals('3307'); - expect(Env::$db_source_name)->equals('mysql:host=localhost;port=3307;dbname=db_name;charset=' . ENV::$db_charset); } function testItProcessDBHostWithSocket() { Env::init('file', '1.0.0', 'localhost:/var/lib/mysql/mysql55.sock', 'db_user', 'pass123', 'db_name'); expect(Env::$db_host)->equals('localhost'); expect(Env::$db_socket)->equals('/var/lib/mysql/mysql55.sock'); - expect(Env::$db_source_name)->equals('mysql:host=localhost;port=3306;dbname=db_name;unix_socket=/var/lib/mysql/mysql55.sock;charset=' . ENV::$db_charset); } function testItProcessDBHostWithIpV6Address() { Env::init('file', '1.0.0', '::1', 'db_user', 'pass123', 'db_name'); expect(Env::$db_host)->equals('::1'); expect(Env::$db_socket)->equals(null); - expect(Env::$db_source_name)->equals('mysql:host=[::1];port=3306;dbname=db_name;charset=' . ENV::$db_charset); Env::init('file', '1.0.0', 'b57e:9b70:ab96:6a0b:5ba2:49e3:ebba:a036', 'db_user', 'pass123', 'db_name'); expect(Env::$db_host)->equals('b57e:9b70:ab96:6a0b:5ba2:49e3:ebba:a036'); expect(Env::$db_socket)->equals(null); - expect(Env::$db_source_name)->equals('mysql:host=[b57e:9b70:ab96:6a0b:5ba2:49e3:ebba:a036];port=3306;dbname=db_name;charset=' . ENV::$db_charset); - } + function testItCanReturnDbName() { expect(Env::$db_name)->equals(DB_NAME); } diff --git a/tests/integration/Models/ModelTest.php b/tests/integration/Models/ModelTest.php index 406590e11f..122551c58a 100644 --- a/tests/integration/Models/ModelTest.php +++ b/tests/integration/Models/ModelTest.php @@ -84,6 +84,6 @@ class ModelTest extends \MailPoetTest { } function _after() { - \ORM::setDb(null); + \ORM::setDb($this->connection->getWrappedConnection()); } }