2012-10-11 21:30:02 +00:00
< ? php
/**
* @ file
* Batch process to check the availability of remote or local po files .
*/
2013-04-13 03:28:22 +00:00
use Guzzle\Http\Exception\BadResponseException ;
use Guzzle\Http\Exception\RequestException ;
2012-10-11 21:30:02 +00:00
/**
2012-12-07 18:17:37 +00:00
* Load the common translation API .
2012-10-11 21:30:02 +00:00
*/
2012-12-07 18:17:37 +00:00
// @todo Combine functions differently in files to avoid unnecessary includes.
// Follow-up issue http://drupal.org/node/1834298
2013-05-09 09:25:10 +00:00
require_once __DIR__ . '/locale.translation.inc' ;
2012-10-11 21:30:02 +00:00
/**
2013-06-27 11:25:01 +00:00
* Batch operation callback : Check status of a remote and local po file .
2012-10-11 21:30:02 +00:00
*
2013-06-27 11:25:01 +00:00
* Checks the presence and creation time po translation files in located at
* remote server location and local file system .
2012-10-11 21:30:02 +00:00
*
2013-06-27 11:25:01 +00:00
* @ 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 .
2012-10-11 21:30:02 +00:00
* @ param array $context
2013-06-27 11:25:01 +00:00
* The batch context .
2012-10-11 21:30:02 +00:00
*/
2013-06-27 11:25:01 +00:00
function locale_translation_batch_status_check ( $project , $langcode , $options = array (), & $context ) {
$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 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 ;
}
2012-12-07 18:17:37 +00:00
2013-06-27 11:25:01 +00:00
// 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 )) {
2012-12-07 18:17:37 +00:00
// Update the file object with the result data. In case of a redirect we
2013-06-27 11:25:01 +00:00
// store the resulting uri.
2013-04-13 03:28:22 +00:00
if ( isset ( $result [ 'last_modified' ])) {
$remote_file -> uri = isset ( $result [ 'location' ]) ? $result [ 'location' ] : $remote_file -> uri ;
$remote_file -> timestamp = $result [ 'last_modified' ];
2013-06-27 11:25:01 +00:00
locale_translation_status_save ( $source -> name , $source -> langcode , LOCALE_TRANSLATION_REMOTE , $remote_file );
2012-12-07 18:17:37 +00:00
}
2013-06-27 11:25:01 +00:00
// @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 ;
2012-12-07 18:17:37 +00:00
}
else {
2013-06-27 11:25:01 +00:00
$failure = TRUE ;
2012-10-11 21:30:02 +00:00
}
}
2013-06-27 11:25:01 +00:00
// 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 ;
2012-10-11 21:30:02 +00:00
}
2013-06-27 11:25:01 +00:00
if ( $failure && ! $checked ) {
$context [ 'results' ][ 'failed_files' ][] = $source -> name ;
2012-10-11 21:30:02 +00:00
}
2013-06-27 11:25:01 +00:00
$context [ 'message' ] = t ( 'Checked translation for %project.' , array ( '%project' => $source -> project ));
2012-10-11 21:30:02 +00:00
}
/**
* Batch finished callback : Set result message .
*
* @ param boolean $success
2013-12-03 15:54:20 +00:00
* TRUE if batch successfully completed .
2012-10-11 21:30:02 +00:00
* @ param array $results
* Batch results .
*/
function locale_translation_batch_status_finished ( $success , $results ) {
2012-12-07 18:17:37 +00:00
if ( $success ) {
if ( isset ( $results [ 'failed_files' ])) {
2013-09-16 03:58:06 +00:00
if ( \Drupal :: moduleHandler () -> moduleExists ( 'dblog' )) {
2012-12-07 18:17:37 +00:00
$message = format_plural ( count ( $results [ 'failed_files' ]), 'One translation file could not be checked. <a href="@url">See the log</a> for details.' , '@count translation files could not be checked. <a href="@url">See the log</a> for details.' , array ( '@url' => url ( 'admin/reports/dblog' )));
}
else {
$message = format_plural ( count ( $results [ 'failed_files' ]), 'One translation files could not be checked. See the log for details.' , '@count translation files could not be checked. See the log for details.' );
}
drupal_set_message ( $message , 'error' );
}
if ( isset ( $results [ 'files' ])) {
2012-10-11 21:30:02 +00:00
drupal_set_message ( format_plural (
2013-06-27 11:25:01 +00:00
count ( $results [ 'files' ]),
2012-10-11 21:30:02 +00:00
'Checked available interface translation updates for one project.' ,
'Checked available interface translation updates for @count projects.'
));
}
2012-12-07 18:17:37 +00:00
if ( ! isset ( $results [ 'failed_files' ]) && ! isset ( $results [ 'files' ])) {
drupal_set_message ( t ( 'Nothing to check.' ));
}
2013-09-16 03:58:06 +00:00
\Drupal :: state () -> set ( 'locale.translation_last_checked' , REQUEST_TIME );
2012-10-11 21:30:02 +00:00
}
else {
2013-06-17 13:35:07 +00:00
drupal_set_message ( t ( 'An error occurred trying to check available interface translation updates.' ), 'error' );
2012-10-11 21:30:02 +00:00
}
}
2012-12-07 18:17:37 +00:00
/**
* Batch operation : Download a remote translation file .
*
2013-06-27 11:25:01 +00:00
* Downloads a remote gettext file into the translations directory . When
* successfully the translation status is updated .
2012-12-07 18:17:37 +00:00
*
* @ param object $project
* Source object of the translatable project .
* @ param string $langcode
* Language code .
2013-06-27 11:25:01 +00:00
* @ param array $context
* The batch context .
2012-12-07 18:17:37 +00:00
*
* @ see locale_translation_batch_fetch_import ()
*/
function locale_translation_batch_fetch_download ( $project , $langcode , & $context ) {
2013-06-27 11:25:01 +00:00
$sources = locale_translation_get_status ( array ( $project ), array ( $langcode ));
if ( isset ( $sources [ $project ][ $langcode ])) {
$source = $sources [ $project ][ $langcode ];
2012-12-07 18:17:37 +00:00
if ( isset ( $source -> type ) && $source -> type == LOCALE_TRANSLATION_REMOTE ) {
2013-06-27 11:25:01 +00:00
if ( $file = locale_translation_download_source ( $source -> files [ LOCALE_TRANSLATION_REMOTE ], 'translations://' )) {
2013-06-17 13:35:07 +00:00
$context [ 'message' ] = t ( 'Downloaded translation for %project.' , array ( '%project' => $source -> project ));
2013-06-27 11:25:01 +00:00
locale_translation_status_save ( $source -> name , $source -> langcode , LOCALE_TRANSLATION_LOCAL , $file );
2012-12-07 18:17:37 +00:00
}
else {
$context [ 'results' ][ 'failed_files' ][] = $source -> files [ LOCALE_TRANSLATION_REMOTE ];
}
}
}
}
/**
* Batch process : Import translation file .
*
2013-06-27 11:25:01 +00:00
* Imports a gettext file from the translation directory . When successfully the
* translation status is updated .
2012-12-07 18:17:37 +00:00
*
* @ param object $project
* Source object of the translatable project .
* @ param string $langcode
* Language code .
* @ param array $options
* Array of import options .
2013-06-27 11:25:01 +00:00
* @ param array $context
* The batch context .
2012-12-07 18:17:37 +00:00
*
* @ see locale_translate_batch_import_files ()
* @ see locale_translation_batch_fetch_download ()
*/
function locale_translation_batch_fetch_import ( $project , $langcode , $options , & $context ) {
2013-06-27 11:25:01 +00:00
$sources = locale_translation_get_status ( array ( $project ), array ( $langcode ));
if ( isset ( $sources [ $project ][ $langcode ])) {
$source = $sources [ $project ][ $langcode ];
2012-12-07 18:17:37 +00:00
if ( isset ( $source -> type )) {
if ( $source -> type == LOCALE_TRANSLATION_REMOTE || $source -> type == LOCALE_TRANSLATION_LOCAL ) {
2013-06-27 11:25:01 +00:00
$file = $source -> files [ LOCALE_TRANSLATION_LOCAL ];
2012-12-07 18:17:37 +00:00
module_load_include ( 'bulk.inc' , 'locale' );
$options += array (
2013-06-17 13:35:07 +00:00
'message' => t ( 'Importing translation for %project.' , array ( '%project' => $source -> project )),
2012-12-07 18:17:37 +00:00
);
// Import the translation file. For large files the batch operations is
2013-06-27 11:25:01 +00:00
// progressive and will be called repeatedly until finished.
2012-12-07 18:17:37 +00:00
locale_translate_batch_import ( $file , $options , $context );
// The import is finished.
if ( isset ( $context [ 'finished' ]) && $context [ 'finished' ] == 1 ) {
2013-12-03 15:54:20 +00:00
// The import is successful.
2012-12-07 18:17:37 +00:00
if ( isset ( $context [ 'results' ][ 'files' ][ $file -> uri ])) {
2013-06-17 13:35:07 +00:00
$context [ 'message' ] = t ( 'Imported translation for %project.' , array ( '%project' => $source -> project ));
2012-12-07 18:17:37 +00:00
2013-06-27 11:25:01 +00:00
// 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 ]);
2012-12-07 18:17:37 +00:00
}
}
}
}
}
}
/**
* Batch finished callback : Set result message .
*
* @ param boolean $success
2013-12-03 15:54:20 +00:00
* TRUE if batch successfully completed .
2012-12-07 18:17:37 +00:00
* @ param array
* Batch results .
*/
function locale_translation_batch_fetch_finished ( $success , $results ) {
module_load_include ( 'bulk.inc' , 'locale' );
2013-06-27 11:25:01 +00:00
if ( $success ) {
2013-09-16 03:58:06 +00:00
\Drupal :: state () -> set ( 'locale.translation_last_checked' , REQUEST_TIME );
2013-06-27 11:25:01 +00:00
}
2012-12-07 18:17:37 +00:00
return locale_translate_batch_finished ( $success , $results );
}
2012-10-11 21:30:02 +00:00
/**
* Check if remote file exists and when it was last updated .
*
2012-12-07 18:17:37 +00:00
* @ param string $uri
* URI of remote file .
2013-04-13 03:28:22 +00:00
*
* @ return array | boolean
* Associative array of file data with the following elements :
* - last_modified : Last modified timestamp of the translation file .
* - ( optional ) location : The location of the translation file . Is only set
* when a redirect ( 301 ) has occurred .
* TRUE if the file is not found . FALSE if a fault occurred .
2012-12-07 18:17:37 +00:00
*/
2013-04-13 03:28:22 +00:00
function locale_translation_http_check ( $uri ) {
try {
2013-09-16 03:58:06 +00:00
$response = \Drupal :: httpClient ()
2013-04-13 03:28:22 +00:00
-> head ( $uri )
-> send ();
$result = array ();
2013-08-10 07:53:20 +00:00
// Return the effective URL if it differs from the requested.
if ( $response -> getEffectiveUrl () != $uri ) {
$result [ 'location' ] = $response -> getEffectiveUrl ();
2012-12-07 18:17:37 +00:00
}
2013-04-13 03:28:22 +00:00
$result [ 'last_modified' ] = $response -> getLastModified () ? strtotime ( $response -> getLastModified ()) : 0 ;
2012-12-07 18:17:37 +00:00
return $result ;
}
2013-04-13 03:28:22 +00:00
catch ( BadResponseException $e ) {
// Handle 4xx and 5xx http responses.
$response = $e -> getResponse ();
if ( $response -> getStatusCode () == 404 ) {
// File not found occurs when a translation file is not yet available
// at the translation server. But also if a custom module or custom
// theme does not define the location of a translation file. By default
// the file is checked at the translation server, but it will not be
// found there.
watchdog ( 'locale' , 'Translation file not found: @uri.' , array ( '@uri' => $uri ));
return TRUE ;
2012-12-07 18:17:37 +00:00
}
2013-04-13 03:28:22 +00:00
watchdog ( 'locale' , 'HTTP request to @url failed with error: @error.' , array ( '@url' => $uri , '@error' => $response -> getStatusCode () . ' ' . $response -> getReasonPhrase ()));
}
catch ( RequestException $e ) {
// Handle connection problems and cURL specific errors (CurlException) and
// other http related errors.
watchdog ( 'locale' , 'HTTP request to @url failed with error: @error.' , array ( '@url' => $uri , '@error' => $e -> getMessage ()));
2012-12-07 18:17:37 +00:00
}
return FALSE ;
}
/**
2013-06-27 11:25:01 +00:00
* Downloads a translation file from a remote server .
2012-12-07 18:17:37 +00:00
*
* @ param object $source_file
* Source file object with at least :
* - " uri " : uri to download the file from .
* - " project " : Project name .
* - " langcode " : Translation language .
* - " version " : Project version .
* - " filename " : File name .
2013-06-27 11:25:01 +00:00
* @ param string $directory
* Directory where the downloaded file will be saved . Defaults to the
* temporary file path .
2012-12-07 18:17:37 +00:00
*
* @ return object
* File object if download was successful . FALSE on failure .
2012-10-11 21:30:02 +00:00
*/
2013-06-27 11:25:01 +00:00
function locale_translation_download_source ( $source_file , $directory = 'temporary://' ) {
if ( $uri = system_retrieve_file ( $source_file -> uri , $directory )) {
$file = clone ( $source_file );
$file -> type = LOCALE_TRANSLATION_LOCAL ;
2012-12-07 18:17:37 +00:00
$file -> uri = $uri ;
2013-06-27 11:25:01 +00:00
$file -> directory = $directory ;
$file -> timestamp = filemtime ( $uri );
2012-12-07 18:17:37 +00:00
return $file ;
2012-10-11 21:30:02 +00:00
}
2013-06-27 11:25:01 +00:00
watchdog ( 'locale' , 'Unable to download translation file @uri.' , array ( '@uri' => $source_file -> uri ), WATCHDOG_ERROR );
2012-12-07 18:17:37 +00:00
return FALSE ;
2012-10-11 21:30:02 +00:00
}