You are here

translation_overview.pages.inc in Translation Overview 6

Same filename and directory in other branches
  1. 6.2 translation_overview.pages.inc

File

translation_overview.pages.inc
View source
<?php

/**
 * List node administration filters that can be applied.
 *
 * This is a fork of node_filters().
 */
function translation_overview_node_filters() {

  // Regular filters
  $filters['status'] = array(
    'title' => t('status'),
    'options' => array(
      'status-1' => t('Published'),
      'status-0' => t('Not published'),
      'promote-1' => t('Promoted'),
      'promote-0' => t('Not promoted'),
      'sticky-1' => t('Sticky'),
      'sticky-0' => t('Not sticky'),
      'translate-0' => t('Up to date translation'),
      'translate-1' => t('Outdated translation'),
    ),
  );
  $filters['type'] = array(
    'title' => t('type'),
    'options' => translation_overview_node_types(),
  );

  // The taxonomy filter
  if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
    $filters['category'] = array(
      'title' => t('category'),
      'options' => $taxonomy,
    );
  }
  return $filters;
}

/**
 * Return form for node administration filters.
 *
 * This is a fork of node_filter_form().
 */
function translation_overview_filter_form() {

  // We reuse a bunch of the node.module's stuff.
  module_load_include('inc', 'node', 'node.admin');
  $session =& $_SESSION['translation_overview_filter'];
  $session = is_array($session) ? $session : array();
  $filters = translation_overview_node_filters();
  $i = 0;
  $form['filters'] = array(
    '#type' => 'fieldset',
    '#title' => t('Show only items where'),
    '#theme' => 'node_filters',
  );
  $form['#submit'][] = 'translation_overview_filter_form_submit';
  foreach ($session as $filter) {
    list($type, $value) = $filter;
    if ($type == 'category') {

      // Load term name from DB rather than search and parse options array.
      $value = module_invoke('taxonomy', 'get_term', $value);
      $value = $value->name;
    }
    else {
      $value = $filters[$type]['options'][$value];
    }
    if ($i++) {
      $form['filters']['current'][] = array(
        '#value' => t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', array(
          '%a' => $filters[$type]['title'],
          '%b' => $value,
        )),
      );
    }
    else {
      $form['filters']['current'][] = array(
        '#value' => t('<strong>%a</strong> is <strong>%b</strong>', array(
          '%a' => $filters[$type]['title'],
          '%b' => $value,
        )),
      );
    }
    if (in_array($type, array(
      'type',
      'language',
    ))) {

      // Remove the option if it is already being filtered on.
      unset($filters[$type]);
    }
  }
  foreach ($filters as $key => $filter) {
    $names[$key] = $filter['title'];
    $form['filters']['status'][$key] = array(
      '#type' => 'select',
      '#options' => $filter['options'],
    );
  }
  $form['filters']['filter'] = array(
    '#type' => 'radios',
    '#options' => $names,
    '#default_value' => 'status',
  );
  $form['filters']['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => count($session) ? t('Refine') : t('Filter'),
  );
  if (count($session)) {
    $form['filters']['buttons']['undo'] = array(
      '#type' => 'submit',
      '#value' => t('Undo'),
    );
    $form['filters']['buttons']['reset'] = array(
      '#type' => 'submit',
      '#value' => t('Reset'),
    );
  }
  drupal_add_js('misc/form.js', 'core');
  return $form;
}

/**
 * Process result from node administration filter form.
 *
 * This is a fork of node_filter_form(). 
 */
function translation_overview_filter_form_submit($form, &$form_state) {
  $filters = translation_overview_node_filters();
  switch ($form_state['values']['op']) {
    case t('Filter'):
    case t('Refine'):
      if (isset($form_state['values']['filter'])) {
        $filter = $form_state['values']['filter'];

        // Flatten the options array to accommodate hierarchical/nested options.
        $flat_options = form_options_flatten($filters[$filter]['options']);
        if (isset($flat_options[$form_state['values'][$filter]])) {
          $_SESSION['translation_overview_filter'][] = array(
            $filter,
            $form_state['values'][$filter],
          );
        }
      }
      break;
    case t('Undo'):
      array_pop($_SESSION['translation_overview_filter']);
      break;
    case t('Reset'):
      $_SESSION['translation_overview_filter'] = array();
      break;
  }
}

/**
 * Build the where clause for a filtered query.
 *
 * This is a fork of node_filter_form_submit().
 */
function translation_overview_build_filter_query() {
  $filters = translation_overview_node_filters();

  // Build query
  $join = $where = $args = array();
  if (!$_SESSION['translation_overview_filter']) {
    $_SESSION['translation_overview_filter'] = array();
  }
  foreach ($_SESSION['translation_overview_filter'] as $index => $filter) {
    list($key, $value) = $filter;
    switch ($key) {
      case 'status':

        // Note: no exploitable hole as $key/$value have already been checked when submitted
        list($key, $value) = explode('-', $value, 2);
        $where['status'] = 'n.' . $key . ' = %d';
        break;
      case 'category':
        $table = "tn{$index}";
        $where[$table] = "{$table}.tid = %d";
        $join[$table] = "INNER JOIN {term_node} {$table} ON n.nid = {$table}.nid ";
        break;
      case 'type':
        $where['type'] = "n.type = '%s'";
        break;
    }
    $args[] = $value;
  }

  // Make sure we limit it to translation enabled types.
  if (!isset($where['type'])) {
    $types = array_keys(translation_overview_node_types());
    $where[] = 'n.type IN (' . db_placeholders($types, 'varchar') . ')';
    $args = array_merge($args, $types);
  }
  return array(
    'where' => $where,
    'join' => $join,
    'args' => $args,
  );
}

/**
 * Translation overview page.
 *
 * Current assumptions:
 *  - translated node's status is synchronized via the i18n_sync module.
 */
function translation_overview_overview_page() {
  drupal_add_css(drupal_get_path('module', 'translation_overview') . '/translation_overview.css');
  $rows_per_page = 30;

  // Bail if there are no translatable nodes
  if (count(translation_overview_node_types()) == 0) {
    drupal_set_message(t('There are no translateable node types on this site.'), 'error');
    return '';
  }

  // Get a list of the enabled languages
  $languages = array();
  foreach (language_list() as $key => $language) {
    if ($language->enabled) {
      $languages[$key] = $language->language;
    }
  }

  // Sort the list so the order matches the menu items.
  asort($languages);
  $header = array(
    array(
      'field' => 'n.title',
      'data' => t('Title'),
      'sort' => 'asc',
    ),
    array(
      'field' => 'n.type',
      'data' => t('Type'),
    ),
    array(
      'field' => 'n.created',
      'data' => t('Created'),
    ),
  );
  foreach ($languages as $key => $language_name) {
    $header[] = array(
      'data' => str_replace('-', '<br />', $language_name),
      'class' => 'translation-overview-lang',
    );
  }
  $query = translation_overview_build_filter_query();
  $sql = "SELECT n.nid, n.title, n.type, n.tnid, n.status, n.created, n.language, n.translate \n    FROM {node} n " . implode(' ', $query['join']) . " WHERE (n.nid = n.tnid OR n.tnid = 0) AND n.language <> '' AND n.language IS NOT NULL\n    AND " . implode(' AND ', $query['where']) . tablesort_sql($header);
  $rows = array();
  $result = pager_query(db_rewrite_sql($sql), $rows_per_page, 0, NULL, $query['args']);
  while ($node = db_fetch_object($result)) {

    // Shorten down the title so the table isn't too wide.
    $title = $node->title;
    if (drupal_strlen($title) > 20) {
      $title = drupal_substr($title, 0, 15) . '...';
    }
    $row = array(
      array(
        'data' => l($title, 'node/' . $node->nid, array(
          'attributes' => array(
            'title' => $node->title,
          ),
        )),
      ),
      array(
        'data' => check_plain($node->type),
      ),
      array(
        'data' => format_date($node->created, 'custom', 'j M Y'),
      ),
    );

    // Load the node's translations and then fill in the table with the status.
    $translations = (array) translation_node_get_translations($node->tnid);
    foreach ($languages as $language) {
      $translation_nid = empty($translations[$language]->nid) ? NULL : $translations[$language]->nid;
      $row[$language] = array(
        'data' => translation_overview_translation_link($node, $translation_nid, $language, FALSE),
        'class' => 'translation-overview-status',
      );
    }
    $rows[] = $row;
  }
  return drupal_get_form('translation_overview_filter_form') . theme('table', $header, $rows) . theme('pager', NULL, $rows_per_page);
}
function translation_overview_language_page($language) {
  $rows_per_page = 30;
  $types = array_keys(translation_overview_node_types());

  // Bail if there are no translatable nodes
  if (count($types) == 0) {
    drupal_set_message(t('There are no translateable node types on this site.'), 'error');
    return '';
  }
  $header = array(
    array(
      'field' => 'n.title',
      'data' => t('Title'),
    ),
    array(
      'field' => 'n.type',
      'data' => t('Type'),
    ),
    array(
      'field' => 'n.status',
      'data' => t('Status'),
    ),
    array(
      'field' => 'n.language',
      'data' => t('Language'),
    ),
    array(
      'field' => 'n.created',
      'data' => t('Created'),
    ),
    array(
      'field' => 'translation_status',
      'data' => t('Translated'),
      'sort' => 'asc',
    ),
  );

  // We want to sort the nodes by the status so we have to resort to this SQL
  // CASE statement.
  // NOTE: the '0 AS i18n' is a little hack to prevent i18n from re-writing our
  // query.
  $rows = array();
  $query = translation_overview_build_filter_query();
  $sql = "SELECT n.nid, n.title, n.type, n.language, n.status, n.created, n.tnid, nt.nid AS t_nid, CASE\n    WHEN n.language = '%s' THEN '4 LOCAL'\n    WHEN nt.translate = 0 THEN '3 DONE'\n    WHEN nt.tnid IS NULL THEN '2 MISS'\n    WHEN n.nid = n.tnid THEN '1 OLD'\n    ELSE 'unknown' END AS translation_status, 0 AS i18n\n    FROM {node} n LEFT JOIN {node} nt ON n.nid = nt.tnid AND nt.language = '%s' " . implode(' ', $query['join']) . "\n    WHERE (n.nid = n.tnid OR n.tnid = 0) AND n.language <> '' AND n.language IS NOT NULL\n    AND " . implode(' AND ', $query['where']) . tablesort_sql($header);

  // We need to put the language that we use as an argument early in the query
  // at the beginning of the arguments list.
  array_unshift($query['args'], $language);
  array_unshift($query['args'], $language);
  $rows = array();
  $result = pager_query(db_rewrite_sql($sql), $rows_per_page, 0, NULL, $query['args']);
  while ($node = db_fetch_object($result)) {

    // Shorten down the title
    $title = $node->title;
    if (drupal_strlen($title) > 25) {
      $title = drupal_substr($title, 0, 20) . '...';
    }
    $rows[] = array(
      l($title, 'node/' . $node->nid, array(
        'attributes' => array(
          'title' => $node->title,
        ),
      )),
      check_plain($node->type),
      empty($node->status) ? t('Unpublished') : t('Published'),
      $node->language,
      format_date($node->created, 'custom', 'j M Y'),
      translation_overview_translation_link($node, $node->t_nid, $language, TRUE),
    );
  }
  return drupal_get_form('translation_overview_filter_form') . theme('table', $header, $rows) . theme('pager', NULL, $rows_per_page);
}

Functions

Namesort descending Description
translation_overview_build_filter_query Build the where clause for a filtered query.
translation_overview_filter_form Return form for node administration filters.
translation_overview_filter_form_submit Process result from node administration filter form.
translation_overview_language_page
translation_overview_node_filters List node administration filters that can be applied.
translation_overview_overview_page Translation overview page.