#812416: Locale upgrade path broken

From: Damien Tournoud <damien@commerceguys.com>


---
 locale/locale.install                              |   15 -
 simpletest/simpletest.info                         |    1 
 .../tests/upgrade/drupal-6.locale.database.php     |  277 ++++++++++++++++++++
 simpletest/tests/upgrade/upgrade.locale.test       |  144 ++++++++++
 system/system.install                              |    2 
 5 files changed, 429 insertions(+), 10 deletions(-)
 create mode 100644 simpletest/tests/upgrade/drupal-6.locale.database.php
 create mode 100644 simpletest/tests/upgrade/upgrade.locale.test

diff --git modules/locale/locale.install modules/locale/locale.install
index d8139f3..a26e338 100644
--- modules/locale/locale.install
+++ modules/locale/locale.install
@@ -46,6 +46,7 @@ function locale_update_7000() {
  */
 function locale_update_7001() {
   require_once DRUPAL_ROOT . '/includes/language.inc';
+  require_once DRUPAL_ROOT . '/includes/locale.inc';
   require_once DRUPAL_ROOT . '/modules/locale/locale.module';
 
   switch (variable_get('language_negotiation', 0)) {
@@ -62,9 +63,12 @@ function locale_update_7001() {
       // Drupal 7 path prefixes are always shown if not empty. Hence we need to
       // ensure that the default language has an empty prefix to avoid breaking
       // the site URLs with a prefix that previously was missing.
+      $default = language_default();
+      $default->prefix = '';
+      variable_set('language_default', $default);
       db_update('languages')
-        ->fields(array('prefix' => ''))
-        ->condition('language', language_default()->language)
+        ->fields(array('prefix' => $default->prefix))
+        ->condition('language', $default->language)
         ->execute();
       break;
 
@@ -90,13 +94,6 @@ function locale_update_7001() {
   $provider_weights = array_flip(array_keys(locale_language_negotiation_info()));
   variable_set("locale_language_providers_weight_$type", $provider_weights);
 
-  // Update language switcher block delta.
-  db_update('block')
-    ->fields(array('delta' => $type))
-    ->condition('module', 'locale')
-    ->condition('delta', 0)
-    ->execute();
-
   // Unset the old language negotiation system variable.
   variable_del('language_negotiation');
 
diff --git modules/simpletest/simpletest.info modules/simpletest/simpletest.info
index a8f4cc9..4396db4 100644
--- modules/simpletest/simpletest.info
+++ modules/simpletest/simpletest.info
@@ -43,3 +43,4 @@ files[] = tests/upgrade/upgrade.comment.test
 files[] = tests/upgrade/upgrade.node.test
 files[] = tests/upgrade/upgrade.taxonomy.test
 files[] = tests/upgrade/upgrade.upload.test
+files[] = tests/upgrade/upgrade.locale.test
diff --git modules/simpletest/tests/upgrade/drupal-6.locale.database.php modules/simpletest/tests/upgrade/drupal-6.locale.database.php
new file mode 100644
index 0000000..d4ea09f
--- /dev/null
+++ modules/simpletest/tests/upgrade/drupal-6.locale.database.php
@@ -0,0 +1,277 @@
+<?php
+// $Id$
+
+/**
+ * Database additions for locale tests.
+ */
+
+db_create_table('languages', array(
+  'fields' => array(
+    'language' => array(
+      'type' => 'varchar',
+      'length' => 12,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'name' => array(
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'native' => array(
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'direction' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'enabled' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'plurals' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'formula' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'domain' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'prefix' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'weight' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'javascript' => array(
+      'type' => 'varchar',
+      'length' => 32,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+  ),
+  'primary key' => array(
+    'language',
+  ),
+  'indexes' => array(
+    'list' => array(
+      'weight',
+      'name',
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'languages',
+));
+db_insert('languages')->fields(array(
+  'language',
+  'name',
+  'native',
+  'direction',
+  'enabled',
+  'plurals',
+  'formula',
+  'domain',
+  'prefix',
+  'weight',
+  'javascript',
+))
+->values(array(
+  'language' => 'en',
+  'name' => 'English',
+  'native' => 'English',
+  'direction' => '0',
+  'enabled' => '1',
+  'plurals' => '0',
+  'formula' => '',
+  'domain' => 'http://en.example.com',
+  'prefix' => 'en',
+  'weight' => '0',
+  'javascript' => '',
+))
+->values(array(
+  'language' => 'fr',
+  'name' => 'French',
+  'native' => 'Français',
+  'direction' => '0',
+  'enabled' => '1',
+  'plurals' => '2',
+  'formula' => '($n>1)',
+  'domain' => '',
+  'prefix' => 'fr',
+  'weight' => '-3',
+  'javascript' => '51e92dcfe1491f4595b9df7f3b287753',
+))
+->execute();
+
+db_create_table('locales_source', array(
+  'fields' => array(
+    'lid' => array(
+      'type' => 'serial',
+      'not null' => TRUE,
+    ),
+    'location' => array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'textgroup' => array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => 'default',
+    ),
+    'source' => array(
+      'type' => 'text',
+      'mysql_type' => 'blob',
+      'not null' => TRUE,
+    ),
+    'version' => array(
+      'type' => 'varchar',
+      'length' => 20,
+      'not null' => TRUE,
+      'default' => 'none',
+    ),
+  ),
+  'primary key' => array(
+    'lid',
+  ),
+  'indexes' => array(
+    'source' => array(
+      array(
+        'source',
+        30,
+      ),
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'locales_source',
+));
+
+db_create_table('locales_target', array(
+  'fields' => array(
+    'lid' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'translation' => array(
+      'type' => 'text',
+      'mysql_type' => 'blob',
+      'not null' => TRUE,
+    ),
+    'language' => array(
+      'type' => 'varchar',
+      'length' => 12,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'plid' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'plural' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+  ),
+  'primary key' => array(
+    'language',
+    'lid',
+    'plural',
+  ),
+  'indexes' => array(
+    'lid' => array(
+      'lid',
+    ),
+    'plid' => array(
+      'plid',
+    ),
+    'plural' => array(
+      'plural',
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'locales_target',
+));
+
+// Enable the locale module.
+db_update('system')->fields(array(
+  'status' => 1,
+  'schema_version' => '6006',
+))
+->condition('type', 'module')
+->condition('name', 'locale')
+->execute();
+
+// Set the default language.
+db_insert('variable')->fields(array(
+  'name',
+  'value',
+))
+->values(array(
+  'name' => 'language_default',
+  'value' => 'O:8:"stdClass":11:{s:8:"language";s:2:"fr";s:4:"name";s:6:"French";s:6:"native";s:9:"Français";s:9:"direction";s:1:"0";s:7:"enabled";i:1;s:7:"plurals";s:1:"2";s:7:"formula";s:6:"($n>1)";s:6:"domain";s:0:"";s:6:"prefix";s:0:"";s:6:"weight";s:2:"-3";s:10:"javascript";s:32:"51e92dcfe1491f4595b9df7f3b287753";}',
+))
+->values(array(
+  'name' => 'language_count',
+  'value' => 'i:2;',
+))
+->values(array(
+  'name' => 'language_negotiation',
+  'value' => 'i:0;',
+))
+->execute();
+
+// Add the language switcher block in the left region.
+db_insert('blocks')->fields(array(
+  'module',
+  'delta',
+  'theme',
+  'status',
+  'weight',
+  'region',
+  'custom',
+  'throttle',
+  'visibility',
+  'pages',
+  'title',
+  'cache',
+))
+->values(array(
+  'module' => 'locale',
+  'delta' => '0',
+  'theme' => 'garland',
+  'status' => '1',
+  'weight' => '0',
+  'region' => 'left',
+  'custom' => '0',
+  'throttle' => '0',
+  'visibility' => '0',
+  'pages' => '',
+  'title' => '',
+  'cache' => '-1',
+))
+->execute();
diff --git modules/simpletest/tests/upgrade/upgrade.locale.test modules/simpletest/tests/upgrade/upgrade.locale.test
new file mode 100644
index 0000000..66ea14e
--- /dev/null
+++ modules/simpletest/tests/upgrade/upgrade.locale.test
@@ -0,0 +1,144 @@
+<?php
+// $Id$
+
+/**
+ * Upgrade test for locale.module.
+ */
+class LocaleUpgradePathTestCase extends UpgradePathTestCase {
+  public static function getInfo() {
+    return array(
+      'name'  => 'Locale upgrade path',
+      'description'  => 'Upgrade path tests for the Locale module.',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    // Path to the database dump files.
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php',
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.locale.database.php',
+    );
+    parent::setUp();
+
+    $this->uninstallModulesExcept(array('locale', 'comment'));
+  }
+
+  /**
+   * Test a successful upgrade (no negotiation).
+   */
+  public function testLocaleUpgrade() {
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // No prefixed page should exist.
+    $this->drupalGet('en');
+    $this->assertResponse(404);
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+  }
+
+  /**
+   * Test an upgrade with path-based negotiation.
+   */
+  public function testLocaleUpgradePathDefault() {
+    // LANGUAGE_NEGOTIATION_PATH_DEFAULT.
+    $this->variable_set('language_negotiation', 1);
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+
+    // The French prefix should not be active because French is the default language.
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+
+    // The English prefix should be active.
+    $this->assertPageInLanguage('en', 'en');
+  }
+
+  /**
+   * Test an upgrade with path-based (with fallback) negotiation.
+   */
+  public function testLocaleUpgradePathFallback() {
+    // LANGUAGE_NEGOTIATION_PATH.
+    $this->variable_set('language_negotiation', 2);
+
+    // Set the language of the admin user to English.
+    db_update('users')
+      ->fields(array('language' => 'en'))
+      ->condition('uid', 1)
+      ->execute();
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // Both prefixes should be active.
+    $this->assertPageInLanguage('fr', 'fr');
+    $this->assertPageInLanguage('en', 'en');
+
+    // The home page should be in the admin user language.
+    $this->assertPageInLanguage('', 'en');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+  }
+
+  /**
+   * Test an upgrade with domain-based negotiation.
+   */
+  public function testLocaleUpgradeDomain() {
+    // LANGUAGE_NEGOTIATION_DOMAIN.
+    $this->variable_set('language_negotiation', 3);
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+
+    // The language switcher block should point to http://en.example.com.
+    $language_links = $this->xpath('//ul[contains(@class, :class)]/li/a', array(':class' => 'language-switcher-locale-url'));
+    $found_english_link = FALSE;
+    foreach ($language_links as $link) {
+      if ((string) $link['href'] == 'http://en.example.com/') {
+        $found_english_link = TRUE;
+      }
+    }
+    $this->assertTrue($found_english_link, t('The English link points to the correct domain.'));
+
+    // Both prefixes should be inactive.
+    $this->drupalGet('en');
+    $this->assertResponse(404);
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+
+  }
+
+  /**
+   * Asserts that a page exists and is in the specified language.
+   */
+  public function assertPageInLanguage($path = NULL, $langcode) {
+    if (isset($path)) {
+      $this->drupalGet($path);
+    }
+
+    if (!$this->assertResponse(200)) {
+      return FALSE;
+    }
+
+    if ($this->parse()) {
+      return $this->assertIdentical($langcode, (string) $this->elements['xml:lang']);
+    }
+    else {
+      return FALSE;
+    }
+  }
+}
diff --git modules/system/system.install modules/system/system.install
index 29c44aa..88a2d0c 100644
--- modules/system/system.install
+++ modules/system/system.install
@@ -1813,7 +1813,7 @@ function system_update_7004(&$sandbox) {
       '0' => 'active',
       '1' => 'new',
     ),
-    'locale' => array('0' => 'language-switcher'),
+    'locale' => array('0' => LANGUAGE_TYPE_INTERFACE),
     'node' => array('0' => 'syndicate'),
     'poll' => array('0' => 'recent'),
     'profile' => array('0' => 'author-information'),
