Projet

Général

Profil

Paste
Télécharger (18,2 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / l10n_update / l10n_update.admin.inc @ 64ad485a

1
<?php
2

    
3
/**
4
 * @file
5
 *   Admin settings and update page.
6
 */
7

    
8
/**
9
 * Project has a new release available.
10
 */
11
define('L10N_UPDATE_NOT_CURRENT', 4);
12

    
13
/**
14
 * Project is up to date.
15
 */
16
define('L10N_UPDATE_CURRENT', 5);
17

    
18
/**
19
 * Project's status cannot be checked.
20
 */
21
define('L10N_UPDATE_NOT_CHECKED', -1);
22

    
23
/**
24
 * No available update data was found for project.
25
 */
26
define('L10N_UPDATE_UNKNOWN', -2);
27

    
28
/**
29
 * There was a failure fetching available update data for this project.
30
 */
31
define('L10N_UPDATE_NOT_FETCHED', -3);
32

    
33
// Include l10n_update API
34
module_load_include('check.inc', 'l10n_update');
35
// And project api
36
module_load_include('project.inc', 'l10n_update');
37

    
38
/**
39
 * Page callback: Admin overview page.
40
 */
41
function l10n_update_admin_overview() {
42
  // For now we get package information provided by modules.
43
  $projects = l10n_update_get_projects();
44
  $languages = l10n_update_language_list('name');
45

    
46
  $build = array();
47
  if ($languages) {
48
    $history = l10n_update_get_history();
49
    $available = l10n_update_available_releases();
50
    $updates = l10n_update_build_updates($history, $available);
51
    $build['project_status'] = array(
52
      '#theme' => 'l10n_update_project_status',
53
      '#projects' => $projects,
54
      '#languages' => $languages,
55
      '#history' => $history,
56
      '#available' => $available,
57
      '#updates' => $updates,
58
    );
59
    $build['admin_import_form'] = drupal_get_form('l10n_update_admin_import_form', $projects, $updates);
60
  }
61
  else {
62
    $build['no_projects'] = array('#markup' => t('No projects or languages to update.'));
63
  }
64
  return $build;
65
}
66

    
67
/**
68
 * Translation update form.
69
 *
70
 * @todo selectable packages
71
 * @todo check language support in server
72
 * @todo check file update dates
73
 *
74
 * @param $form_state
75
 *   Form states array.
76
 * @param $projects
77
 *   @todo $projects are not used in the form.
78
 * @param $updates
79
 *   Updates to be displayed in the form.
80
 */
81
function l10n_update_admin_import_form($form, $form_state, $projects, $updates) {
82
  //module_load_include('inc', 'l10n_update');
83
  // For now we get package information provided by modules
84
  $projects = l10n_update_get_projects();
85
  $languages = l10n_update_language_list('name');
86

    
87
  // Absence of projects is an error and only occurs if the database table
88
  // was truncated. In this case we rebuild the project data.
89
  if (!$projects) {
90
    l10n_update_build_projects();
91
    $projects = l10n_update_get_projects();
92
  }
93

    
94
  if ($projects && $languages) {
95
    $form['updates'] = array(
96
      '#type' => 'value',
97
      '#value' => $updates,
98
    );
99
    // @todo Only show this language fieldset if we have more than 1 language.
100
    $form['lang'] = array(
101
      '#type' => 'fieldset',
102
      '#title' => t('Languages'),
103
      '#collapsible' => TRUE,
104
      '#collapsed' => TRUE,
105
      '#description' => t('Select one or more languages to download and update. If you select none, all of them will be updated.'),
106
    );
107
    $form['lang']['languages'] = array(
108
      '#type' => 'checkboxes',
109
      '#options' => $languages,
110
    );
111
    $form['mode'] = array(
112
      '#type' => 'radios',
113
      '#title' => t('Update mode'),
114
      '#default_value' => variable_get('l10n_update_import_mode', LOCALE_IMPORT_KEEP),
115
      '#options' => _l10n_update_admin_import_options(),
116
    );
117
    $form['buttons']['download'] = array(
118
      '#type' => 'submit',
119
      '#value' => t('Update translations'),
120
    );
121
  }
122
  $form['buttons']['refresh'] = array(
123
    '#type' => 'submit',
124
    '#value' => t('Refresh information'),
125
  );
126
  return $form;
127
}
128

    
129
/**
130
 * Submit handler for Update form.
131
 *
132
 * Handles both submit buttons to update translations and to update the
133
 * form information.
134
 */
135
function l10n_update_admin_import_form_submit($form, $form_state) {
136
  $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
137
  $projects = l10n_update_get_projects();
138

    
139
  if ($op == t('Update translations')) {
140
    $languages = array_filter($form_state['values']['languages']);
141
    $updates = $form_state['values']['updates'];
142
    $mode = $form_state['values']['mode'];
143
    if ($projects && $updates) {
144
      module_load_include('batch.inc', 'l10n_update');
145
      // Filter out updates in other languages. If no languages, all of them will be updated
146
      $updates = _l10n_update_prepare_updates($updates, NULL, $languages);
147
      $batch = l10n_update_batch_multiple($updates, $mode);
148
      batch_set($batch);
149
    }
150
    else {
151
      drupal_set_message(t('Cannot find any translation updates.'), 'error');
152
    }
153
  }
154
  elseif ($op == t('Refresh information')) {
155
    // Get current version of projects.
156
    l10n_update_build_projects();
157

    
158
    // Get available translation updates and update file history.
159
    if ($available = l10n_update_available_releases(TRUE)) {
160
      l10n_update_flag_history($available);
161
      drupal_set_message(t('Fetched information about available updates from the server'));
162
    }
163
    else {
164
      drupal_set_message(t('Failed to fetch information about available updates from the server.'), 'error');
165
    }
166
  }
167
}
168

    
169
/**
170
 * Page callback: Settings form.
171
 */
172
function l10n_update_admin_settings_form($form, &$form_state) {
173
  $form['l10n_update_check_mode'] = array(
174
    '#type' => 'radios',
175
    '#title' => t('Update source'),
176
    '#default_value' => variable_get('l10n_update_check_mode', L10N_UPDATE_CHECK_ALL),
177
    '#options' => _l10n_update_admin_check_options(),
178
  );
179
  $form['l10n_update_import_mode'] = array(
180
    '#type' => 'radios',
181
    '#title' => t('Update mode'),
182
    '#default_value' => variable_get('l10n_update_import_mode', LOCALE_IMPORT_KEEP),
183
    '#options' => _l10n_update_admin_import_options(),
184
  );
185
  $form['l10n_update_check_frequency'] = array(
186
    '#type' => 'radios',
187
    '#title' => t('Check for updates'),
188
    '#default_value' => variable_get('l10n_update_check_frequency', 0),
189
    '#options' => array(
190
      0 => t('Never (manually)'),
191
      1 => t('Daily'),
192
      7 => t('Weekly'),
193
    ),
194
    '#description' => t('Select how frequently you want to automatically check for updated translations for installed modules and themes.'),
195
  );
196
  $form['l10n_update_check_disabled'] = array(
197
    '#type' => 'checkbox',
198
    '#title' => t('Check for updates of disabled modules and themes'),
199
    '#default_value' => variable_get('l10n_update_check_disabled', 0),
200
    '#description' => t('Note that this comes with a performance penalty, so it is not recommended.'),
201
  );
202
  $form['l10n_update_download_store'] = array(
203
    '#title' => t('Store downloaded files'),
204
    '#type' => 'textfield',
205
    '#default_value' => variable_get('l10n_update_download_store', ''),
206
    '#description' => t('A path relative to the Drupal installation directory where translation files will be stored, e.g. sites/all/translations. Saved translation files can be reused by other installations. If left empty the downloaded translation will not be saved.'),
207
  );
208
  return system_settings_form($form);
209
}
210

    
211
/**
212
 * Additional validation handler for update settings.
213
 *
214
 * Check for existing files directory and creates one when required.
215
 */
216
function l10n_update_admin_settings_form_validate($form, &$form_state) {
217
  $form_values = $form_state['values'];
218
  if (!empty($form_values['l10n_update_download_store'])) {
219
    if (!file_prepare_directory($form_values['l10n_update_download_store'], FILE_CREATE_DIRECTORY, 'l10n_update_download_store')) {
220
      form_set_error('l10n_update_download_store', t('The directory %directory does not exist or is not writable.', array('%directory' => $form_values['l10n_update_download_store'])));
221
      watchdog('file system', 'The directory %directory does not exist or is not writable.', array('%directory' => $form_values['l10n_update_download_store']), WATCHDOG_ERROR);
222
    }
223
  }
224
}
225

    
226
/**
227
 * Get array of import options.
228
 *
229
 * The import options of the Locale module are used but the UI text is altered
230
 * to suit the Localization update cases.
231
 *
232
 * @return
233
 *   Keyed array of import options.
234
 */
235
function _l10n_update_admin_import_options() {
236
  return array(
237
    LOCALE_IMPORT_OVERWRITE => t('Translation updates replace existing ones, new ones are added'),
238
    LOCALE_UPDATE_OVERRIDE_DEFAULT => t('Edited translations are kept, only previously imported ones are overwritten and new translations are added'),
239
    LOCALE_IMPORT_KEEP => t('All existing translations are kept, only new translations are added.'),
240
  );
241
}
242

    
243
/**
244
 * Get array of check options.
245
 *
246
 * @return
247
 *   Keyed array of source download options.
248
 */
249
function _l10n_update_admin_check_options() {
250
  return array(
251
    L10N_UPDATE_CHECK_ALL => t('Local files and remote server.'),
252
    L10N_UPDATE_CHECK_LOCAL => t('Local files only.'),
253
    L10N_UPDATE_CHECK_REMOTE => t('Remote server only.'),
254
  );
255
}
256

    
257
/**
258
 * Format project update status.
259
 *
260
 * @param $variables
261
 *   An associative array containing:
262
 *    - projects: An array containing all enabled projects.
263
 *    - languages: An array of all enabled languages.
264
 *    - history: An array of the current translations per project.
265
 *    - available: An array of translation sources per project.
266
 *    - updates: An array of available translation updates per project.
267
 *      Only recommended translations are listed.
268
 *
269
 * @return string
270
 *   HTML output.
271
 */
272
function theme_l10n_update_project_status($variables) {
273
  $header = $rows = array();
274

    
275
  // Get module and theme data for the project title.
276
  $projects = system_rebuild_module_data();
277
  $projects += system_rebuild_theme_data();
278

    
279
  foreach ($variables['projects'] as $name => $project) {
280
    if (isset($variables['history'][$name])) {
281
      if (isset($variables['updates'][$name])) {
282
        $project_status = 'updatable';
283
        $project_class = 'warning';
284
      }
285
      else {
286
        $project_status = 'uptodate';
287
        $project_class = 'ok';
288
      }
289
    }
290
    elseif (isset($variables['available'][$name])) {
291
      $project_status = 'available';
292
      $project_class = 'warning';
293
    }
294
    else {
295
      // Remote information not checked
296
      $project_status = 'unknown';
297
      $project_class = 'unknown';
298
    }
299

    
300
    // Get the project title and module version.
301
    $project->title = isset($projects[$name]->info['name']) ? $projects[$name]->info['name'] : '';
302
    $project->module_version = isset($projects[$name]->info['version']) ? $projects[$name]->info['version'] : $project->version;
303

    
304
    // Project with related language states.
305
    $row = theme('l10n_update_single_project_wrapper', array(
306
      'project' => $project,
307
      'project_status' => $project_status,
308
      'languages' => $variables['languages'],
309
      'available' => $variables['available'],
310
      'history' => $variables['history'],
311
      'updates' => $variables['updates'],
312
    ));
313

    
314
    $rows[$project->project_type][] = array(
315
      'data' => array(
316
        array(
317
          'data' => $row,
318
          'class' => 'l10n-update-wrapper collapsed',
319
        ),
320
      ),
321
      'class' => array($project_class),
322
    );
323
  }
324

    
325
  // Build tables of update states grouped by project type. Similar to the
326
  // status report by the Update module.
327
  $output = '';
328
  $project_types = array(
329
    'core' => t('Drupal core'),
330
    'module' => t('Modules'),
331
    'theme' => t('Themes'),
332
    'module-disabled' => t('Disabled modules'),
333
    'theme-disabled' => t('Disabled themes'),
334
  );
335
  foreach ($project_types as $type_name => $type_label) {
336
    if (!empty($rows[$type_name])) {
337
      ksort($rows[$type_name]);
338
      $output .= "\n<h3>" . $type_label . "</h3>\n";
339
      $output .= theme('table', array('header' => $header, 'rows' => $rows[$type_name], 'attributes' => array('class' => array('update l10n-update'))));
340
    }
341
  }
342

    
343
  // We use the core update module CSS to re-use the color definitions.
344
  // Plus add our own css and js.
345
  drupal_add_css(drupal_get_path('module', 'update') . '/update.css');
346
  drupal_add_css(drupal_get_path('module', 'l10n_update') . '/css/l10n_update.admin.css');
347
  drupal_add_js(drupal_get_path('module', 'l10n_update') . '/js/l10n_update.js');
348

    
349
  return $output;
350
}
351

    
352
/**
353
 * Format project translation state with states per language.
354
 *
355
 * @param $variables
356
 *   An associative array containing:
357
 *   - project: Project data object
358
 *   - project_status: Project status
359
 *   - languages: Available languages.
360
 *  @return string
361
 *    HTML output.
362
 */
363
function theme_l10n_update_single_project_wrapper($variables) {
364
  $project = $variables['project'];
365
  $name = $project->name;
366
  $project_status = $variables['project_status'];
367
  $languages = $variables['languages'];
368
  $history = $variables['history'];
369
  $updates = $variables['updates'];
370
  $availables = $variables['available'];
371

    
372
  // Output project title and project summary status.
373
  $output = theme('l10n_update_single_project_status', array(
374
    'project' => $project,
375
    'server' => l10n_update_server($project->l10n_server),
376
    'status' => $project_status,
377
  ));
378

    
379
  // Translation status per language is displayed in a table, one language per row.
380
  // For each language the current translation is listed. And optionally the
381
  // most recent update.
382
  $rows = array();
383
  foreach ($languages as $lang => $language) {
384
    // Determine current translation status and update status.
385
    $installed = isset($history[$name][$lang]) ? $history[$name][$lang] : NULL;
386
    $update = isset($updates[$name][$lang]) ? $updates[$name][$lang] : NULL;
387
    $available = isset($availables[$name][$lang]) ? $availables[$name][$lang] : NULL;
388
    if ($installed) {
389
      if ($update) {
390
        $status = 'updatable';
391
        $class = 'messages warning';
392
      }
393
      else {
394
        $status = 'uptodate';
395
        $class = 'ok';
396
      }
397
    }
398
    elseif ($available) {
399
      $status = 'available';
400
      $class = 'warning';
401
    }
402
    else {
403
      $status = 'unknown';
404
      $class = 'unknown';
405
    }
406

    
407
    // The current translation version.
408
    $row = theme('l10n_update_current_release', array('language' => $language, 'release' => $installed, 'status' => $status));
409

    
410
    // If an update is available, add it.
411
    if ($update) {
412
      $row .= theme('l10n_update_available_release', array('release' => $update));
413
    }
414

    
415
    $rows[] = array(
416
      'data' => array($row),
417
      'class' => array($class),
418
    );
419
  }
420

    
421
  // Output tables with translation status per language.
422
  $output .= '<div class="fieldset-wrapper">' . "\n";
423
  $output .= theme('table', array('header' => array(), 'rows' => $rows));
424
  $output .= "</div>\n";
425

    
426
  return $output;
427
}
428

    
429
/**
430
 * Format a single project translation state.
431
 *
432
 * @param $variables
433
 *   An associative array containing:
434
 *   - project: project data object.
435
 *   - server: (optional) remote server data object.
436
 *   - status: project summary status.
437
 *  @return string
438
 *    HTML output.
439
 */
440
function theme_l10n_update_single_project_status($variables) {
441
  $project = $variables['project'];
442
  $server = $variables['server'];
443
  $title = $project->title ? $project->title : $project->name;
444

    
445
  $output = '<div class="project">';
446
  $output .= '<span class="project-title">' . check_plain($title) . '</span>' . ' ' . check_plain($project->module_version) ;
447
  if ($server = l10n_update_server($project->l10n_server)) {
448
    $output .= '<span class="project-server">' . t('(translation source: !server)', array('!server' => l($server['name'], $server['link']))) . '</span>';
449
  }
450
  $output .= theme('l10n_update_version_status', array('status' => $variables['status']));
451
  $output .= "</div>\n";
452

    
453
  return $output;
454
}
455

    
456
/**
457
 * Format current translation version.
458
 *
459
 * @param $variables
460
 *   An associative array containing:
461
 *   - language: Language name.
462
 *   - release: Current file data.
463
 *   - status: Release status.
464
 * @return string
465
 *   HTML output.
466
 */
467
function theme_l10n_update_current_release($variables) {
468
  if (isset($variables['release'])) {
469
    $date = $variables['release']->timestamp;
470
    $version = $variables['release']->version;
471
    $text = t('@language: @version (!date)', array('@language' => $variables['language'], '@version' => $version, '!date' => format_date($date, 'custom', 'Y-M-d')));
472
  }
473
  else {
474
    $text = t('@language: <em>No installed translation</em>', array('@language' => $variables['language']));
475
  }
476

    
477
  $output = '<div class="language">';
478
  $output .= $text;
479
  $output .= theme('l10n_update_version_status', $variables);
480
  $output .= "</div>\n";
481

    
482
  return $output;
483
}
484

    
485
/**
486
 * Format current translation version.
487
 *
488
 * @param object $release
489
 *   Update file data.
490
 * @return string
491
 *   HTML output.
492
 */
493
function theme_l10n_update_available_release($variables) {
494
  $date = $variables['release']->timestamp;
495
  $version = $variables['release']->version;
496
  if (!empty($variables['release']->fileurl)) {
497
    // Remote file, straight link
498
    $link = l(t('Download'), $variables['release']->fileurl);
499
  }
500
  elseif (!empty($variables['release']->uri)) {
501
    // Local file, try something
502
    $link = l(t('Download'), $variables['release']->uri, array('absolute' => TRUE));
503
  }
504

    
505
  $output = '<div class="version version-recommended">';
506
  $output .=  t('Recommended version: @version (!date)', array('@version' => $version, '!date' => format_date($date, 'custom', 'Y-M-d')));
507
  $output .= '<span class="version-links">' . $link . '</span>';
508
  $output .= "</div>\n";
509
  return $output;
510
}
511

    
512
/**
513
 * Format version status with icon.
514
 *
515
 * @param string $status
516
 *   Version status: 'uptodate', 'updatable', 'available', 'unknown'.
517
 * @param string $type
518
 *   Update type: 'download', 'localfile'.
519
 *
520
 * @return sting
521
 *   HTML output.
522
 */
523
function theme_l10n_update_version_status($variables) {
524
  $icon = '';
525
  $msg = '';
526

    
527
  switch ($variables['status']) {
528
    case 'uptodate':
529
      $icon = theme('image', array('path' => 'misc/watchdog-ok.png', 'alt' => t('ok'), 'title' => t('ok')));
530
      $msg = '<span class="current">' . t('Up to date') . '</span>';
531
      break;
532
    case 'updatable':
533
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
534
      $msg = '<span class="not-current">' . t('Update available') . '</span>';
535
      break;
536
    case 'available':
537
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
538
      $msg = '<span class="not-current">' . t('Uninstalled translation available') . '</span>';
539
      break;
540
    case 'unknown':
541
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
542
      $msg = '<span class="not-supported">' . t('No available translations found') . '</span>';
543
      break;
544
  }
545
  $output = '<div class="version-status">';
546
  $output .= $msg;
547
  $output .= '<span class="icon">' . $icon . '</span>';
548
  $output .= "</div>\n";
549
  return $output;
550
}