summaryrefslogtreecommitdiff
path: root/modules/locale
diff options
context:
space:
mode:
authorwebchick <webchick@24967.no-reply.drupal.org>2012-03-07 10:44:46 -0800
committerwebchick <webchick@24967.no-reply.drupal.org>2012-03-07 10:44:46 -0800
commit465cab13f138f37a2158fbea04f5e1007a097bb9 (patch)
treec17e75f2a0066598a57c3e7abebb769a03f8f956 /modules/locale
parent09ecc5ba834bda67d5208216e6e19d9eafdca933 (diff)
downloadbrdo-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.install68
-rw-r--r--modules/locale/locale.module8
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;