Projet

Général

Profil

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

root / drupal7 / sites / all / modules / l10n_update / l10n_update.admin.inc @ 503b3f7b

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_languages'] = array('#markup' => t('No translatable language defined. <a href="/admin/config/regional/language">Add a language</a>.'));
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

    
100
    if (count($languages) > 1) {
101
      $form['lang'] = array(
102
        '#type' => 'fieldset',
103
        '#title' => t('Languages'),
104
        '#collapsible' => TRUE,
105
        '#collapsed' => FALSE ,
106
        '#description' => t('Select one or more languages to download and update. If you select none, all of them will be updated.'),
107
      );
108
      $form['lang']['languages'] = array(
109
        '#type' => 'checkboxes',
110
        '#options' => $languages,
111
      );
112
    }
113

    
114
    if ($updates) {
115
      $form['actions']['download'] = array(
116
        '#type' => 'submit',
117
        '#value' => t('Update translations'),
118
      );
119
    }
120
  }
121
  $form['actions']['refresh'] = array(
122
    '#type' => 'submit',
123
    '#value' => t('Refresh information'),
124
  );
125
  return $form;
126
}
127

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

    
138
  if ($op == t('Update translations')) {
139
    $languages = isset($form_state['values']['languages']) ? array_filter($form_state['values']['languages']) : NULL;
140
    $updates = $form_state['values']['updates'];
141
    $mode = variable_get('l10n_update_import_mode', LOCALE_IMPORT_KEEP);
142

    
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
  }
151
  elseif ($op == t('Refresh information')) {
152
    // Get current version of projects.
153
    l10n_update_build_projects();
154

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

    
166
/**
167
 * Page callback: Settings form.
168
 */
169
function l10n_update_admin_settings_form($form, &$form_state) {
170
  $form['l10n_update_check_mode'] = array(
171
    '#type' => 'radios',
172
    '#title' => t('Update source'),
173
    '#default_value' => variable_get('l10n_update_check_mode', L10N_UPDATE_CHECK_ALL),
174
    '#options' => _l10n_update_admin_check_options(),
175
  );
176
  $form['l10n_update_import_mode'] = array(
177
    '#type' => 'radios',
178
    '#title' => t('Update mode'),
179
    '#default_value' => variable_get('l10n_update_import_mode', LOCALE_IMPORT_KEEP),
180
    '#options' => _l10n_update_admin_import_options(),
181
  );
182
  $form['l10n_update_check_frequency'] = array(
183
    '#type' => 'radios',
184
    '#title' => t('Check for updates'),
185
    '#default_value' => variable_get('l10n_update_check_frequency', 0),
186
    '#options' => array(
187
      0 => t('Never (manually)'),
188
      1 => t('Daily'),
189
      7 => t('Weekly'),
190
    ),
191
    '#description' => t('Select how frequently you want to automatically check for updated translations for installed modules and themes.'),
192
  );
193
  $form['l10n_update_check_disabled'] = array(
194
    '#type' => 'checkbox',
195
    '#title' => t('Check for updates of disabled modules and themes'),
196
    '#default_value' => variable_get('l10n_update_check_disabled', 0),
197
    '#description' => t('Note that this comes with a performance penalty, so it is not recommended.'),
198
  );
199
  $form['l10n_update_download_store'] = array(
200
    '#title' => t('Store downloaded files'),
201
    '#type' => 'textfield',
202
    '#default_value' => variable_get('l10n_update_download_store', ''),
203
    '#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.'),
204
  );
205
  return system_settings_form($form);
206
}
207

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

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

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

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

    
272
  // Get module and theme data for the project title.
273
  $projects = system_rebuild_module_data();
274
  $projects += system_rebuild_theme_data();
275

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

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

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

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

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

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

    
346
  return $output;
347
}
348

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

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

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

    
404
    // The current translation version.
405
    $row = theme('l10n_update_current_release', array('language' => $language, 'release' => $installed, 'status' => $status));
406

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

    
412
    $rows[] = array(
413
      'data' => array($row),
414
      'class' => array($class),
415
    );
416
  }
417

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

    
423
  return $output;
424
}
425

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

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

    
450
  return $output;
451
}
452

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

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

    
479
  return $output;
480
}
481

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

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

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

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