Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional utf8mb4 fixes #5

Merged
merged 4 commits into from
Nov 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 1 addition & 64 deletions administrator/components/com_admin/script.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function update($installer)

$this->deleteUnexistingFiles();
$this->updateManifestCaches();
$this->updateDatabase();
$this->uninstallEosPlugin();
$this->clearRadCache();
$this->updateAssets();
$this->clearStatsCache();
Expand Down Expand Up @@ -97,69 +97,6 @@ protected function clearStatsCache()
}
}

/**
* Method to update Database
*
* @return void
*/
protected function updateDatabase()
{
$db = JFactory::getDbo();

if (strpos($db->name, 'mysql') !== false)
{
$this->updateDatabaseMysql();
}

$this->uninstallEosPlugin();
}

/**
* Method to update MySQL Database
*
* @return void
*/
protected function updateDatabaseMysql()
{
$db = JFactory::getDbo();

$db->setQuery('SHOW ENGINES');

try
{
$results = $db->loadObjectList();
}
catch (Exception $e)
{
echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

return;
}

foreach ($results as $result)
{
if ($result->Support != 'DEFAULT')
{
continue;
}

$db->setQuery('ALTER TABLE #__update_sites_extensions ENGINE = ' . $result->Engine);

try
{
$db->execute();
}
catch (Exception $e)
{
echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

return;
}

break;
}
}

/**
* Uninstall the 2.5 EOS plugin
*
Expand Down
17 changes: 11 additions & 6 deletions administrator/components/com_installer/models/database.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,18 @@ public function convertTablesToUtf8mb4()

foreach ($queries as $query)
{
try
{
$db->setQuery($query)->execute();
}
catch (Exception $e)
$query = trim($query);

if ($query != '' && $query{0} != '#')
{
// If the query fails we will go on. It probably means we've already done this conversion.
try
{
$db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
JFactory::getApplication()->enqueueMessage(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $e->getCode(), $e->getMessage()));
}
}
}
}
Expand Down
19 changes: 13 additions & 6 deletions libraries/joomla/database/driver/mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,17 +510,24 @@ private function hasProfiling()
private function serverClaimsUtf8mb4Support()
{
$client_version = mysql_get_client_info();
$server_support = version_compare($this->getVersion(), '5.5.3', '>=');
$server_version = $this->getVersion();

if (strpos($client_version, 'mysqlnd') !== false && $server_support)
if (version_compare($server_version, '5.5.3', '<'))
{
$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

return version_compare($client_version, '5.0.9', '>=');
return false;
}
else
{
return $server_support;
if (strpos($client_version, 'mysqlnd') !== false)
{
$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

return version_compare($client_version, '5.0.9', '>=');
}
else
{
return version_compare($client_version, '5.5.3', '>=');
}
}
}

Expand Down
19 changes: 13 additions & 6 deletions libraries/joomla/database/driver/mysqli.php
Original file line number Diff line number Diff line change
Expand Up @@ -952,17 +952,24 @@ private function hasProfiling()
private function serverClaimsUtf8mb4Support()
{
$client_version = mysqli_get_client_info();
$server_support = version_compare($this->getVersion(), '5.5.3', '>=');
$server_version = $this->getVersion();

if (strpos($client_version, 'mysqlnd') !== false && $server_support)
if (version_compare($server_version, '5.5.3', '<'))
{
$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

return version_compare($client_version, '5.0.9', '>=');
return false;
}
else
{
return $server_support;
if (strpos($client_version, 'mysqlnd') !== false)
{
$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

return version_compare($client_version, '5.0.9', '>=');
}
else
{
return version_compare($client_version, '5.5.3', '>=');
}
}
}

Expand Down
57 changes: 35 additions & 22 deletions libraries/joomla/database/driver/pdomysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,20 @@ class JDatabaseDriverPdomysql extends JDatabaseDriverPdo
*/
public function __construct($options)
{
/**
* Pre-populate the UTF-8 Multibyte compatibility flag. Unfortunately PDO won't report the server version
* unless we're connected to it and we cannot connect to it unless we know if it supports utf8mb4 which requires
* us knowing the server version. Between this chicken and egg issue we _assume_ it's supported and we'll just
* catch any problems at connection time.
*/
$this->utf8mb4 = true;

// Get some basic values from the options.
$options['driver'] = 'mysql';
$options['charset'] = (isset($options['charset'])) ? $options['charset'] : 'utf8';

if ($this->utf8mb4 && ($options['charset'] == 'utf8'))
if (!isset($options['charset']) || $options['charset'] == 'utf8')
{
$options['charset'] = 'utf8mb4';
}

$this->charset = $options['charset'];
/**
* Pre-populate the UTF-8 Multibyte compatibility flag. Unfortunately PDO won't report the server version
* unless we're connected to it, and we cannot connect to it unless we know if it supports utf8mb4, which requires
* us knowing the server version. Because of this chicken and egg issue, we _assume_ it's supported and we'll just
* catch any problems at connection time.
*/
$this->utf8mb4 = ($options['charset'] == 'utf8mb4');

// Finalize initialisation.
parent::__construct($options);
Expand All @@ -112,27 +108,44 @@ public function connect()
}
catch (\RuntimeException $e)
{
// If the connection failed but not because of the wrong character set bubble up the exception
if (!$this->utf8mb4 || ($this->options['charset'] != 'utf8mb4'))
// If the connection failed, but not because of the wrong character set, then bubble up the exception.
if (!$this->utf8mb4)
{
throw $e;
}

/**
* If the connection failed and I was trying to use the utf8mb4 charset then it is likely that the server
* doesn't support utf8mb4 despite claiming otherwise.
*
* This happens on old MySQL server versions (less than 5.5.3) using the mysqlnd PHP driver. Since mysqlnd
* masks the server version and reports only its own we can not be sure if the server actually does support
* UTF-8 Multibyte (i.e. it's MySQL 5.5.3 or later). Since the utf8mb4 charset is undefined in this case we
* catch the error and determine that utf8mb4 is not supported!
/*
* Otherwise, try connecting again without using
* utf8mb4 and see if maybe that was the problem. If the
* connection succeeds, then we will have learned that the
* client end of the connection does not support utf8mb4.
*/

$this->utf8mb4 = false;
$this->options['charset'] = 'utf8';

parent::connect();
}

if ($this->utf8mb4)
{
/*
* At this point we know the client supports utf8mb4. Now
* we must check if the server supports utf8mb4 as well.
*/

$serverVersion = $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
$this->utf8mb4 = version_compare($serverVersion, '5.5.3', '>=');

if (!$this->utf8mb4)
{
// Reconnect with the utf8 character set.
parent::disconnect();
$this->options['charset'] = 'utf8';
parent::connect();
}
}

$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
}
Expand Down