diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 4997a23991b5af7b8c4fcb09ecf4c434bbf9010e..33d2a0e0c0f6dddc66932e0d1359dce05a47628e 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1303,11 +1303,10 @@ function install_check_localization_server($uri) { /** * Gets the core release version and release alternatives for localization. * - * In case core is a development version or the translation file for the release - * is not available, fall back to the latest stable release. For example, - * 8.2-dev might fall back to 8.1 and 8.0-dev might fall back to 7.0. Fallback - * is required because the localization server only provides translation files - * for stable releases. + * In case core is a development version or the translation file for the + * release is not available, fall back to an earlier release. + * For example, 8.2.0-dev might fall back to 8.1.0 and 8.0.0-dev + * might fall back to 7.0. * * @param string $version * (optional) Version of core trying to find translation files for. @@ -1315,90 +1314,87 @@ function install_check_localization_server($uri) { * @return array * Array of release data. Each array element is an associative array with: * - core: Core compatibility version (e.g., 8.x). - * - version: Release version (e.g., 8.1). + * - version: Release version (e.g., 8.1.0). */ function install_get_localization_release($version = \Drupal::VERSION) { $releases = array(); $alternatives = array(); - // The version string is broken up into: - // - major: Major version (e.g., "8"). - // - minor: Minor version (e.g., "0"). - // - extra: Extra version info (e.g., "alpha2"). - // - extra_text: The text part of "extra" (e.g., "alpha"). - // - extra_number: The number part of "extra" (e.g., "2"). $info = _install_get_version_info($version); + // This code assumes there is a first alpha available as "alpha1". For + // Drupal 8.0.0 that isn't the case. In addition the semantic versioning + // wasn't introduced before "alpha14". However, we have already gotten to + // "beta1" so we are ignoring this for now. + + // The fallback detection is relaxed - removing version duplicates at the end. + // Check if the version is a regular stable release (no 'rc', 'beta', 'alpha', // 'dev', etc.) if (!isset($info['extra_text'])) { // First version alternative: the current version. $alternatives[] = $version; - // Point-releases: previous minor release (e.g., 8.2 falls back to 8.1). - if ($info['minor'] > 0) { - $alternatives[]= $info['major'] . '.' . ($info['minor'] - 1); + + // Patch-level: Previous and zero patch level (e.g., 8.2.4 falls back to + // 8.2.3 and 8.2.0). + if ($info['patch'] > 0) { + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.' . ($info['patch'] - 1); + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0'; } - // Zero release: first release candidate (e.g., 8.0 falls back to 8.0-rc1). + // Zero patch: First release candidate (e.g., 8.0.0 falls back to + // 8.0.0-rc1). else { - $alternatives[] = $info['major'] . '.0-rc1'; + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-rc1'; + } + // Point-releases: Previous and zero minor release (e.g., 8.2.x falls back + // to 8.1.0 and 8.0.0). + if ($info['minor'] > 0) { + $alternatives[] = $info['major'] . '.' . ($info['minor'] - 1) . '.0'; + $alternatives[] = $info['major'] . '.0.0'; } } else { - switch ($info['extra_text']) { - // Alpha release: current alpha or previous alpha release (e.g. 8.0-alpha2 - // falls back to 8.0-alpha1). - case 'alpha': - $alternatives[] = $version; - if ($info['extra_number'] > 1) { - $alternatives[] = $info['major'] . '.0-alpha' . ($info['extra_number'] - 1); - } - break; - - // Beta release: current beta or previous beta release (e.g. 8.0-beta2 - // falls back to 8.0-beta1) or first alpha release. - case 'beta': - $alternatives[] = $version; - if ($info['extra_number'] > 1) { - $alternatives[] = $info['major'] . '.0-beta' . ($info['extra_number'] - 1); - } - else { - $alternatives[] = $info['major'] . '.0-alpha2'; - } - break; - - // Dev release: the previous point release (e.g., 8.2-dev falls back to - // 8.1) or any unstable release (e.g., 8.0-dev falls back to 8.0-rc1, - // 8.0-beta1 or 8.0-alpha12) - case 'dev': - if ($info['minor'] >= 1) { - $alternatives[] = $info['major'] . '.' . ($info['minor'] - 1); - } - else { - $alternatives[] = $info['major'] . '.0-rc1'; - $alternatives[] = $info['major'] . '.0-beta1'; - $alternatives[] = $info['major'] . '.0-alpha12'; - } - break; - - // Release candidate: the current or previous release candidate (e.g., - // 8.0-rc2 falls back to 8.0-rc1) or the first beta release. - case 'rc': - $alternatives[] = $version; - if ($info['extra_number'] >= 2) { - $alternatives[] = $info['major'] . '.0-rc' . ($info['extra_number'] - 1); - } - else { - $alternatives[] = $info['major'] . '.0-beta1'; - } - break; + // Below we assume that for all dev, alpha, beta or rc releases the patch + // level is 0. + + $release_levels = array('rc', 'beta', 'alpha'); + + if ($info['extra_text'] == 'dev') { + // Dev release: Any unstable release (e.g., 8.2.0-dev falls back to + // 8.2.0-rc1, 8.2.0-beta1 and 8.2.0-alpha1). + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-rc1'; + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-beta1'; + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-alpha1'; + } + elseif (in_array($info['extra_text'], $release_levels)) { + // All other unstable release always includes the current version. + $alternatives[] = $version; + // Alpha release: Previous alpha release (e.g. 8.0.0-alpha2 falls back to + // 8.0.0-alpha1). + // Beta release: Previous beta release and first alpha release (e.g. + // 8.0.0-beta2 falls back to 8.0.0-beta1 and 8.0.0-alpha1). + // Release candidate: Previous release candidate and the first beta + // release (e.g. 8.0.0-rc2 falls back to 8.0.0-rc1 and 8.0.0-beta1). + $release_level_key = array_search($info['extra_text'], $release_levels); + if ($info['extra_number'] > 1) { + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-' . $info['extra_text'] . ($info['extra_number'] - 1); + } + if ($info['extra_text'] != 'alpha') { + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0-' . $release_levels[$release_level_key + 1] . '1'; + } + } + else { + $alternatives[] = $info['major'] . '.' . $info['minor'] . '.0'; + } + // All unstable releases except the zero release: The previous minor release + // and the zero release. + if ($info['minor'] > 0) { + $alternatives[] = $info['major'] . '.' . ($info['minor'] - 1) . '.0'; + $alternatives[] = $info['major'] . '.0.0'; } } - // All releases may fall back to the previous major release (e.g., 8.1 falls - // back to 7.0, 8.x-dev falls back to 7.0). This will probably only be used - // for early dev releases or languages with an inactive translation team. - $alternatives[] = $info['major'] - 1 . '.0'; - + $alternatives = array_unique($alternatives); foreach ($alternatives as $alternative) { list($core) = explode('.', $alternative); $releases[] = array( @@ -1407,6 +1403,23 @@ function install_get_localization_release($version = \Drupal::VERSION) { ); } + // All releases may fall back to the previous major release (e.g., 8.1.0 + // may fall back to 7.0). This will probably only be used for early dev + // releases or languages with an inactive translation team. + if ($info['major'] == 8) { + $releases[] = array( + 'core' => '7.x', + 'version' => '7.0', + ); + } + else { + $prev_major = $info['major'] - 1; + $releases[] = array( + 'core' => $prev_major . '.x', + 'version' => $prev_major . '.0.0', + ); + } + return $releases; } @@ -1414,14 +1427,14 @@ function install_get_localization_release($version = \Drupal::VERSION) { * Extracts version information from a drupal core version string. * * @param string $version - * Version info string (e.g., 8.0, 8.1, 8.0-dev, 8.0-unstable1, 8.0-alpha2, - * 8.0-beta3, and 8.0-rc4). - * + * Version info string (e.g., 8.0.0, 8.1.0, 8.0.0-dev, 8.0.0-unstable1, + * 8.0.0-alpha2, 8.0.0-beta3, and 8.0.0-rc4). * * @return array * Associative array of version info: * - major: Major version (e.g., "8"). * - minor: Minor version (e.g., "0"). + * - patch: Patch version (e.g., "0"). * - extra: Extra version info (e.g., "alpha2"). * - extra_text: The text part of "extra" (e.g., "alpha"). * - extra_number: The number part of "extra" (e.g., "2"). @@ -1432,6 +1445,8 @@ function _install_get_version_info($version) { (?P[0-9]+) # Major release number. \. # . (?P[0-9]+) # Minor release number. + \. # . + (?P[0-9]+) # Patch release number. ) # ( # - # - separator for "extra" version information. diff --git a/core/modules/system/src/Tests/Installer/InstallerTranslationVersionUnitTest.php b/core/modules/system/src/Tests/Installer/InstallerTranslationVersionUnitTest.php index 031a79de3003c36f594c802403ee176a25951e11..882af17f941cef3586d62e5a9084885a4cd4c7a8 100644 --- a/core/modules/system/src/Tests/Installer/InstallerTranslationVersionUnitTest.php +++ b/core/modules/system/src/Tests/Installer/InstallerTranslationVersionUnitTest.php @@ -62,56 +62,84 @@ protected function assertVersionFallback($version, $fallback, $message = '', $gr * Tests version fallback of install_get_localization_release(). */ public function testVersionFallback() { - $version = '8.0'; - $fallback = array('8.0', '8.0-rc1', '7.0'); + $version = '8.0.0'; + $fallback = array('8.0.0', '8.0.0-rc1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.1'; - $fallback = array('8.1', '8.0', '7.0'); + $version = '8.1.0'; + $fallback = array('8.1.0', '8.1.0-rc1', '8.0.0', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.12'; - $fallback = array('8.12', '8.11', '7.0'); + $version = '8.12.0'; + $fallback = array('8.12.0', '8.12.0-rc1', '8.11.0', '8.0.0', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-dev'; - $fallback = array('8.0-rc1', '8.0-beta1', '8.0-alpha12', '7.0'); + $version = '8.0.0-dev'; + $fallback = array('8.0.0-rc1', '8.0.0-beta1', '8.0.0-alpha1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.9-dev'; - $fallback = array('8.8', '7.0'); + $version = '8.9.0-dev'; + $fallback = array('8.9.0-rc1', '8.9.0-beta1', '8.9.0-alpha1', '8.8.0', '8.0.0', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-alpha3'; - $fallback = array('8.0-alpha3', '8.0-alpha2', '7.0'); + $version = '8.0.0-alpha3'; + $fallback = array('8.0.0-alpha3', '8.0.0-alpha2', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-alpha1'; - $fallback = array('8.0-alpha1', '7.0'); + $version = '8.0.0-alpha1'; + $fallback = array('8.0.0-alpha1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-beta2'; - $fallback = array('8.0-beta2', '8.0-beta1', '7.0'); + $version = '8.0.0-beta2'; + $fallback = array('8.0.0-beta2', '8.0.0-beta1', '8.0.0-alpha1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-beta1'; - $fallback = array('8.0-beta1', '8.0-alpha2', '7.0'); + $version = '8.0.0-beta1'; + $fallback = array('8.0.0-beta1', '8.0.0-alpha1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-rc8'; - $fallback = array('8.0-rc8', '8.0-rc7', '7.0'); + $version = '8.0.0-rc8'; + $fallback = array('8.0.0-rc8', '8.0.0-rc7', '8.0.0-beta1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-rc1'; - $fallback = array('8.0-rc1', '8.0-beta1', '7.0'); + $version = '8.0.0-rc1'; + $fallback = array('8.0.0-rc1', '8.0.0-beta1', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '8.0-foo2'; - $fallback = array('7.0'); + $version = '8.2.0-beta1'; + $fallback = array('8.2.0-beta1', '8.2.0-alpha1', '8.1.0', '8.0.0', '7.0'); $this->assertVersionFallback($version, $fallback); - $version = '99.2'; - $fallback = array('99.2', '99.1', '98.0'); + $version = '8.2.0-beta7'; + $fallback = array('8.2.0-beta7', '8.2.0-beta6', '8.2.0-alpha1', '8.1.0', '8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '8.2.0-rc1'; + $fallback = array('8.2.0-rc1', '8.2.0-beta1', '8.1.0', '8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '8.2.0-rc2'; + $fallback = array('8.2.0-rc2', '8.2.0-rc1', '8.2.0-beta1', '8.1.0', '8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '8.0.0-foo2'; + $fallback = array('8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '8.0.4'; + $fallback = array('8.0.4', '8.0.3', '8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '8.3.5'; + $fallback = array('8.3.5', '8.3.4', '8.3.0', '8.2.0', '8.0.0', '7.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '99.0.1'; + $fallback = array('99.0.1', '99.0.0' ,'98.0.0'); + $this->assertVersionFallback($version, $fallback); + + $version = '99.7.1'; + $fallback = array('99.7.1', '99.7.0', '99.6.0', '99.0.0' ,'98.0.0'); $this->assertVersionFallback($version, $fallback); } }