commit 9c189d6adb4ccf6048cd4170ff0004b27097495b Author: Erik Stielstra Date: Mon Sep 8 18:36:36 2014 +0200 #23 diff --git a/core/modules/locale/lib/Drupal/locale/ProjectTranslationState.php b/core/modules/locale/lib/Drupal/locale/ProjectTranslationState.php deleted file mode 100644 index 894e4c5..0000000 --- a/core/modules/locale/lib/Drupal/locale/ProjectTranslationState.php +++ /dev/null @@ -1,405 +0,0 @@ -projectName = $project_name; - } - - public function __destruct() { - foreach ($this->stateByLanguage as $langcode => $state) { - // @todo Need to check if changed? - $this->saveState($langcode); - } - } - - /** - * Returns the machine name of the project. - */ - public function getName() { - return $this->projectName; - } - - /** - * Returns the human readable name of the project. - */ - public function getHumanName() { - return $this->projectHumanName; - } - - /** - * Sets the language this project is translated to. - * - * @param $langcode - */ - public function setLangcode($langcode) { - // @todo Need to check if language is translatable? - $this->langcode = $langcode; - if (!isset($this->stateByLanguage[$langcode])) { - $this->initState(); - } - $this->timestamp = &$this->stateByLanguage[$langcode]->timestamp; - $this->lastChecked = &$this->stateByLanguage[$langcode]->lastChecked; - $this->latestSource = &$this->stateByLanguage[$langcode]->latestSource; - $this->latestSourceTimestamp = &$this->stateByLanguage[$langcode]->latestSourceTimestamp; - $this->localSource = &$this->stateByLanguage[$langcode]->localSource; - $this->remoteSource = &$this->stateByLanguage[$langcode]->remoteSource; - } - - /** - * Deletes stored data of specified language. - */ - public function deleteLangcode($langcode) { - \Drupal::state()->delete('locale.translation_status.' . $this->projectName . '.' . $langcode); - } - - /** - * Returns the local source state. - */ - public function getLocalSource() { - if (!empty($this->localSource)) { - return $this->localSource; - } - return FALSE; - } - - /** - * Returns the remote source state. - */ - public function getRemoteSource() { - if (!empty($this->remoteSource)) { - return $this->remoteSource; - } - return FALSE; - } - - public function getLatestSourceTimestamp() { - return $this->latestSourceTimestamp; - } - - public function getVersion() { - return $this->projectVersion; - } - - /** - * Whether the remote source is valid and can be checked or downloaded. - * - * @return bool - * Returns FALSE if the project version is a dev release. No translations - * are available for dev releases. - */ - public function remoteIsValid() { - // @todo Return FALSE if file was not found (404) less than x time ago. - if ($this->projectVersion && strpos('dev', $this->projectVersion) !== FALSE) { - return FALSE; - } - return TRUE; - } - - /** - * Whether a remote source file is available and can be downloaded. - * - * @return bool - * Returns FALSE if the project version is a dev release. No translations - * are available for dev releases. - */ - public function remoteIsAvailable() { - return $this->remoteIsValid() && $this->latestSource == 'remote'; - } - - /** - * Whether the local source is available and can be imported. - * - * @return bool - * Returns FALSE if the project version is a dev release. No translations - * are available for dev releases. - */ - public function localIsAvailable() { - return $this->latestSource == 'local'; - } - - public function remoteIsLatest() { - return $this->latestSource == 'remote'; - } - - public function localIsLatest() { - return $this->latestSource == 'local'; - } - - /** - * Updates the translation state with local source data. - * - * @param $data - */ - public function updateLocalSource($data) { - $this->localSource = $data; - $this->localSource->lastChecked = REQUEST_TIME; - - // If the local translation is the most recent, we update the latestSource - // status. Otherwise only mark the current translation as checked. If remote - // and local have the same timestamp, the local source is chosen. - if ($data->timestamp > $this->latestSourceTimestamp || ($data->timestamp >= $this->latestSourceTimestamp && $this->latestSource == 'remote')) { - $this->latestSource = 'local'; - $this->latestSourceTimestamp = $data->timestamp; - } - else { - $this->lastChecked = REQUEST_TIME; - } - } - - /** - * Updates the translation state with remote source data. - * - * @param $data - */ - public function updateRemoteSource($data) { - $this->remoteSource = $data; - $this->remoteSource->lastChecked = REQUEST_TIME; - - // If the remote translation is the most recent, we update the latestSource - // status. Otherwise mark the current translation as checked. - if ($data->timestamp > $this->latestSourceTimestamp) { - $this->latestSource = 'remote'; - $this->latestSourceTimestamp = $data->timestamp; - } - else { - $this->lastChecked = REQUEST_TIME; - } - } - - /** - * Updates the translation state with the timestamp of a newly imported translation. - * - * @param $timestamp - */ - public function updateTimestamp($timestamp) { - $this->timestamp = $timestamp; - $this->lastChecked = REQUEST_TIME; - - $this->latestSource = 'current'; - $this->latestSourceTimestamp = $timestamp; - } - - /** - * Whether this project is translated in language $langcode. - * - * @return bool - * Returns TRUE if this project is translated. - */ - public function isTranslated() { - return $this->timestamp > 0; - } - - /** - * Whether translation updates are available for this language. - * - * @return bool - * Returns TRUE if a local or remote translation update is available. - */ - public function hasUpdates() { - return $this->latestSource == 'local' || $this->latestSource == 'remote' ; - } - - /* - * Initializes the translation state by loading from cache or building a new one. - */ - protected function initState() { - if (empty($this->projectCore)) { - $this->loadProject(); - } - $this->loadState(); - if (empty($this->stateByLanguage[$this->langcode])) { - $this->stateByLanguage[$this->langcode] = $this->buildState(); - } - } - - /** - * Loads the project data. - */ - protected function loadProject() { - module_load_include('translation.inc', 'locale'); - // @todo Make a singular function based on locale_translation_get_projects() - //$project = locale_translation_get_project($this->projectName); - // @todo Follow-up issue to convert project into an object, so we don't have - // to call a procedural function here. https://drupal.org/node/1832946 - $project = locale_translation_get_projects(array($this->projectName)); - $project = $project[$this->projectName]; - if (empty($project)) { - // @todo Throw exception. - } - $this->projectHumanName = $this->projectName . ' (TODO)'; - $this->projectVersion = $project->version; - $this->projectCore = $project->core; - $this->serverPattern = $project->server_pattern; - } - - /** - * Builds a new translation state. - */ - protected function buildState() { - $state = new \stdClass(); - $state->timestamp = 0; - $state->lastChecked = 0; - $state->latestSource = ''; - $state->latestSourceTimestamp = 0; - $state->localSource = $this->buildLocalSource(); - $state->remoteSource = $this->buildRemoteSource(); - - return $state; - } - - /** - * Builds a local translation source object. - */ - protected function buildLocalSource() { - $filename = config('locale.settings')->get('translation.default_filename'); - $source = new \stdClass(); - if ($this->fileIsRemote($this->serverPattern)) { - $source->filename = $this->buildServerPattern($filename); - $source->directory = 'translations://'; - $source->uri = $source->directory . $source->filename; - } - else { - $source->filename = $this->buildServerPattern(basename($this->serverPattern)); - $source->directory = $this->buildServerPattern(drupal_dirname($this->serverPattern)); - $source->uri = $source->directory . '/' . $source->filename; - } - return $source; - } - - /** - * Builds a local translation source object. - */ - protected function buildRemoteSource() { - $source = new \stdClass(); - if ($this->fileIsRemote($this->serverPattern)) { - $source->filename = $this->buildServerPattern(basename($this->serverPattern)); - $source->uri = $this->buildServerPattern($this->serverPattern); - } - return $source; - } - - /** - * Builds uri of a translation file out of a server path replacement pattern. - * - * @param string $template - * Uri template string containing placeholders. Available placeholders: - * - "%project": Project name. - * - "%version": Project version. - * - "%core": Project core version. - * - "%language": Language code. - * - * @return string - * File uri with replaced placeholders. - */ - protected function buildServerPattern($template) { - $variables = array( - '%project' => $this->projectName, - '%version' => $this->projectVersion, - '%core' => $this->projectCore, - '%language' => $this->langcode, - ); - return strtr($template, $variables); - } - - /** - * Loads the translation state. - */ - protected function loadState() { - return $this->stateByLanguage[$this->langcode] = \Drupal::state()->get('locale.translation_status.' . $this->projectName . '.' . $this->langcode, NULL); - } - - /** - * Saves the translation state. - * - * @param $langcode - */ - protected function saveState() { - // @todo Need to check if data changed? (hash of lastChecked timestamps). - \Drupal::state()->set('locale.translation_status.' . $this->projectName . '.' . $this->langcode, $this->stateByLanguage[$this->langcode]); - } - - protected function fileIsRemote($uri) { - $scheme = file_uri_scheme($uri); - if ($scheme) { - return !drupal_realpath($scheme . '://'); - } - return FALSE; - } -} diff --git a/core/modules/locale/locale.batch.inc b/core/modules/locale/locale.batch.inc index 6738f94..7bea448 100644 --- a/core/modules/locale/locale.batch.inc +++ b/core/modules/locale/locale.batch.inc @@ -6,7 +6,7 @@ */ use GuzzleHttp\Exception\RequestException; -use Drupal\locale\ProjectTranslationState; +use Drupal\locale\LocaleTranslatableProject; /** * Load the common translation API. @@ -21,7 +21,7 @@ * Checks the presence and creation time po translation files in located at * remote server location and local file system. * - * @param string $project + * @param string $project_id * Machine name of the project for which to check the translation status. * @param string $langcode * Language code of the language for which to check the translation. @@ -34,53 +34,59 @@ * @param array $context * The batch context. */ -function locale_translation_batch_status_check($project, $langcode, $options = array(), &$context) { +function locale_translation_batch_status_check($project_id, $langcode, $options = array(), &$context) { + $failure = $checked = FALSE; $options += array( 'finish_feedback' => TRUE, 'use_remote' => TRUE, ); - // @todo Class ProjectTranslationState must be overridable. - $project_state = new ProjectTranslationState($project); - $project_state->setLangcode($langcode); - // Check the status of local translation files. - if ($source = $project_state->getLocalSource()) { - if ($local_file = locale_translation_source_check_file($source)) { - $project_state->updateLocalSource($local_file); - } - $checked = TRUE; - } + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get($project_id); + if ($project) { + $project->setLangcode($langcode); - // Check the status of remote translation files. - if ($options['use_remote'] && $project_state->remoteIsValid() && $remote_file = $project_state->getRemoteSource()) { - if ($result = locale_translation_http_check($remote_file->uri)) { - // Update the file object with the result data. In case of a redirect we - // store the resulting uri. - if (isset($result['last_modified'])) { - $remote_file->uri = isset($result['location']) ? $result['location'] : $remote_file->uri; - $remote_file->timestamp = $result['last_modified']; - $project_state->updateRemoteSource($remote_file); + // Check the status of local translation files. + if ($source = $project->getLocalSource()) { + if ($local_file = locale_translation_source_check_file($source)) { + $project->updateLocalSource($local_file); + \Drupal::service('locale.project')->set($project); } - // @todo What to do with when the file is not found (404)? To prevent - // re-checking within the TTL (1day, 1week) we can set a last_checked - // timestamp or cache the result. $checked = TRUE; } - else { - $failure = TRUE; + + // Check the status of remote translation files. + if ($options['use_remote'] && $project->remoteIsValid() && $remote_file = $project->getRemoteSource()) { + if ($result = locale_translation_http_check($remote_file->uri)) { + // Update the file object with the result data. In case of a redirect we + // store the resulting uri. + if (isset($result['last_modified'])) { + $remote_file->uri = isset($result['location']) ? $result['location'] : $remote_file->uri; + $remote_file->timestamp = $result['last_modified']; + $project->updateRemoteSource($remote_file); + \Drupal::service('locale.project')->set($project); + } + // @todo What to do with when the file is not found (404)? To prevent + // re-checking within the TTL (1day, 1week) we can set a last_checked + // timestamp or cache the result. + $checked = TRUE; + } + else { + $failure = TRUE; + } } - } - // Provide user feedback and record success or failure for reporting at the - // end of the batch. - if ($options['finish_feedback'] && $checked) { - $context['results']['files'][] = $project_state->getName(); - } - if ($failure && !$checked) { - $context['results']['failed_files'][] = $project_state->getName(); + // Provide user feedback and record success or failure for reporting at the + // end of the batch. + if ($options['finish_feedback'] && $checked) { + $context['results']['files'][] = $project->id(); + } + if ($failure && !$checked) { + $context['results']['failed_files'][] = $project->id(); + } + $context['message'] = t('Checked translation for %project.', array('%project' => $project->getName())); } - $context['message'] = t('Checked translation for %project.', array('%project' => $project_state->getHumanName())); } /** @@ -125,8 +131,8 @@ function locale_translation_batch_status_finished($success, $results) { * Downloads a remote gettext file into the translations directory. When * successfully the translation status is updated. * - * @param object $project - * Source object of the translatable project. + * @param string $project_id + * The id of the translatable project. * @param string $langcode * Language code. * @param array $context @@ -134,18 +140,21 @@ function locale_translation_batch_status_finished($success, $results) { * * @see locale_translation_batch_fetch_import() */ -function locale_translation_batch_fetch_download($project, $langcode, &$context) { - $project_state = new ProjectTranslationState($project); - $project_state->setLangcode($langcode); +function locale_translation_batch_fetch_download($project_id, $langcode, &$context) { + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get($project_id); + if ($project) { + $project->setLangcode($langcode); - if ($project_state->remoteIsAvailable() && $remote = $project_state->getRemoteSource()) { - $t = get_t(); - if ($result = locale_translation_download_source($remote, 'translations://')) { - $context['message'] = $t('Downloaded translation for %project.', array('%project' => $project_state->getHumanName())); - $project_state->updateLocalSource($result); - } - else { - $context['results']['failed_files'][] = $remote; + if ($project->remoteIsAvailable() && $remote = $project->getRemoteSource()) { + if ($result = locale_translation_download_source($remote, 'translations://')) { + $context['message'] = t('Downloaded translation for %project.', array('%project' => $project->getName())); + $project->updateLocalSource($result); + \Drupal::service('locale.project')->set($project); + } + else { + $context['results']['failed_files'][] = $remote; + } } } } @@ -156,8 +165,8 @@ function locale_translation_batch_fetch_download($project, $langcode, &$context) * Imports a gettext file from the translation directory. When successfully the * translation status is updated. * - * @param object $project - * Source object of the translatable project. + * @param string $project_id + * The id of the translatable project. * @param string $langcode * Language code. * @param array $options @@ -168,29 +177,32 @@ function locale_translation_batch_fetch_download($project, $langcode, &$context) * @see locale_translate_batch_import_files() * @see locale_translation_batch_fetch_download() */ -function locale_translation_batch_fetch_import($project, $langcode, $options, &$context) { - $project_state = new ProjectTranslationState($project); - $project_state->setLangcode($langcode); +function locale_translation_batch_fetch_import($project_id, $langcode, $options, &$context) { + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get($project_id); + if ($project) { + $project->setLangcode($langcode); - if ($project_state->localIsAvailable() && $local = $project_state->getLocalSource()) { - $local->langcode = $langcode; - $t = get_t(); - module_load_include('bulk.inc', 'locale'); - $options += array( - 'message' => $t('Importing translation for %project.', array('%project' => $project_state->getHumanName())), - ); - // Import the translation file. For large files the batch operations is - // progressive and will be called repeatedly until finished. - locale_translate_batch_import($local, $options, $context); + if ($project->localIsAvailable() && $local = $project->getLocalSource()) { + $local->langcode = $langcode; + module_load_include('bulk.inc', 'locale'); + $options += array( + 'message' => t('Importing translation for %project.', array('%project' => $project->getName())), + ); + // Import the translation file. For large files the batch operations is + // progressive and will be called repeatedly until finished. + locale_translate_batch_import($local, $options, $context); - // The import is finished. - if (isset($context['finished']) && $context['finished'] == 1) { - // The import is successfull. - if (isset($context['results']['files'][$local->uri])) { - $context['message'] = $t('Imported translation for %project.', array('%project' => $project_state->getHumanName())); + // The import is finished. + if (isset($context['finished']) && $context['finished'] == 1) { + // The import is successful. + if (isset($context['results']['files'][$local->uri])) { + $context['message'] = t('Imported translation for %project.', array('%project' => $project->getName())); - // Update the current translation timestamp. - $project_state->updateTimestamp($local->timestamp); + // Update the current translation timestamp. + $project->updateTimestamp($local->timestamp); + \Drupal::service('locale.project')->set($project); + } } } } diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc index 6da3a51..a3e8422 100644 --- a/core/modules/locale/locale.compare.inc +++ b/core/modules/locale/locale.compare.inc @@ -85,7 +85,8 @@ function locale_translation_build_projects() { // For every project store information. $data += array( - 'name' => $name, + 'id' => $name, + 'name' => $data['info']['name'], 'version' => isset($data['info']['version']) ? $data['info']['version'] : '', 'core' => isset($data['info']['core']) ? $data['info']['core'] : \Drupal::CORE_COMPATIBILITY, // A project can provide the path and filename pattern to download the @@ -93,11 +94,11 @@ function locale_translation_build_projects() { 'server_pattern' => isset($data['info']['interface translation server pattern']) && $data['info']['interface translation server pattern'] ? $data['info']['interface translation server pattern'] : $default_server['pattern'], 'status' => !empty($data['project_status']) ? 1 : 0, ); - $project = (object) $data; - $projects[$name] = $project; - // Create or update the project record. - \Drupal::service('locale.project')->set($project->name, $data); + $project = new \Drupal\locale\LocaleTranslatableProject($data); + $projects[$name] = $project; + $project->initLangcodeMultiple(array_keys(locale_translatable_language_list())); + \Drupal::service('locale.project')->set($project); // Invalidate the cache of translatable projects. locale_translation_clear_cache_projects(); @@ -321,14 +322,13 @@ function locale_translation_check_projects_local($projects = array(), $langcodes // For each project and each language we check if a local po file is // available. When found the source object is updated with the appropriate // type and timestamp of the po file. + /** @var \Drupal\locale\LocaleTranslatableProject $project */ foreach ($projects as $name => $project) { - // @todo ProjectTranslationState must be overridable. - $project_state = new ProjectTranslationState($project); foreach ($langcodes as $langcode) { - $project_state->setLangcode($langcode); - $local = $project_state->getLocal(); + $project->setLangcode($langcode); + $local = $project->getLocalSource(); $file = locale_translation_source_check_file($local); - $project_state->updateLocalSource($file); + $project->updateLocalSource($file); } } } diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 197eded..a6bdb24 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -243,15 +243,18 @@ function locale_requirements($phase) { if ($languages) { // Determine the status of the translation updates per language. - $status = locale_translation_get_status(); - if ($status) { - foreach ($status as $project) { - foreach ($project as $langcode => $project_info) { - if (empty($project_info->type)) { - $untranslated[$langcode] = $languages[$langcode]->name; + $projects = locale_translation_get_status(); + if ($projects) { + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + foreach ($projects as $project) { + /** @var \Drupal\Core\Language\Language $language */ + foreach ($languages as $langcode => $language) { + $project->setLangcode($langcode); + if (!$project->isTranslated()) { + $untranslated[$langcode] = $language->getName(); } - elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) { - $available_updates[$langcode] = $languages[$langcode]->name; + elseif ($project->hasUpdates()) { + $available_updates[$langcode] = $language->getName(); } } } diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 5e66531..1eeebd4 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -21,7 +21,7 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Component\Utility\Crypt; -use Drupal\locale\ProjectTranslationState; +use Drupal\locale\LocaleTranslatableProject; /** * Regular expression pattern used to localize JavaScript strings. @@ -888,25 +888,26 @@ function locale_translation_file_history_delete($projects = array(), $langcodes /** * Gets the current translation status. * - * @todo What is 'translation status'? + * @param array|NULL $project_names + * Array of project machine names for which to get the translation status. + * Defaults to all projects. + * @param array|NULL $langcodes + * Array of language codes for which to get the translation status. Defaults + * to all languages. + * + * @return array + * Array of translatable project objects. */ -function locale_translation_get_status($projects = NULL, $langcodes = NULL) { - $result = array(); - module_load_include('translation.inc', 'locale'); - $projects = $projects ? $projects : array_keys(locale_translation_get_projects()); - $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); - - // Get the translation status of each project-language combination. If no - // status was stored, a new translation source is created. - foreach ($projects as $project) { - foreach ($langcodes as $langcode) { - // @todo ProjectTranslationState object needs a method to clear its own data. - if ($status = Drupal::state()->get('locale.translation_status.' . $project . '.' . $langcode, NULL)) { - $result[$project][$langcode] = $status; - } - } +// @todo deprecate/remove this function? +// @todo Is $langcode param needed? +function locale_translation_get_status($project_names = NULL, $langcodes = NULL) { + + if ($project_names) { + return \Drupal::service('locale.project')->getMultiple($project_names); + } + else { + return \Drupal::service('locale.project')->getAll(); } - return $result; } /** @@ -917,13 +918,13 @@ function locale_translation_get_status($projects = NULL, $langcodes = NULL) { */ function locale_translation_status_delete_languages($langcodes) { $projects = locale_translation_get_projects(); - foreach (array_keys($projects) as $project) { + /** @var \Drupal\locale\LocaleTranslatableProject $project */ + foreach ($projects as $key => $project) { foreach ($langcodes as $langcode) { - // @todo ProjectTranslationState object needs a method to clear its own data. - Drupal::state() - ->delete('locale.translation_status.' . $project . '.' . $langcode); + $projects[$key]->removeLangcode($langcode); } } + \Drupal::service('locale.project')->setMultiple($projects); } /** @@ -933,29 +934,16 @@ function locale_translation_status_delete_languages($langcodes) { * Project name(s) to be deleted from the cache. */ function locale_translation_status_delete_projects($projects) { - $status = locale_translation_get_status(); - foreach ($status as $project => $languages) { - if (in_array($project, $projects)) { - unset($status[$project]); - } - } - \Drupal::state()->set('locale.translation_status', $status); + \Drupal::service('locale.project')->deleteMultiple($projects); } /** * Clear the translation status cache. */ +// @todo Deprecate function locale_translation_clear_status() { - $projects = locale_translation_get_projects(); - $langcodes = locale_translatable_language_list(); - foreach (array_keys($projects) as $project) { - foreach (array_keys($langcodes) as $langcode) { - Drupal::state() - ->delete('locale.translation_status.' . $project . '.' . $langcode); - } - } - \Drupal::state()->delete('locale.translation_last_checked'); + \Drupal::service('locale.project')->disableAll(); } /** diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index 01afdbd..a6178ca 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -11,7 +11,7 @@ use Drupal\locale\TranslationString; use Drupal\Component\Utility\String; use Symfony\Component\HttpFoundation\RedirectResponse; -use Drupal\locale\ProjectTranslationState; +use Drupal\locale\LocaleTranslatableProject; /** * Page callback: Checks for translation updates and displays the status. diff --git a/core/modules/locale/locale.translation.inc b/core/modules/locale/locale.translation.inc index fdeecaa..911c15f 100644 --- a/core/modules/locale/locale.translation.inc +++ b/core/modules/locale/locale.translation.inc @@ -21,7 +21,7 @@ * Array of names of the projects to get. * * @return array - * Array of project data for translation update. + * Array of translatable project classes for translation update. * * @see locale_translation_build_projects() */ @@ -40,9 +40,6 @@ function locale_translation_get_projects($project_names = array()) { locale_translation_build_projects(); } $projects = \Drupal::service('locale.project')->getAll(); - array_walk($projects, function(&$project) { - $project = (object) $project; - }); } // Return the requested project names or all projects. @@ -130,7 +127,7 @@ function locale_cron_fill_queue() { $last = REQUEST_TIME - $config->get('translation.update_interval_days') * 3600 * 24; $projects = \Drupal::service('locale.project')->getAll(); $projects = array_filter($projects, function($project) { - return $project['status'] == 1; + return $project->getStatus(); }); $files = db_select('locale_file', 'f') ->condition('f.project', array_keys($projects)) diff --git a/core/modules/locale/src/Form/TranslationStatusForm.php b/core/modules/locale/src/Form/TranslationStatusForm.php index df43b62..7d6e63d 100644 --- a/core/modules/locale/src/Form/TranslationStatusForm.php +++ b/core/modules/locale/src/Form/TranslationStatusForm.php @@ -70,15 +70,16 @@ public function getFormID() { */ public function buildForm(array $form, FormStateInterface $form_state) { $languages = locale_translatable_language_list(); - $status = locale_translation_get_status(); + $projects = locale_translation_get_status(); $options = array(); $languages_update = array(); $languages_not_found = array(); $projects_update = array(); + // Prepare information about projects which have available translation // updates. - if ($languages && $status) { - $updates = $this->prepareUpdateData($status); + if ($languages && $projects) { + $updates = $this->prepareUpdateData($projects, $languages); // Build data options for the select table. foreach ($updates as $langcode => $update) { @@ -105,7 +106,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { if (!empty($update['not_found'])) { $languages_not_found[$langcode] = $langcode; } - elseif (!empty($update['updates'])) { + if (!empty($update['updates'])) { $languages_update[$langcode] = $langcode; } } @@ -138,7 +139,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '@add_language' => $this->url('language.admin_overview'), )); } - elseif ($status) { + elseif ($projects) { $empty = $this->t('All translations up to date.'); } else { @@ -183,41 +184,37 @@ public function buildForm(array $form, FormStateInterface $form_state) { /** * Prepare information about projects with available translation updates. * - * @param array $status - * Translation update status as an array keyed by Project ID and langcode. + * @param array $projects + * Translatable projects as an array keyed by project ID. + * @param array $languages + * Translatable languages as an array keyed by langcode. * * @return array * Translation update status as an array keyed by language code and * translation update status. */ - protected function prepareUpdateData(array $status) { + protected function prepareUpdateData(array $projects, array $languages) { $updates = array(); - // @todo Calling locale_translation_build_projects() is an expensive way to - // get a module name. In follow-up issue http://drupal.org/node/1842362 - // the project name will be stored to display use, like here. - $this->moduleHandler->loadInclude('locale', 'compare.inc'); - $project_data = locale_translation_build_projects(); - - foreach ($status as $project_id => $project) { - foreach ($project as $langcode => $project_info) { + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + foreach ($projects as $project_id => $project) { + /** @var \Drupal\Core\Language\Language $language */ + foreach ($languages as $langcode => $language) { + $project->setLangcode($langcode); // No translation file found for this project-language combination. - if (empty($project_info->type)) { + if ($project->hasNoTranslation()) { $updates[$langcode]['not_found'][] = array( - 'name' => $project_info->name == 'drupal' ? $this->t('Drupal core') : $project_data[$project_info->name]->info['name'], - 'version' => $project_info->version, - 'info' => $this->createInfoString($project_info), + 'name' => $project->getName(), + 'version' => $project->getVersion(), + 'info' => $this->createInfoString($project), ); } // Translation update found for this project-language combination. - elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) { - $local = isset($project_info->files[LOCALE_TRANSLATION_LOCAL]) ? $project_info->files[LOCALE_TRANSLATION_LOCAL] : NULL; - $remote = isset($project_info->files[LOCALE_TRANSLATION_REMOTE]) ? $project_info->files[LOCALE_TRANSLATION_REMOTE] : NULL; - $recent = _locale_translation_source_compare($local, $remote) == LOCALE_TRANSLATION_SOURCE_COMPARE_LT ? $remote : $local; + elseif ($project->hasUpdates()) { $updates[$langcode]['updates'][] = array( - 'name' => $project_data[$project_info->name]->info['name'], - 'version' => $project_info->version, - 'timestamp' => $recent->timestamp, + 'name' => $project->getName(), + 'version' => $project->getVersion(), + 'timestamp' => $project->getLatestSourceTimestamp(), ); } } @@ -237,17 +234,19 @@ protected function prepareUpdateData(array $status) { * Translations for development versions are never fetched, so the debug info * for that is a fixed message. * - * @param array $project_info - * An array which is the project information of the source. + * @param \Drupal\locale\LocaleTranslatableProjectInterface $project + * The translatable project object. * * @return string * The string which contains debug information. */ - protected function createInfoString($project_info) { - $remote_path = isset($project_info->files['remote']->uri) ? $project_info->files['remote']->uri : FALSE; - $local_path = isset($project_info->files['local']->uri) ? $project_info->files['local']->uri : FALSE; + protected function createInfoString(\Drupal\locale\LocaleTranslatableProjectInterface $project) { + $remote_source = $project->getRemoteSource(); + $local_source = $project->getLocalSource(); + $remote_path = isset($remote_source->uri) ? $remote_source->uri : FALSE; + $local_path = isset($local_source->uri) ? $local_source->uri : FALSE; - if (strpos($project_info->version, 'dev') !== FALSE) { + if (strpos($project->getVersion(), 'dev') !== FALSE) { return $this->t('No translation files are provided for development releases.'); } if (locale_translation_use_remote_source() && $remote_path && $local_path) { diff --git a/core/modules/locale/src/LocaleProjectStorage.php b/core/modules/locale/src/LocaleProjectStorage.php index 65c83fc..d37dc07 100644 --- a/core/modules/locale/src/LocaleProjectStorage.php +++ b/core/modules/locale/src/LocaleProjectStorage.php @@ -25,6 +25,7 @@ class LocaleProjectStorage implements LocaleProjectStorageInterface { * Static state cache. * * @var array + * Array of translatable project classes. */ protected $cache = array(); @@ -59,6 +60,7 @@ public function get($key, $default = NULL) { public function getMultiple(array $keys) { $values = array(); $load = array(); + foreach ($keys as $key) { // Check if we have a value in the cache. if (isset($this->cache[$key])) { @@ -76,8 +78,8 @@ public function getMultiple(array $keys) { // If we find a value, even one that is NULL, add it to the cache and // return it. if (isset($loaded_values[$key])) { - $values[$key] = $loaded_values[$key]; - $this->cache[$key] = $loaded_values[$key]; + $values[$key] = $this->buildProject($loaded_values[$key]); + $this->cache[$key] = $values[$key]; } else { $this->cache[$key] = NULL; @@ -91,16 +93,17 @@ public function getMultiple(array $keys) { /** * {@inheritdoc} */ - public function set($key, $value) { - $this->setMultiple(array($key => $value)); + public function set(\Drupal\locale\LocaleTranslatableProjectInterface $project) { + $this->setMultiple(array($project->id() => $project)); } /** * {@inheritdoc} */ public function setMultiple(array $data) { - foreach ($data as $key => $value) { - $this->cache[$key] = $value; + foreach ($data as $key => $project) { + $this->cache[$key] = $project; + $data[$key] = $project->toArray(); } $this->keyValueStore->setMultiple($data); } @@ -142,15 +145,15 @@ public function deleteAll() { * {@inheritdoc} */ public function disableAll() { - $projects = $this->keyValueStore->getAll(); + $projects = $this->getAll(); foreach (array_keys($projects) as $key) { - $projects[$key]['status'] = 0; + $projects[$key]->setStatus(0); if (isset($cache[$key])) { $cache[$key] = $projects[$key]; } } - $this->keyValueStore->setMultiple($projects); + $this->setMultiple($projects); } /** @@ -165,9 +168,23 @@ public function countProjects() { */ public function getAll() { if (!static::$all) { - $this->cache = $this->keyValueStore->getAll(); + foreach ($this->keyValueStore->getAll() as $key => $value) { + $this->cache[$key] = $this->buildProject($value); + } static::$all = TRUE; } return $this->cache; } + + /** + * Builds translatable project object. + * + * @param array $data + * Project data. + * + * @return LocaleTranslatableProject + */ + protected function buildProject($data) { + return new \Drupal\locale\LocaleTranslatableProject($data); + } } diff --git a/core/modules/locale/src/LocaleProjectStorageInterface.php b/core/modules/locale/src/LocaleProjectStorageInterface.php index 876f05a..d75910d 100644 --- a/core/modules/locale/src/LocaleProjectStorageInterface.php +++ b/core/modules/locale/src/LocaleProjectStorageInterface.php @@ -2,7 +2,7 @@ /** * @file - * Contains Drupal\locale\LocalProjectStorageInterface. + * Contains Drupal\locale\LocaleProjectStorageInterface. */ namespace Drupal\locale; @@ -20,7 +20,7 @@ * @param mixed $default * The default value to use if the key is not found. * - * @return mixed + * @return \Drupal\locale\LocaleTranslatableProjectInterface|NULL * The stored value, or the default value if no value exists. */ public function get($key, $default = NULL); @@ -39,12 +39,10 @@ public function getMultiple(array $keys); /** * Creates or updates the project record. * - * @param string $key - * The key of the data to store. - * @param mixed $value - * The data to store. + * @param \Drupal\locale\LocaleTranslatableProjectInterface $project + * The project to store. */ - public function set($key, $value); + public function set(\Drupal\locale\LocaleTranslatableProjectInterface $project); /** * Creates or updates multiple project records. diff --git a/core/modules/locale/src/LocaleTranslatableProject.php b/core/modules/locale/src/LocaleTranslatableProject.php new file mode 100644 index 0000000..3a5ae70 --- /dev/null +++ b/core/modules/locale/src/LocaleTranslatableProject.php @@ -0,0 +1,520 @@ +getMapping() as $key => $property) { + if (isset($data[$key])) { + $this->$property = $data[$key]; + } + } + + // Override the module name of drupal core. The default name is the name + // of the first extension ('Action'). + if ($this->id == 'drupal') { + $this->name = 'Drupal core'; + } + } + + /** + * @inheritdoc + */ + public function id() { + + return $this->id; + } + + /** + * @inheritdoc + */ + public function getName() { + + return $this->name; + } + + /** + * @inheritdoc + */ + public function toArray() { + + $result = array(); + + foreach ($this->getMapping() as $key => $property) { + $result[$key] = $this->$property; + } + + return $result; + } + + /** + * @inheritdoc + */ + public function setLangcode($langcode) { + + $this->langcode = $langcode; + $this->initLangcode($langcode); + $this->timestamp = &$this->stateByLanguage[$langcode]->timestamp; + $this->lastChecked = &$this->stateByLanguage[$langcode]->lastChecked; + $this->latestSource = &$this->stateByLanguage[$langcode]->latestSource; + $this->latestSourceTimestamp = &$this->stateByLanguage[$langcode]->latestSourceTimestamp; + $this->localSource = &$this->stateByLanguage[$langcode]->localSource; + $this->remoteSource = &$this->stateByLanguage[$langcode]->remoteSource; + } + + /** + * @inheritdoc + */ + public function initLangcode($langcode) { + + if (empty($this->stateByLanguage[$langcode])) { + $this->initState($langcode); + } + } + + /** + * @inheritdoc + */ + public function initLangcodeMultiple(array $langcodes) { + + foreach ($langcodes as $langcode) { + $this->initLangcode($langcode); + } + } + + /** + * @inheritdoc + */ + public function getStatus() { + + return $this->status; + } + + /** + * @inheritdoc + */ + public function setStatus($status) { + + $this->status = $status ? 1 : 0; + } + + /** + * @inheritdoc + */ + public function removeLangcode($langcode) { + + unset($this->stateByLanguage[$langcode]); + } + + /** + * @inheritdoc + */ + public function clearTranslationStates() { + + foreach ($this->stateByLanguage as $langcode => $data) { + $this->stateByLanguage[$langcode]->localSource = NULL; + $this->stateByLanguage[$langcode]->remoteSource = NULL; + } + } + + /** + * @inheritdoc + */ + public function getLocalSource() { + + if (!empty($this->localSource)) { + return $this->localSource; + } + + return FALSE; + } + + /** + * @inheritdoc + */ + public function getRemoteSource() { + + if (!empty($this->remoteSource)) { + return $this->remoteSource; + } + + return FALSE; + } + + /** + * @inheritdoc + */ + public function getLatestSourceTimestamp() { + + return $this->latestSourceTimestamp; + } + + /** + * @inheritdoc + */ + public function getLatestSourceType() { + + return $this->latestSource; + } + + /** + * @inheritdoc + */ + public function getVersion() { + + return $this->projectVersion; + } + + /** + * @inheritdoc + */ + public function setVersion($version) { + + $this->projectVersion = $version; + } + + /** + * @inheritdoc + */ + public function remoteIsValid() { + + // @todo Return FALSE if file was not found (404) less than x time ago. + if ($this->projectVersion && strpos('dev', $this->projectVersion) !== FALSE) { + return FALSE; + } + + return TRUE; + } + + /** + * @inheritdoc + */ + public function remoteIsAvailable() { + + return $this->remoteIsValid() && $this->latestSource == 'remote'; + } + + /** + * @inheritdoc + */ + public function localIsAvailable() { + + return $this->latestSource == 'local'; + } + + /** + * @inheritdoc + */ + public function remoteIsLatest() { + + return $this->latestSource == 'remote'; + } + + /** + * @inheritdoc + */ + public function localIsLatest() { + + return $this->latestSource == 'local'; + } + + /** + * @inheritdoc + */ + public function updateLocalSource($data) { + + $this->localSource = $data; + $this->localSource->lastChecked = REQUEST_TIME; + + // If the local translation is the most recent, we update the latestSource + // status. Otherwise only mark the current translation as checked. If remote + // and local have the same timestamp, the local source is chosen. + if ($data->timestamp > $this->latestSourceTimestamp || ($data->timestamp >= $this->latestSourceTimestamp && $this->latestSource == 'remote')) { + $this->latestSource = 'local'; + $this->latestSourceTimestamp = $data->timestamp; + } + else { + $this->lastChecked = REQUEST_TIME; + } + } + + /** + * @inheritdoc + */ + public function updateRemoteSource($data) { + + $this->remoteSource = $data; + $this->remoteSource->lastChecked = REQUEST_TIME; + + // If the remote translation is the most recent, we update the latestSource + // status. Otherwise mark the current translation as checked. + if ($data->timestamp > $this->latestSourceTimestamp) { + $this->latestSource = 'remote'; + $this->latestSourceTimestamp = $data->timestamp; + } + else { + $this->lastChecked = REQUEST_TIME; + } + } + + /** + * @inheritdoc + */ + public function updateTimestamp($timestamp) { + + $this->timestamp = $timestamp; + $this->lastChecked = REQUEST_TIME; + + $this->latestSource = 'current'; + $this->latestSourceTimestamp = $timestamp; + } + + /** + * @inheritdoc + */ + public function isTranslated() { + + return $this->timestamp > 0; + } + + /** + * @inheritdoc + */ + public function hasUpdates() { + + return $this->latestSource == 'local' || $this->latestSource == 'remote'; + } + + /** + * @inheritdoc + */ + public function hasNoTranslation() { + + return $this->latestSource == ''; + } + + /* + * Initializes the translation state by loading from cache or building a new one. + * + * @param string $langcode + * Language code of the translation sources. + */ + protected function initState($langcode) { + + if (!isset($this->stateByLanguage[$langcode])) { + $state = new \stdClass(); + $state->timestamp = 0; + $state->lastChecked = 0; + $state->latestSource = ''; + $state->latestSourceTimestamp = 0; + $state->localSource = $this->buildLocalSource($langcode); + $state->remoteSource = $this->buildRemoteSource($langcode); + + $this->stateByLanguage[$langcode] = $state; + } + } + + /** + * Returns mapping for array to properties. + * + * @return array + * Key value array of mapping values. Keyed by array key, the values are the + * class property names. + */ + protected function getMapping() { + + // All properties are mapped except: + // - langcode + // - timestamp + // - lastChecked + // - latestSource + // - latestSourceTimestamp + // - localSource + // - remoteSource + return array( + 'id' => 'id', + 'name' => 'name', + 'version' => 'projectVersion', + 'core' => 'projectCore', + 'status' => 'status', + 'server_pattern' => 'serverPattern', + 'state_by_language' => 'stateByLanguage', + ); + } + + /** + * Builds a local translation source object. + * + * @param string $langcode + * Language code of the translation source. + * + * @return \stdClass + * Local source object. + */ + protected function buildLocalSource($langcode) { + + $filename = \Drupal::config('locale.settings')->get('translation.default_filename'); + $source = new \stdClass(); + if ($this->fileIsRemote($this->serverPattern)) { + $source->filename = $this->buildServerPattern($filename, $langcode); + $source->directory = 'translations://'; + $source->uri = $source->directory . $source->filename; + } + else { + $source->filename = $this->buildServerPattern(basename($this->serverPattern), $langcode); + $source->directory = $this->buildServerPattern(drupal_dirname($this->serverPattern), $langcode); + $source->uri = $source->directory . '/' . $source->filename; + } + + return $source; + } + + /** + * Builds a local translation source object. + * + * @param string $langcode + * Language code of the translation source. + * + * @return \stdClass + * Remote source object. + */ + protected function buildRemoteSource($langcode) { + + $source = new \stdClass(); + if ($this->fileIsRemote($this->serverPattern)) { + $source->filename = $this->buildServerPattern(basename($this->serverPattern), $langcode); + $source->uri = $this->buildServerPattern($this->serverPattern, $langcode); + } + + return $source; + } + + /** + * Builds uri of a translation file out of a server path replacement pattern. + * + * @param string $template + * Uri template string containing placeholders. Available placeholders: + * - "%project": Project name. + * - "%version": Project version. + * - "%core": Project core version. + * - "%language": Language code. + * @param string $langcode + * Language code of the translation file. + * + * @return string + * File uri with replaced placeholders. + */ + protected function buildServerPattern($template, $langcode) { + + $variables = array( + '%project' => $this->id, + '%version' => $this->projectVersion, + '%core' => $this->projectCore, + '%language' => $langcode, + ); + + return strtr($template, $variables); + } + + /** + * @todo + * + * @param $uri + * + * @return bool + */ + protected function fileIsRemote($uri) { + + $scheme = file_uri_scheme($uri); + if ($scheme) { + return !drupal_realpath($scheme . '://'); + } + + return FALSE; + } +} diff --git a/core/modules/locale/src/LocaleTranslatableProjectInterface.php b/core/modules/locale/src/LocaleTranslatableProjectInterface.php new file mode 100644 index 0000000..25d6a3f --- /dev/null +++ b/core/modules/locale/src/LocaleTranslatableProjectInterface.php @@ -0,0 +1,199 @@ +type = 'current'; - \Drupal::state()->set('locale.translation_status', $status); + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get('drupal'); + $project->setLangcode('de'); + $project->updateTimestamp(REQUEST_TIME); + \Drupal::service('locale.project')->set($project); // One language added, all translations up to date. $this->drupalGet('admin/reports/status'); @@ -65,9 +67,10 @@ public function testInterface() { $this->assertText(t('All translations up to date.'), 'Translations up to date'); // Set locale_test_translate module to have a local translation available. - $status = locale_translation_get_status(); - $status['locale_test_translate']['de']->type = 'local'; - \Drupal::state()->set('locale.translation_status', $status); + $project = \Drupal::service('locale.project')->get('drupal'); + $project->setLangcode('de'); + $project->updateLocalSource((object) array('timestamp' => REQUEST_TIME)); + \Drupal::service('locale.project')->set($project); // Check if updates are available for German. $this->drupalGet('admin/reports/status'); @@ -78,10 +81,11 @@ public function testInterface() { // Set locale_test_translate module to have a dev release and no // translation found. - $status = locale_translation_get_status(); - $status['locale_test_translate']['de']->version = '1.3-dev'; - $status['locale_test_translate']['de']->type = ''; - \Drupal::state()->set('locale.translation_status', $status); + $project = \Drupal::service('locale.project')->get('drupal'); + $project->setLangcode('de'); + $project->setVersion('1.3-dev'); + $project->clearTranslationStates(); + \Drupal::service('locale.project')->set($project); // Check if no updates were found. $this->drupalGet('admin/reports/status'); diff --git a/core/modules/locale/src/Tests/LocaleUpdateTest.php b/core/modules/locale/src/Tests/LocaleUpdateTest.php index f564652..db42b52 100644 --- a/core/modules/locale/src/Tests/LocaleUpdateTest.php +++ b/core/modules/locale/src/Tests/LocaleUpdateTest.php @@ -94,13 +94,24 @@ public function testUpdateCheckStatus() { // Get status of translation sources at local file system. $this->drupalGet('admin/reports/translations/check'); - $result = locale_translation_get_status(); - $this->assertEqual($result['contrib_module_one']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of contrib_module_one found'); - $this->assertEqual($result['contrib_module_one']['de']->timestamp, $this->timestampOld, 'Translation timestamp found'); - $this->assertEqual($result['contrib_module_two']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of contrib_module_two found'); - $this->assertEqual($result['contrib_module_two']['de']->timestamp, $this->timestampNew, 'Translation timestamp found'); - $this->assertEqual($result['locale_test']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of locale_test found'); - $this->assertEqual($result['custom_module_one']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of custom_module_one found'); + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get('contrib_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of contrib_module_one found'); + $this->assertEqual($project->getLatestSourceTimestamp(), $this->timestampOld, 'Translation timestamp found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_two'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of contrib_module_two found'); + $this->assertEqual($project->getLatestSourceTimestamp(), $this->timestampNew, 'Translation timestamp found'); + + $project = \Drupal::service('locale.project')->get('locale_test'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of locale_test found'); + + $project = \Drupal::service('locale.project')->get('custom_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of custom_module_one found'); // Set the test conditions. $edit = array( @@ -110,15 +121,29 @@ public function testUpdateCheckStatus() { // Get status of translation sources at both local and remote locations. $this->drupalGet('admin/reports/translations/check'); - $result = locale_translation_get_status(); - $this->assertEqual($result['contrib_module_one']['de']->type, LOCALE_TRANSLATION_REMOTE, 'Translation of contrib_module_one found'); - $this->assertEqual($result['contrib_module_one']['de']->timestamp, $this->timestampNew, 'Translation timestamp found'); - $this->assertEqual($result['contrib_module_two']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of contrib_module_two found'); - $this->assertEqual($result['contrib_module_two']['de']->timestamp, $this->timestampNew, 'Translation timestamp found'); - $this->assertEqual($result['contrib_module_three']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of contrib_module_three found'); - $this->assertEqual($result['contrib_module_three']['de']->timestamp, $this->timestampOld, 'Translation timestamp found'); - $this->assertEqual($result['locale_test']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of locale_test found'); - $this->assertEqual($result['custom_module_one']['de']->type, LOCALE_TRANSLATION_LOCAL, 'Translation of custom_module_one found'); + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get('contrib_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'remote', 'Translation of contrib_module_one found'); + $this->assertEqual($project->getLatestSourceTimestamp(), $this->timestampNew, 'Translation timestamp found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_two'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of contrib_module_two found'); + $this->assertEqual($project->getLatestSourceTimestamp(), $this->timestampNew, 'Translation timestamp found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_three'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of contrib_module_three found'); + $this->assertEqual($project->getLatestSourceTimestamp(), $this->timestampOld, 'Translation timestamp found'); + + $project = \Drupal::service('locale.project')->get('locale_test'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of locale_test found'); + + $project = \Drupal::service('locale.project')->get('custom_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'local', 'Translation of custom_module_one found'); } /** @@ -156,10 +181,18 @@ public function testUpdateImportSourceRemote() { $this->drupalPostForm('admin/reports/translations', array(), t('Update translations')); // Check if the translation has been updated, using the status cache. - $status = locale_translation_get_status(); - $this->assertEqual($status['contrib_module_one']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_one found'); - $this->assertEqual($status['contrib_module_two']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_two found'); - $this->assertEqual($status['contrib_module_three']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_three found'); + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get('contrib_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_one found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_two'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_two found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_three'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_three found'); // Check the new translation status. // The static cache needs to be flushed first to get the most recent data @@ -210,10 +243,18 @@ public function testUpdateImportSourceLocal() { $this->drupalPostForm('admin/reports/translations', array(), t('Update translations')); // Check if the translation has been updated, using the status cache. - $status = locale_translation_get_status(); - $this->assertEqual($status['contrib_module_one']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_one found'); - $this->assertEqual($status['contrib_module_two']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_two found'); - $this->assertEqual($status['contrib_module_three']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_three found'); + /** @var \Drupal\locale\LocaleTranslatableProjectInterface $project */ + $project = \Drupal::service('locale.project')->get('contrib_module_one'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_one found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_two'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_two found'); + + $project = \Drupal::service('locale.project')->get('contrib_module_three'); + $project->setLangcode('de'); + $this->assertEqual($project->getLatestSourceType(), 'current', 'Translation of contrib_module_three found'); // Check the new translation status. // The static cache needs to be flushed first to get the most recent data diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.module b/core/modules/locale/tests/modules/locale_test/locale_test.module index f06a24a..416b2dd 100644 --- a/core/modules/locale/tests/modules/locale_test/locale_test.module +++ b/core/modules/locale/tests/modules/locale_test/locale_test.module @@ -20,7 +20,7 @@ function locale_test_system_info_alter(&$info, Extension $file, $type) { // To test the module detection process by locale_project_list() the // test modules should mimic a custom module. I.e. be non-hidden. if (\Drupal::state()->get('locale.test_system_info_alter')) { - if ($file->getName() == 'locale_test' || $file->getName() == 'locale_test_translate') { + if ($file->id() == 'locale_test' || $file->id() == 'locale_test_translate') { // Don't hide the module. $info['hidden'] = FALSE; } diff --git a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module index e55d4dc..0bc13e9 100644 --- a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module +++ b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module @@ -15,7 +15,7 @@ * setting the hidden status to FALSE. */ function locale_test_translate_system_info_alter(&$info, Extension $file, $type) { - if ($file->getName() == 'locale_test_translate') { + if ($file->id() == 'locale_test_translate') { // Don't hide the module. $info['hidden'] = FALSE; }