diff options
author | webchick <webchick@24967.no-reply.drupal.org> | 2012-03-07 10:44:46 -0800 |
---|---|---|
committer | webchick <webchick@24967.no-reply.drupal.org> | 2012-03-07 10:44:46 -0800 |
commit | 465cab13f138f37a2158fbea04f5e1007a097bb9 (patch) | |
tree | c17e75f2a0066598a57c3e7abebb769a03f8f956 /modules/locale | |
parent | 09ecc5ba834bda67d5208216e6e19d9eafdca933 (diff) | |
download | brdo-465cab13f138f37a2158fbea04f5e1007a097bb9.tar.gz brdo-465cab13f138f37a2158fbea04f5e1007a097bb9.tar.bz2 |
Issue #746240 by c960657, Gábor Hojtsy: Fixed Race condition in locale() - duplicates in {locales_source()}.
Diffstat (limited to 'modules/locale')
-rw-r--r-- | modules/locale/locale.install | 68 | ||||
-rw-r--r-- | modules/locale/locale.module | 8 |
2 files changed, 73 insertions, 3 deletions
diff --git a/modules/locale/locale.install b/modules/locale/locale.install index 80b20c454..cb7cefe01 100644 --- a/modules/locale/locale.install +++ b/modules/locale/locale.install @@ -138,6 +138,74 @@ function locale_update_7003() { */ /** + * @addtogroup updates-7.x-extra + * @{ + */ + +/** + * Remove duplicates in {locales_source}. + */ +function locale_update_7004() { + // Look up all duplicates. For each set of duplicates, we select the row + // with the lowest lid as the "master" that will be preserved. + $result_source = db_query("SELECT MIN(lid) AS lid, source, context FROM {locales_source} WHERE textgroup = 'default' GROUP BY source, context HAVING COUNT(*) > 1"); + + $conflict = FALSE; + foreach ($result_source as $source) { + // Find all rows in {locales_target} that are translations of the same + // string (incl. context). + $result_target = db_query("SELECT t.lid, t.language, t.plural, t.translation FROM {locales_source} s JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default' ORDER BY lid", array( + ':source' => $source->source, + ':context' => $source->context, + )); + + $translations = array(); + $keep_lids = array($source->lid); + foreach ($result_target as $target) { + if (!isset($translations[$target->language])) { + $translations[$target->language] = $target->translation; + if ($target->lid != $source->lid) { + // Move translation to the master lid. + db_query('UPDATE {locales_target} SET lid = :new_lid WHERE lid = :old_lid', array( + ':new_lid' => $source->lid, + ':old_lid' => $target->lid)); + } + } + elseif ($translations[$target->language] == $target->translation) { + // Delete duplicate translation. + db_query('DELETE FROM {locales_target} WHERE lid = :lid AND language = :language', array( + ':lid' => $target->lid, + ':language' => $target->language)); + } + else { + // The same string is translated into several different strings in one + // language. We do not know which is the preferred, so we keep them all. + $keep_lids[] = $target->lid; + $conflict = TRUE; + } + } + + // Delete rows in {locales_source} that are no longer referenced from + // {locales_target}. + db_delete('locales_source') + ->condition('source', $source->source) + ->condition('context', $source->context) + ->condition('textgroup', 'default') + ->condition('lid', $keep_lids, 'NOT IN') + ->execute(); + } + + if ($conflict) { + $url = 'http://drupal.org/node/746240'; + drupal_set_message('Your {locales_source} table contains duplicates that could not be removed automatically. See <a href="' . $url .'" target="_blank">' . $url . '</a> for more information.', 'warning'); + } +} + +/** + * @} End of "addtogroup updates-7.x-extra" + */ + +/** * Implements hook_uninstall(). */ function locale_uninstall() { diff --git a/modules/locale/locale.module b/modules/locale/locale.module index caa01f2f3..5de8e44da 100644 --- a/modules/locale/locale.module +++ b/modules/locale/locale.module @@ -699,13 +699,15 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) { } else { // We don't have the source string, cache this as untranslated. - db_insert('locales_source') - ->fields(array( + db_merge('locales_source') + ->insertFields(array( 'location' => request_uri(), + 'version' => VERSION, + )) + ->key(array( 'source' => $string, 'context' => (string) $context, 'textgroup' => 'default', - 'version' => VERSION, )) ->execute(); $locale_t[$langcode][$context][$string] = TRUE; |