commit 010072e8f7399fe4abcdeb76750eb85eeffd649b Author: Erik Stielstra Date: Sat Jun 1 22:34:06 2013 +0200 #22 diff --git a/core/modules/locale/locale.batch.inc b/core/modules/locale/locale.batch.inc index 4c17bec..e177437 100644 --- a/core/modules/locale/locale.batch.inc +++ b/core/modules/locale/locale.batch.inc @@ -16,82 +16,70 @@ require_once __DIR__ . '/locale.translation.inc'; /** - * Batch operation callback: Check the availability of a remote po file. + * Batch operation callback: Check status of a remote and local po file. * - * Checks the presence and creation time of one po file per batch process. The - * file URL and timestamp are stored. + * Checks the presence and creation time po translation files in located at + * remote server location and local file system. * - * @param array $source - * A translation source object of the project for which to check the state of - * a remote po file. + * @param string $project + * 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. + * @param array $options + * Optional, an array with options that can have the following elements: + * - 'finish_feedback': Whether or not to give feedback to the user when the + * batch is finished. Optional, defaults to TRUE. + * - 'use_remote': Whether or not to check the remote translation file. + * Optional, defaults to TRUE. * @param array $context - * The batch context array. The collected state is stored in the 'results' - * parameter of the context. - * - * @see locale_translation_batch_status_fetch_local() + * The batch context. */ -function locale_translation_batch_status_fetch_remote($project, $langcode, &$context) { +function locale_translation_batch_status_check($project, $langcode, $options = array(), &$context) { $t = get_t(); + $failure = $checked = FALSE; + $options += array( + 'finish_feedback' => TRUE, + 'use_remote' => TRUE, + ); $source = locale_translation_get_status(array($project), array($langcode)); $source = $source[$project][$langcode]; - // Check the translation file at the remote server and update the source - // data with the remote status. - if (isset($source->files[LOCALE_TRANSLATION_REMOTE])) { - $remote_file = $source->files[LOCALE_TRANSLATION_REMOTE]; - $result = locale_translation_http_check($remote_file->uri); + // Check the status of local translation files. + if (isset($source->files[LOCALE_TRANSLATION_LOCAL])) { + if ($file = locale_translation_source_check_file($source)) { + locale_translation_status_save($source->name, $source->langcode, LOCALE_TRANSLATION_LOCAL, $file); + } + $checked = TRUE; + } - if ($result) { + // Check the status of remote translation files. + if ($options['use_remote'] && isset($source->files[LOCALE_TRANSLATION_REMOTE])) { + $remote_file = $source->files[LOCALE_TRANSLATION_REMOTE]; + 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 a file is not found we don't update the - // file object, and store it unchanged. + // 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']; locale_translation_status_save($source->name, $source->langcode, LOCALE_TRANSLATION_REMOTE, $remote_file); } - // @todo What to do with 404s ($result == TRUE)? Do we need to record the action to prevent re-checking within the TTL (1day, 1week)? - // Record success. - $context['results']['files'][$source->name] = $source->name; + // @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 { - // An error occured when checking the file. Record the failure for - // reporting at the end of the batch. - $context['results']['failed_files'][] = $source->name; + $failure = TRUE; } - $context['message'] = $t('Checked translation for %project.', array('%project' => $source->project)); } -} - -/** - * Batch operation callback: Check the availability of local po files. - * - * Checks the presence and creation time of po files in the local file system. - * The file path and the timestamp are stored. - * - * @param array $source - * A translation source object of the project for which to check the state of - * a remote po file. - * @param array $context - * The batch context array. The collected state is stored in the 'results' - * parameter of the context. - * - * @see locale_translation_batch_status_fetch_remote() - */ -function locale_translation_batch_status_fetch_local($project, $langcode, &$context) { - $t = get_t(); - $source = locale_translation_get_status(array($project), array($langcode)); - $source = $source[$project][$langcode]; - - // Get the status of local translation files and store the result data in the - // batch results for later processing. - if (isset($source->files[LOCALE_TRANSLATION_LOCAL])) { - if ($file = locale_translation_source_check_file($source)) { - locale_translation_status_save($source->name, $source->langcode, LOCALE_TRANSLATION_LOCAL, $file); - // Record success and store the updated source data. - $context['results']['files'][$source->name] = $source->name; - } + // Provide user feedback and record success or failure for reporting at the + // end of the batch. + if ($options['finish_feedback'] && $checked) { + $context['results']['files'][] = $source->name; + } + if ($failure && !$checked) { + $context['results']['failed_files'][] = $source->name; } $context['message'] = $t('Checked translation for %project.', array('%project' => $source->project)); } @@ -134,42 +122,18 @@ function locale_translation_batch_status_finished($success, $results) { } /** - * Loads translation source data for the projects to be updated. - * - * Source data is loaded from cache and stored in the context results array. - * Source data contains the translations status per project / per language - * and whether translation updates are available and where the updates can be - * retrieved from. The data is stored in the $context['results'] parameter - * so that other batch operations can take this data as input for their - * operation. - * - * @see locale_translation_batch_fetch_download() - * @see locale_translation_batch_fetch_import() - */ -function locale_translation_batch_fetch_sources($projects, $langcodes, &$context) { - // If this batch operation is preceded by the status check operations, the - // results of those operation are stored in the context. We remove them here - // to keep the result records clean. - unset($context['results']['files']); - unset($context['results']['failed_files']); -} - -/** * Batch operation: Download a remote translation file. * - * This operation downloads a remote gettext file and saves it in the temporary - * directory. The remote file URL is taken from the input data in - * $context['results']['input']. The result of the operation is stored in - * $context['results']['sources'] and contains the URL of the temporary file. + * 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 $langcode * Language code. - * @param $context - * Batch context array. + * @param array $context + * The batch context. * - * @see locale_translation_batch_fetch_sources() * @see locale_translation_batch_fetch_import() */ function locale_translation_batch_fetch_download($project, $langcode, &$context) { @@ -192,12 +156,8 @@ function locale_translation_batch_fetch_download($project, $langcode, &$context) /** * Batch process: Import translation file. * - * This batch operation imports either a local gettext file or a downloaded - * remote gettext file. In case of a downloaded file the location of the - * temporary file is found in the $context['results']['sources']. The temporary - * file will be deleted after importing or will be moved to the local - * translations directory. In case of a local file the file will just be - * imported. + * Imports a gettext file from the translation directory. When successfully the + * translation status is updated. * * @param object $project * Source object of the translatable project. @@ -205,11 +165,10 @@ function locale_translation_batch_fetch_download($project, $langcode, &$context) * Language code. * @param array $options * Array of import options. - * @param $context - * Batch context array. + * @param array $context + * The batch context. * * @see locale_translate_batch_import_files() - * @see locale_translation_batch_fetch_sources() * @see locale_translation_batch_fetch_download() */ function locale_translation_batch_fetch_import($project, $langcode, $options, &$context) { @@ -225,7 +184,7 @@ function locale_translation_batch_fetch_import($project, $langcode, $options, &$ 'message' => $t('Importing translation for %project.', array('%project' => $source->project)), ); // Import the translation file. For large files the batch operations is - // progressive and will be called repeatedly untill finished. + // progressive and will be called repeatedly until finished. locale_translate_batch_import($file, $options, $context); // The import is finished. @@ -314,9 +273,7 @@ function locale_translation_http_check($uri) { } /** - * Downloads source file from a remote server. - * - * The downloaded file is stored in the temporary files directory. + * Downloads a translation file from a remote server. * * @param object $source_file * Source file object with at least: diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc index 380078d..e30ba88 100644 --- a/core/modules/locale/locale.compare.inc +++ b/core/modules/locale/locale.compare.inc @@ -80,7 +80,6 @@ function locale_translation_build_projects() { } } } - // @todo Remove this elseif. See http://drupal.org/node/1883154 // If project is not a dev version, but is core, pick latest release. elseif ($name == "drupal") { // Pick latest available release. @@ -250,7 +249,6 @@ function locale_translation_check_projects($projects = array(), $langcodes = arr * @param string $langcodes * Array of language codes. Defaults to all translatable languages. */ -// @todo Return batch, don't set it here. function locale_translation_check_projects_batch($projects = array(), $langcodes = array()) { // Build and set the batch process. $batch = locale_translation_batch_status_build($projects, $langcodes); @@ -260,7 +258,7 @@ function locale_translation_check_projects_batch($projects = array(), $langcodes /** * Builds a batch to get the status of remote and local translation files. * - * The batch process fetches the state of both remote and (if configured) local + * The batch process fetches the state of both local and (if configured) remote * translation files. The data of the most recent translation is stored per * per project and per language. This data is stored in a state variable * 'locale.translation_status'. The timestamp it was last updated is stored @@ -279,8 +277,9 @@ function locale_translation_batch_status_build($projects = array(), $langcodes = $t = get_t(); $projects = $projects ? $projects : array_keys(locale_translation_get_projects()); $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); + $options = _locale_translation_default_update_options(); - $operations = _locale_translation_batch_status_operations($projects, $langcodes); + $operations = _locale_translation_batch_status_operations($projects, $langcodes, $options); $batch = array( 'operations' => $operations, @@ -297,27 +296,23 @@ function locale_translation_batch_status_build($projects = array(), $langcodes = * Helper function to construct batch operations checking remote translation * status. * - * @param array projects + * @param array $projects * Array of project names to be processed. - * @param array langcodes + * @param array $langcodes * Array of language codes. + * @param array $options + * Batch processing options. * * @return array * Array of batch operations. */ -function _locale_translation_batch_status_operations($projects, $langcodes) { +function _locale_translation_batch_status_operations($projects, $langcodes, $options = array()) { $operations = array(); - $use_remote = locale_translation_use_remote_source(); foreach ($projects as $project) { foreach ($langcodes as $langcode) { - // Check for local sources and save the result. - $operations[] = array('locale_translation_batch_status_fetch_local', array($project, $langcode)); - - // Set the batch processes for remote sources. - if ($use_remote) { - $operations[] = array('locale_translation_batch_status_fetch_remote', array($project, $langcode)); - } + // Check status of local and remote translation sources. + $operations[] = array('locale_translation_batch_status_check', array($project, $langcode, $options)); } } @@ -328,8 +323,7 @@ function _locale_translation_batch_status_operations($projects, $langcodes) { * Check and store the status and timestamp of local po files. * * Only po files in the local file system are checked. Any remote translation - * sources will be ignored. Results are stored in the state variable - * 'locale.translation_status'. + * files will be ignored. * * Projects may contain a server_pattern option containing a pattern of the * path to the po source files. If no server_pattern is defined the default @@ -347,8 +341,6 @@ function _locale_translation_batch_status_operations($projects, $langcodes) { function locale_translation_check_projects_local($projects = array(), $langcodes = array()) { $projects = locale_translation_get_projects($projects); $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); - $history = locale_translation_get_file_history(); - $results = array(); // 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 diff --git a/core/modules/locale/locale.fetch.inc b/core/modules/locale/locale.fetch.inc index 62a488f..f6d3496 100644 --- a/core/modules/locale/locale.fetch.inc +++ b/core/modules/locale/locale.fetch.inc @@ -31,8 +31,12 @@ function locale_translation_batch_update_build($projects = array(), $langcodes = $t = get_t(); $projects = $projects ? $projects : array_keys(locale_translation_get_projects()); $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); + $status_options = $options; + $status_options['finish_feedback'] = FALSE; - $operations = _locale_translation_batch_status_operations($projects, $langcodes); + // Check status of local and remote translation files. + $operations = _locale_translation_batch_status_operations($projects, $langcodes, $status_options); + // Download and import translations. $operations = array_merge($operations, _locale_translation_fetch_operations($projects, $langcodes, $options)); $batch = array( @@ -92,10 +96,7 @@ function locale_translation_batch_fetch_build($projects = array(), $langcodes = */ function _locale_translation_fetch_operations($projects, $langcodes, $options) { $operations = array(); - $config = config('locale.settings'); - //@todo Rework this batch operation to only reset the result counter. - $operations[] = array('locale_translation_batch_fetch_sources', array($projects, $langcodes)); foreach ($projects as $project) { foreach ($langcodes as $langcode) { if (locale_translation_use_remote_source()) { diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 4022809..67abbeb 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -528,23 +528,33 @@ function locale_queue_info() { } /** - * @todo Function title + * Callback: Executes interface translation queue tasks. * - * Performs check, download and import of project translations. - * May be called multiple times if the import is not completed. + * The translation update functions executed here are batch operations which + * are also used in translation update batches. The batch functions may need to + * be executed multiple times to complete their task, typically this is the + * translation import function. When a batch function is not finished, a new + * queue task is created and added to the end of the queue. The batch context + * data is needed to continue the batch task is stored in the queue with the + * queue data. + * + * @param array $data + * Queue data array containing: + * - Function name. + * - Array of function arguments. Optionally contains the batch context data. + * + * @see locale_queue_info() */ function locale_translation_worker($data) { module_load_include('batch.inc', 'locale'); - list($function, $args) = $data; - // We execute batch operation functions here to import the translation files. - // All batch functions use a context variable as last argument, the context - // is passed by reference. When a batch operation is called for the first time - // a default batch context is set. When called iterative (usually the batch - // import function) the batch context is passed through via the queue and is - // part of the $data. The $batch_context is be passed by reference to the - // batch operation function. + // We execute batch operation functions here to check, download and import the + // translation files. Batch functions use a context variable as last argument + // which is passed by reference. When a batch operation is called for the + // first time a default batch context is created. When called iterative + // (usually the batch import function) the batch context is passed through via + // the queue and is part of the $data. $last = count($args) - 1; if (!is_array($args[$last]) || !isset($args[$last]['finished'])) { $batch_context = array( @@ -563,21 +573,13 @@ function locale_translation_worker($data) { // Call the batch operation function. call_user_func_array($function, $args); - // If the batch operation is not yet finished we create a new queue task - // to continue the works. This probably is the translation import task. + // If the batch operation is not finished we create a new queue task to + // continue the task. This is typically the translation import task. if ($batch_context['finished'] < 1) { - $batch_context['strings'] = array(); + unset($batch_context['strings']); $queue = Drupal::queue('locale_translation', TRUE); $queue->createItem(array($function, $args)); } - else { - if ($function == 'locale_translation_batch_fetch_import') { - // Remove record from queue registry. - $in_queue = state()->get('locale_translation_in_queue', array()); - unset($in_queue[$args[0] . ':' . $args[1]]); - state()->set('locale_translation_in_queue', $in_queue); - } - } } /** @@ -977,7 +979,7 @@ function locale_translation_get_file_history() { // Get file history from the database. $result = db_query('SELECT project, langcode, filename, version, uri, timestamp, last_checked FROM {locale_file}'); foreach ($result as $file) { - $file->type = LOCALE_TRANSLATION_CURRENT; + $file->type = $file->timestamp ? LOCALE_TRANSLATION_CURRENT : ''; $history[$file->project][$file->langcode] = $file; } } @@ -1076,50 +1078,47 @@ function locale_translation_status_save($project, $langcode, $type, $data) { // Followup issue: http://drupal.org/node/1842362 // Split status storage per module/language and expire individually. This will // improve performance for large sites. + + // Load the translation status or build it if not already available. module_load_include('translation.inc', 'locale'); $status = locale_translation_get_status(); - $status = empty($status) ? array() : $status; - - // @todo Can this be done better? Use ..._build_sources instead? - if (!isset($status[$project])) { + if (empty($status)) { $projects = locale_translation_get_projects(array($project)); if (isset($projects[$project])) { $status[$project][$langcode] = locale_translation_source_build($projects[$project], $langcode); } } - elseif (!isset($status[$project][$langcode])) { - $projects = locale_translation_get_projects(array($project)); - $status[$project][$langcode] = locale_translation_source_build($projects[$project], $langcode); - } - // Merge the new data into the existing structured status array. - switch ($type) { - case LOCALE_TRANSLATION_REMOTE: - case LOCALE_TRANSLATION_LOCAL: - // Add the source data to the status array. - $status[$project][$langcode]->files[$type] = $data; - - // Check if this translation is the most recent one. Set timestamp and - // data type of the most recent translation source. - if (isset($data->timestamp) && $data->timestamp) { - if ($data->timestamp > $status[$project][$langcode]->timestamp) { - $status[$project][$langcode]->timestamp = $data->timestamp; - $status[$project][$langcode]->last_checked = REQUEST_TIME; - $status[$project][$langcode]->type = $type; + // Merge the new status data with the existing status. + if (isset($status[$project][$langcode])) { + switch ($type) { + case LOCALE_TRANSLATION_REMOTE: + case LOCALE_TRANSLATION_LOCAL: + // Add the source data to the status array. + $status[$project][$langcode]->files[$type] = $data; + + // Check if this translation is the most recent one. Set timestamp and + // data type of the most recent translation source. + if (isset($data->timestamp) && $data->timestamp) { + if ($data->timestamp > $status[$project][$langcode]->timestamp) { + $status[$project][$langcode]->timestamp = $data->timestamp; + $status[$project][$langcode]->last_checked = REQUEST_TIME; + $status[$project][$langcode]->type = $type; + } } - } - break; - case LOCALE_TRANSLATION_CURRENT: - $data->last_checked = REQUEST_TIME; - $status[$project][$langcode]->timestamp = $data->timestamp; - $status[$project][$langcode]->last_checked = $data->last_checked; - $status[$project][$langcode]->type = $type; - locale_translation_update_file_history($data); - break; - } + break; + case LOCALE_TRANSLATION_CURRENT: + $data->last_checked = REQUEST_TIME; + $status[$project][$langcode]->timestamp = $data->timestamp; + $status[$project][$langcode]->last_checked = $data->last_checked; + $status[$project][$langcode]->type = $type; + locale_translation_update_file_history($data); + break; + } - state()->set('locale.translation_status', $status); - state()->set('locale.translation_last_checked', REQUEST_TIME); + state()->set('locale.translation_status', $status); + state()->set('locale.translation_last_checked', REQUEST_TIME); + } } /** diff --git a/core/modules/locale/locale.queue.inc b/core/modules/locale/locale.queue.inc deleted file mode 100644 index 4fb0093..0000000 --- a/core/modules/locale/locale.queue.inc +++ /dev/null @@ -1,178 +0,0 @@ -get('translation.update_interval_days')) { - locale_cron_fill_queue(); - locale_cron_process_queue(); - } -} - -/** - * Populate a queue with project to check for translation updates. - */ -function locale_cron_fill_queue() { - $languages = locale_translatable_language_list(); - - // If no languages are enabled, there is nothing to do here. - if (empty($languages)) { - return; - } - - // Select active projects x languages ordered by last checked time - $last = REQUEST_TIME - config('locale.settings')->get('translation.update_interval_days') * 3600 * 24; - // @todo For testing only. vv - $last = REQUEST_TIME; - $query = db_select('locale_project', 'p'); - $query->join('locale_file', 'f', 'p.name = f.project'); - $query->condition('p.status', 1); - $query->condition('f.last_checked', $last, '<'); - $query->condition('f.langcode', array_keys($languages)); - $query->condition('f.queued', 0); - $query->fields('f', array('project', 'langcode')); - $query->orderBy('last_checked'); - if ($updates = $query->execute()->fetchAll()) { - // @todo $updates will only contain existing translations. Project/language without translations needs to be added. - // @todo Instead: Query for all up to date translations and exclude these from a full list based on all projects and all languages. - // Add update tasks to the queue. - // @todo Consider using _locale_translation_fetch_operations() as source of queue items. - $queue = Drupal::queue('locale_translation', TRUE); - foreach ($updates as $update) { - $queue->createItem(array( - 'callback' => 'locale_translation_batch_status_fetch_local', - 'arguments' => array( - 'project' => $update->project, - 'langcode' => $update->langcode, - ), - 'return_value' => FALSE, - )); - $queue->createItem(array( - 'callback' => 'locale_translation_batch_status_fetch_remote', - 'arguments' => array( - 'project' => $update->project, - 'langcode' => $update->langcode, - ), - 'return_value' => FALSE, - )); - $queue->createItem(array( - 'callback' => 'locale_translation_batch_fetch_download', - 'arguments' => array( - 'project' => $update->project, - 'langcode' => $update->langcode, - ), - 'return_value' => FALSE, - )); - $queue->createItem(array( - 'callback' => 'locale_translation_queue_fetch_import', - 'arguments' => array( - 'project' => $update->project, - 'langcode' => $update->langcode, - ), - 'return_value' => TRUE, - )); - } - - // Mark all projects as being added to the queue to prevent them being added - // multiple times. - // @todo Flagging in locale_file does not work for project/language without translation file. - $query = db_update('locale_file'); - $query->fields(array('queued' => REQUEST_TIME)); - $or = db_or(); - foreach($updates as $update) { - $and = db_and(); - $and->condition('project', $update->project); - $and->condition('langcode', $update->langcode); - $or->condition($and); - } - $query->condition($or); - $query->execute(); - } -} - -/** - * Processes project translation items in the queue. - * - * Checks for project translation update. Download and imports if update is - * available. - */ -function locale_cron_process_queue() { - $end = time() + 15; - $queue = Drupal::queue('locale_translation', TRUE); - while (time() < $end && ($item = $queue->claimItem(300))) { - if (locale_translation_update_queue_worker($item->data)) { - $queue->deleteItem($item); - - // Unset queued flag. - $query = db_update('locale_file'); - $query->fields(array('queued' => 0)); - $query->condition('project', $item->data['arguments']['project']); - $query->condition('langcode', $item->data['arguments']['langcode']); - $query->execute(); - } - else { - $queue->releaseItem($item); - } - } -} - -/** -function locale_cron_unset_queue($item) { - -} - -/** - * Performs check, download and import of project translations. - * May be called multiple times if the import is not completed. - */ -function locale_translation_update_queue_worker($data) { - $function = $data['callback']; - - module_load_include('batch.inc', 'locale'); - if (function_exists($function)) { - $context = array(); - if (!$data['return_value']) { - $function($data['arguments']['project'], $data['arguments']['langcode'], $context); - return TRUE; - } - return $function($data['arguments']['project'], $data['arguments']['langcode']); - } -} - -/** - * Import a local translation file. - * - * @param $project - * @param $langcode - */ -// @todo Consider using the batch function locale_translation_batch_fetch_import() instead. -// @todo If this function is not required, function locale_translate_file_import() can be droped and the change in http://drupal.org/node/1998056 #11 be reverted. -function locale_translation_queue_fetch_import($project, $langcode) { - $sources = locale_translation_get_status(array($project), array($langcode)); - if (isset($sources[$project][$langcode])) { - $source = $sources[$project][$langcode]; - if (isset($source->type) && ($source->type == LOCALE_TRANSLATION_REMOTE || $source->type == LOCALE_TRANSLATION_LOCAL)) { - module_load_include('translation.inc', 'locale'); - $options = _locale_translation_default_update_options(); - $file = $source->files[LOCALE_TRANSLATION_LOCAL]; - module_load_include('bulk.inc', 'locale'); - // Import the translation file. For large files the batch operations is - // progressive and will be called repeatedly until finished. - if ($result = locale_translate_file_import($file, $options)) { - if ($result['finished'] == 1) { - // Save the data of imported source into the {locale_file} table and - // update the current translation status. - locale_translation_status_save($project, $langcode, LOCALE_TRANSLATION_CURRENT, $source->files[LOCALE_TRANSLATION_LOCAL]); - return TRUE; - } - // Import not completed. - return FALSE; - } - // An import error occurred. Return TRUE to terminate the queue job. - } - } - // Nothing to do. Return TRUE to terminate the queue job. - return TRUE; -} diff --git a/core/modules/locale/locale.translation.inc b/core/modules/locale/locale.translation.inc index 2e8b930..6dc1829 100644 --- a/core/modules/locale/locale.translation.inc +++ b/core/modules/locale/locale.translation.inc @@ -128,8 +128,6 @@ function locale_translation_load_sources($projects = NULL, $langcodes = NULL) { * * @see locale_translation_source_build() */ -// @todo What is the most efficient and flexible way to organize the source data? [$project][$langcode] or ["$project:$langcode"] or other? -// @todo Change the name of this function? Change the parameters too (it is currently only called for single project/langcode)?. function locale_translation_build_sources($projects = array(), $langcodes = array()) { $sources = array(); $projects = locale_translation_get_projects($projects); @@ -174,14 +172,6 @@ function locale_translation_source_check_file($source) { $directory = $source_file->directory; $filename = '/' . preg_quote($source_file->filename) . '$/'; - // If the directory contains a stream wrapper, it is converted to a real - // path. This is required for file_scan_directory() which can not handle - // stream wrappers. - // @todo file_scan_directory() has changed does it handle stream wrappers now? - if ($scheme = file_uri_scheme($directory)) { - $directory = str_replace($scheme . '://', drupal_realpath($scheme . '://'), $directory); - } - if ($files = file_scan_directory($directory, $filename, array('key' => 'name', 'recurse' => FALSE))) { $file = current($files); $source_file->uri = $file->uri; @@ -285,16 +275,19 @@ function locale_translation_source_build($project, $langcode, $filename = NULL) } $source->files = $files; - // If this project/language combination is already translated, we add its - // translation status and update the current translation timestamp and - // last_updated time. + // If this project+language is already translated, we add its status and + // update the current translation timestamp and last_updated time. If the + // project+language is not translated before, create a new record. $history = locale_translation_get_file_history(); - if (isset($history[$project->name][$langcode])) { + if (isset($history[$project->name][$langcode]) && $history[$project->name][$langcode]->timestamp) { $source->files[LOCALE_TRANSLATION_CURRENT] = $history[$project->name][$langcode]; $source->type = LOCALE_TRANSLATION_CURRENT; $source->timestamp = $history[$project->name][$langcode]->timestamp; $source->last_checked = $history[$project->name][$langcode]->last_checked; } + else { + locale_translation_update_file_history($source); + } return $source; } @@ -328,37 +321,32 @@ function locale_translation_build_server_pattern($project, $template) { * Populate a queue with project to check for translation updates. */ function locale_cron_fill_queue() { - // @todo Disabled modules should not be added to the queue. - - $up_to_date = $updates = array(); - // @todo Do we have an expiring state()? - // @todo Consider individual state variables as flag. - $in_queue = state()->get('locale_translation_in_queue', array()); - $projects = array_keys(locale_translation_get_projects()); - $langcodes = array_keys(locale_translatable_language_list()); + $updates = array(); + $config = config('locale.settings'); // Determine which project+language should be updated. - // We start with all possible combinations of projects and languages and - // remove those project/language combinations that are either up to date or - // are already in the queue. - $last = REQUEST_TIME - config('locale.settings')->get('translation.update_interval_days') * 3600 * 24; - $query = db_select('locale_project', 'p'); - $query->join('locale_file', 'f', 'p.name = f.project'); + $last = REQUEST_TIME - $config->get('translation.update_interval_days') * 3600 * 24; + $query = db_select('locale_file', 'f'); + $query->join('locale_project', 'p', 'p.name = f.project'); $query->condition('f.last_checked', $last, '>='); $query->fields('f', array('project', 'langcode')); + if (!$config->get('translation.check_disabled_modules')) { + $query->condition('p.status', 1); + } $files = $query->execute()->fetchAll(); foreach ($files as $file) { - $up_to_date[$file->project . ':' . $file->langcode] = TRUE; - } - foreach ($projects as $project) { - foreach ($langcodes as $langcode) { - if (!isset($up_to_date[$project . ':' . $langcode]) && !isset($in_queue[$project . ':' . $langcode])) { - $updates[$project][$langcode] = array('project' => $project, 'langcode' => $langcode); - } - } + $updates[$file->project][] = $file->langcode; + + // Update the last_checked timestamp of the project+language that will + // be checked for updates. + db_update('locale_file') + ->fields(array('last_checked' => REQUEST_TIME)) + ->condition('project', $file->project) + ->condition('langcode', $file->langcode) + ->execute(); } - // For each project/language combination a number of tasks are added to + // For each project+language combination a number of tasks are added to // the queue. if ($updates) { module_load_include('fetch.inc', 'locale'); @@ -366,19 +354,14 @@ function locale_cron_fill_queue() { $queue = Drupal::queue('locale_translation', TRUE); foreach ($updates as $project => $languages) { - $batch = locale_translation_batch_update_build(array($project), array_keys($languages), $options); + $batch = locale_translation_batch_update_build(array($project), $languages, $options); foreach ($batch['operations'] as $item) { $queue->createItem($item); } - $in_queue[$project . ':' . $langcode] = TRUE; } - - // Update the list of queued translations. - state()->set('locale_translation_in_queue', $in_queue); } } - /** * Determine if a file is a remote file. * @@ -449,5 +432,7 @@ function _locale_translation_default_update_options() { 'not_customized' => $config->get('translation.overwrite_not_customized'), 'customized' => $config->get('translation.overwrite_customized'), ), + 'finish_feedback' => TRUE, + 'use_remote' => locale_translation_use_remote_source(), ); }