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 @ f066bdb5

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('misc/collapse.js');
345
  drupal_add_js(drupal_get_path('module', 'l10n_update') . '/js/l10n_update.js');
346

    
347
  return $output;
348
}
349

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

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

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

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

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

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

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

    
424
  return $output;
425
}
426

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

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

    
451
  return $output;
452
}
453

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

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

    
480
  return $output;
481
}
482

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

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

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

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