Projet

Général

Profil

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

root / drupal7 / sites / all / modules / l10n_update / l10n_update.admin.inc @ 620f9137

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

    
206
  $form = system_settings_form($form);
207
  $form['#submit'][] = 'l10n_update_admin_settings_form_submit';
208

    
209
  return $form;
210
}
211

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

    
227
/**
228
 * Additional submit handler for update settings.
229
 */
230
function l10n_update_admin_settings_form_submit($form, &$form_state) {
231
  // Add .htaccess file to the translations directory.
232
  l10n_update_ensure_htaccess();
233
}
234

    
235
/**
236
 * Get array of import options.
237
 *
238
 * The import options of the Locale module are used but the UI text is altered
239
 * to suit the Localization update cases.
240
 *
241
 * @return
242
 *   Keyed array of import options.
243
 */
244
function _l10n_update_admin_import_options() {
245
  return array(
246
    LOCALE_IMPORT_OVERWRITE => t('Translation updates replace existing ones, new ones are added'),
247
    LOCALE_UPDATE_OVERRIDE_DEFAULT => t('Edited translations are kept, only previously imported ones are overwritten and new translations are added'),
248
    LOCALE_IMPORT_KEEP => t('All existing translations are kept, only new translations are added.'),
249
  );
250
}
251

    
252
/**
253
 * Get array of check options.
254
 *
255
 * @return
256
 *   Keyed array of source download options.
257
 */
258
function _l10n_update_admin_check_options() {
259
  return array(
260
    L10N_UPDATE_CHECK_ALL => t('Local files and remote server.'),
261
    L10N_UPDATE_CHECK_LOCAL => t('Local files only.'),
262
    L10N_UPDATE_CHECK_REMOTE => t('Remote server only.'),
263
  );
264
}
265

    
266
/**
267
 * Format project update status.
268
 *
269
 * @param $variables
270
 *   An associative array containing:
271
 *    - projects: An array containing all enabled projects.
272
 *    - languages: An array of all enabled languages.
273
 *    - history: An array of the current translations per project.
274
 *    - available: An array of translation sources per project.
275
 *    - updates: An array of available translation updates per project.
276
 *      Only recommended translations are listed.
277
 *
278
 * @return string
279
 *   HTML output.
280
 */
281
function theme_l10n_update_project_status($variables) {
282
  $header = $rows = array();
283

    
284
  // Get module and theme data for the project title.
285
  $projects = system_rebuild_module_data();
286
  $projects += system_rebuild_theme_data();
287

    
288
  foreach ($variables['projects'] as $name => $project) {
289
    if (isset($variables['history'][$name])) {
290
      if (isset($variables['updates'][$name])) {
291
        $project_status = 'updatable';
292
        $project_class = 'warning';
293
      }
294
      else {
295
        $project_status = 'uptodate';
296
        $project_class = 'ok';
297
      }
298
    }
299
    elseif (isset($variables['available'][$name])) {
300
      $project_status = 'available';
301
      $project_class = 'warning';
302
    }
303
    else {
304
      // Remote information not checked
305
      $project_status = 'unknown';
306
      $project_class = 'unknown';
307
    }
308

    
309
    // Get the project title and module version.
310
    $project->title = isset($projects[$name]->info['name']) ? $projects[$name]->info['name'] : '';
311
    $project->module_version = isset($projects[$name]->info['version']) ? $projects[$name]->info['version'] : $project->version;
312

    
313
    // Project with related language states.
314
    $row = theme('l10n_update_single_project_wrapper', array(
315
      'project' => $project,
316
      'project_status' => $project_status,
317
      'languages' => $variables['languages'],
318
      'available' => $variables['available'],
319
      'history' => $variables['history'],
320
      'updates' => $variables['updates'],
321
    ));
322

    
323
    $rows[$project->project_type][] = array(
324
      'data' => array(
325
        array(
326
          'data' => $row,
327
          'class' => 'l10n-update-wrapper collapsed',
328
        ),
329
      ),
330
      'class' => array($project_class),
331
    );
332
  }
333

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

    
352
  // We use the core update module CSS to re-use the color definitions.
353
  // Plus add our own css and js.
354
  drupal_add_css(drupal_get_path('module', 'update') . '/update.css');
355
  drupal_add_css(drupal_get_path('module', 'l10n_update') . '/css/l10n_update.admin.css');
356
  drupal_add_js('misc/collapse.js');
357
  drupal_add_js(drupal_get_path('module', 'l10n_update') . '/js/l10n_update.js');
358

    
359
  return $output;
360
}
361

    
362
/**
363
 * Format project translation state with states per language.
364
 *
365
 * @param $variables
366
 *   An associative array containing:
367
 *   - project: Project data object
368
 *   - project_status: Project status
369
 *   - languages: Available languages.
370
 *  @return string
371
 *    HTML output.
372
 */
373
function theme_l10n_update_single_project_wrapper($variables) {
374
  $project = $variables['project'];
375
  $name = $project->name;
376
  $project_status = $variables['project_status'];
377
  $languages = $variables['languages'];
378
  $history = $variables['history'];
379
  $updates = $variables['updates'];
380
  $availables = $variables['available'];
381

    
382
  // Output project title and project summary status.
383
  $output = theme('l10n_update_single_project_status', array(
384
    'project' => $project,
385
    'server' => l10n_update_server($project->l10n_server),
386
    'status' => $project_status,
387
  ));
388

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

    
417
    // The current translation version.
418
    $row = theme('l10n_update_current_release', array('language' => $language, 'release' => $installed, 'status' => $status));
419

    
420
    // If an update is available, add it.
421
    if ($update) {
422
      $row .= theme('l10n_update_available_release', array('release' => $update));
423
    }
424

    
425
    $rows[] = array(
426
      'data' => array($row),
427
      'class' => array($class),
428
    );
429
  }
430

    
431
  // Output tables with translation status per language.
432
  $output .= '<div class="fieldset-wrapper">' . "\n";
433
  $output .= theme('table', array('header' => array(), 'rows' => $rows));
434
  $output .= "</div>\n";
435

    
436
  return $output;
437
}
438

    
439
/**
440
 * Format a single project translation state.
441
 *
442
 * @param $variables
443
 *   An associative array containing:
444
 *   - project: project data object.
445
 *   - server: (optional) remote server data object.
446
 *   - status: project summary status.
447
 *  @return string
448
 *    HTML output.
449
 */
450
function theme_l10n_update_single_project_status($variables) {
451
  $project = $variables['project'];
452
  $server = $variables['server'];
453
  $title = $project->title ? $project->title : $project->name;
454

    
455
  $output = '<div class="project">';
456
  $output .= '<span class="project-title">' . check_plain($title) . '</span>' . ' ' . check_plain($project->module_version) ;
457
  if ($server = l10n_update_server($project->l10n_server)) {
458
    $output .= '<span class="project-server">' . t('(translation source: !server)', array('!server' => l($server['name'], $server['link']))) . '</span>';
459
  }
460
  $output .= theme('l10n_update_version_status', array('status' => $variables['status']));
461
  $output .= "</div>\n";
462

    
463
  return $output;
464
}
465

    
466
/**
467
 * Format current translation version.
468
 *
469
 * @param $variables
470
 *   An associative array containing:
471
 *   - language: Language name.
472
 *   - release: Current file data.
473
 *   - status: Release status.
474
 * @return string
475
 *   HTML output.
476
 */
477
function theme_l10n_update_current_release($variables) {
478
  if (isset($variables['release'])) {
479
    $date = $variables['release']->timestamp;
480
    $version = $variables['release']->version;
481
    $text = t('@language: @version (!date)', array('@language' => $variables['language'], '@version' => $version, '!date' => format_date($date, 'custom', 'Y-M-d')));
482
  }
483
  else {
484
    $text = t('@language: <em>No installed translation</em>', array('@language' => $variables['language']));
485
  }
486

    
487
  $output = '<div class="language">';
488
  $output .= $text;
489
  $output .= theme('l10n_update_version_status', $variables);
490
  $output .= "</div>\n";
491

    
492
  return $output;
493
}
494

    
495
/**
496
 * Format current translation version.
497
 *
498
 * @param object $release
499
 *   Update file data.
500
 * @return string
501
 *   HTML output.
502
 */
503
function theme_l10n_update_available_release($variables) {
504
  $date = $variables['release']->timestamp;
505
  $version = $variables['release']->version;
506
  if (!empty($variables['release']->fileurl)) {
507
    // Remote file, straight link
508
    $link = l(t('Download'), $variables['release']->fileurl);
509
  }
510
  elseif (!empty($variables['release']->uri)) {
511
    // Local file, try something
512
    $link = l(t('Download'), $variables['release']->uri, array('absolute' => TRUE));
513
  }
514

    
515
  $output = '<div class="version version-recommended">';
516
  $output .=  t('Recommended version: @version (!date)', array('@version' => $version, '!date' => format_date($date, 'custom', 'Y-M-d')));
517
  $output .= '<span class="version-links">' . $link . '</span>';
518
  $output .= "</div>\n";
519
  return $output;
520
}
521

    
522
/**
523
 * Format version status with icon.
524
 *
525
 * @param string $status
526
 *   Version status: 'uptodate', 'updatable', 'available', 'unknown'.
527
 * @param string $type
528
 *   Update type: 'download', 'localfile'.
529
 *
530
 * @return sting
531
 *   HTML output.
532
 */
533
function theme_l10n_update_version_status($variables) {
534
  $icon = '';
535
  $msg = '';
536

    
537
  switch ($variables['status']) {
538
    case 'uptodate':
539
      $icon = theme('image', array('path' => 'misc/watchdog-ok.png', 'alt' => t('ok'), 'title' => t('ok')));
540
      $msg = '<span class="current">' . t('Up to date') . '</span>';
541
      break;
542
    case 'updatable':
543
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
544
      $msg = '<span class="not-current">' . t('Update available') . '</span>';
545
      break;
546
    case 'available':
547
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
548
      $msg = '<span class="not-current">' . t('Uninstalled translation available') . '</span>';
549
      break;
550
    case 'unknown':
551
      $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning')));
552
      $msg = '<span class="not-supported">' . t('No available translations found') . '</span>';
553
      break;
554
  }
555
  $output = '<div class="version-status">';
556
  $output .= $msg;
557
  $output .= '<span class="icon">' . $icon . '</span>';
558
  $output .= "</div>\n";
559
  return $output;
560
}