You are here

tmgmt_local.module in Translation Management Tool 7

Same filename and directory in other branches
  1. 8 translators/tmgmt_local/tmgmt_local.module

Main module file for the local translation module.

File

translators/tmgmt_local/tmgmt_local.module
View source
<?php

/**
 * @file
 * Main module file for the local translation module.
 */

/**
 * @defgroup tmgmt_local_task TMGMT Local Task
 * @{
 * Various local task API functions.
 */

/**
 * Modules should return this value from hook_tmgmt_local_translation_access()
 * to allow access to a node.
 */
define('TMGMT_LOCAL_TRANSLATION_ACCESS_ALLOW', 'allow');

/**
 * Modules should return this value from hook_tmgmt_local_translation_access()
 * to deny access to a node.
 */
define('TMGMT_LOCAL_TRANSLATION_ACCESS_DENY', 'deny');

/**
 * Modules should return this value from hook_tmgmt_local_translation_access()
 * to not affect node access.
 */
define('TMGMT_LOCAL_TRANSLATION_ACCESS_IGNORE', NULL);

/**
 * Translation task is not assigned to translator.
 */
define('TMGMT_LOCAL_TASK_STATUS_UNASSIGNED', 0);

/**
 * Translation task is pending.
 */
define('TMGMT_LOCAL_TASK_STATUS_PENDING', 1);

/**
 * Translation task is completed (all job items are translated).
 */
define('TMGMT_LOCAL_TASK_STATUS_COMPLETED', 2);

/**
 * Translation task is rejected (at least some job items are rejected).
 */
define('TMGMT_LOCAL_TASK_STATUS_REJECTED', 3);

/**
 * Translation task is closed.
 */
define('TMGMT_LOCAL_TASK_STATUS_CLOSED', 4);

/**
 * Translation task item is untranslated.
 */
define('TMGMT_LOCAL_TASK_ITEM_STATUS_PENDING', 0);

/**
 * Translation task item is translated and pending review of the job item.
 */
define('TMGMT_LOCAL_TASK_ITEM_STATUS_COMPLETED', 1);

/**
 * Translation job item has been rejected and the task needs to be updated.
 */
define('TMGMT_LOCAL_TASK_ITEM_STATUS_REJECTED', 2);

/**
 * The translation task item has been completed and closed.
 */
define('TMGMT_LOCAL_TASK_ITEM_STATUS_CLOSED', 3);

/**
 * Untranslated translation data item.
 */
define('TMGMT_DATA_ITEM_STATE_UNTRANSLATED', 0);

/**
 * @} End of "tmgmt_local_task".
 */

/**
 * Implements hook_entity_info().
 */
function tmgmt_local_entity_info() {
  $info = array(
    'tmgmt_local_task' => array(
      'label' => t('Translation Task'),
      'module' => 'tmgmt_local',
      'entity class' => 'TMGMTLocalTask',
      'controller class' => 'TMGMTLocalTaskController',
      'metadata controller class' => 'TMGMTLocalTaskMetadataController',
      'views controller class' => 'TMGMTLocalTaskViewsController',
      'base table' => 'tmgmt_local_task',
      'uri callback' => 'entity_class_uri',
      'label callback' => 'entity_class_label',
      'access callback' => 'tmgmt_local_task_access',
      'entity keys' => array(
        'id' => 'tltid',
      ),
      'admin ui' => array(
        'controller class' => 'TMGMTLocalTaskUIController',
        'path' => 'translate',
      ),
    ),
    'tmgmt_local_task_item' => array(
      'label' => t('Translation Task Item'),
      'module' => 'tmgmt_local',
      'entity class' => 'TMGMTLocalTaskItem',
      'controller class' => 'TMGMTLocalTaskItemController',
      'metadata controller class' => 'TMGMTLocalTaskItemMetadataController',
      'views controller class' => 'TMGMTLocalTaskItemViewsController',
      'base table' => 'tmgmt_local_task_item',
      'uri callback' => 'entity_class_uri',
      'label callback' => 'entity_class_label',
      'access callback' => 'tmgmt_local_task_item_access',
      'entity keys' => array(
        'id' => 'tltiid',
      ),
      'admin ui' => array(
        'controller class' => 'TMGMTLocalTaskItemUIController',
        'path' => 'translate',
      ),
    ),
  );
  return $info;
}

/**
 * Implements hook_theme().
 */
function tmgmt_local_theme() {
  return array(
    'tmgmt_local_translation_form' => array(
      'render element' => 'element',
      'file' => 'includes/tmgmt_local.theme.inc',
    ),
    'tmgmt_local_translation_form_element' => array(
      'render element' => 'element',
      'file' => 'includes/tmgmt_local.theme.inc',
    ),
    // @todo - not implemented.
    'tmgmt_local_translation_form_element_status' => array(
      'render element' => 'status',
      'file' => 'includes/tmgmt_local.theme.inc',
    ),
  );
}

/**
 * Implements hook_menu().
 */
function tmgmt_local_menu() {
  $items['translate/%tmgmt_local_task/assign-to-me'] = array(
    'title' => 'Assign translation task to me',
    'description' => 'Assign translation task to current translator user.',
    'page callback' => 'tmgmt_local_translation_assign_to_me',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'tmgmt_local_translation_access',
    'access arguments' => array(
      1,
    ),
    'file' => 'includes/tmgmt_local.pages.inc',
  );
  $items['manage-translate/assign-tasks'] = array(
    'title' => 'Assign translation task',
    'description' => 'Assign translation tasks to specific translator.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'tmgmt_local_translation_assign_form',
      2,
    ),
    'access arguments' => array(
      'administer translation tasks',
    ),
    'file' => 'includes/tmgmt_local.pages.inc',
    'type' => MENU_CALLBACK,
  );
  $items['manage-translate/reassign-tasks'] = array(
    'title' => 'Reassign translation task',
    'description' => 'Ressign translation tasks to specific translator.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'tmgmt_local_translation_reassign_form',
      2,
    ),
    'access arguments' => array(
      'administer translation tasks',
    ),
    'file' => 'includes/tmgmt_local.pages.inc',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function tmgmt_local_permission() {
  return array(
    'provide translation services' => array(
      'title' => t('Provide translation services'),
      'descriptions' => t('Root permission for translation access: Users with this permission are eligible to be granted translation access to a translation task.'),
    ),
    'administer translation tasks' => array(
      'title' => t('Administer translation tasks'),
      'description' => t('Administer translation tasks.'),
    ),
  );
}

/**
 * Implements hook_views_api().
 */
function tmgmt_local_views_api() {
  return array(
    'api' => 3.0,
    'path' => drupal_get_path('module', 'tmgmt_local') . '/views',
  );
}

/**
 * Implements hook_default_views().
 */
function tmgmt_local_views_default_views() {
  return _tmgmt_load_exports('tmgmt_local', 'views', 'view.inc', 'view');
}

/**
 * Implements hook_tmgmt_translator_plugin_info().
 */
function tmgmt_local_tmgmt_translator_plugin_info() {
  $info['local'] = array(
    'label' => t('Local Translator'),
    'description' => t('Allows local users to process translation jobs.'),
    'plugin controller class' => 'TMGMTLocalTranslatorPluginController',
    'ui controller class' => 'TMGMTLocalTranslatorUIController',
    'map remote languages' => FALSE,
  );
  return $info;
}

/**
 * @addtogroup tmgmt_local
 * @{
 */

/**
 * Determine whether the current user is allowed to translate a given
 * translation task.
 *
 * @param $task
 *   The translation task to be translated.
 * @param $account
 *   (Optional) A user object representing the user that is trying to obtain
 *   translation access. Determines access for a user other than the current
 *   user.
 * @return bool
 *   TRUE if the user is allowed to translate the given translation job, FALSE
 *   otherwise.
 */
function tmgmt_local_translation_access(TMGMTLocalTask $task, $account = NULL) {
  $job = $task
    ->getJob();
  if (!$job || !$job
    ->isActive()) {
    return FALSE;
  }
  $rights =& drupal_static(__FUNCTION__);

  // If no user object is supplied, the access check is for the current user.
  if (empty($account)) {
    $account = $GLOBALS['user'];
  }

  // If we've already checked access for this job and user, return from cache.
  if (isset($rights[$account->uid][$job->tjid])) {
    return $rights[$account->uid][$job->tjid];
  }

  // We grant access to the translation if both of the following conditions are
  // met:
  // - User is assigned as a translator to the given task.
  // - User has 'provide translation services' permission.
  // - No modules say to deny access.
  // - At least one module says to grant access.
  // - User has translation capabilities for this task.
  if (!user_access('provide translation services')) {
    $rights[$account->uid][$job->tjid] = FALSE;
    return FALSE;
  }
  if ($task->tuid == $account->uid) {
    $rights[$account->uid][$job->tjid] = TRUE;
    return TRUE;
  }
  $access = module_invoke_all('tmgmt_local_translation_access', $job, $account);
  if (in_array(TMGMT_LOCAL_TRANSLATION_ACCESS_DENY, $access, TRUE)) {
    $rights[$account->uid][$job->tjid] = FALSE;
    return FALSE;
  }
  elseif (in_array(TMGMT_LOCAL_TRANSLATION_ACCESS_ALLOW, $access, TRUE)) {
    $rights[$account->uid][$job->tjid] = TRUE;
    return TRUE;
  }

  // Lastly, check for the translation capabilities.
  $target_languages = tmgmt_local_supported_target_languages($job->source_language, array(
    $account->uid,
  ));
  $rights[$account->uid][$job->tjid] = in_array($job->target_language, $target_languages);
  return $rights[$account->uid][$job->tjid];
}

/**
 * Helper function for clearing the languages cache of all local translators.
 *
 * Can be used in oder to clear the cache for supported target languages after
 * the translation capabilities of an local have changed.
 */
function tmgmt_local_clear_languages_cache() {
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'tmgmt_translator');
  $query
    ->propertyCondition('plugin', 'local');
  $result = $query
    ->execute();
  if ($result) {
    foreach (tmgmt_translator_load_multiple(array_keys($result['tmgmt_translator'])) as $translator) {
      $translator
        ->clearLanguageCache();
    }
  }
}

/**
 * Loads a local translation task entity.
 *
 * @return TMGMTLocalTask
 */
function tmgmt_local_task_load($tltid) {
  return entity_load_single('tmgmt_local_task', $tltid);
}

/**
 * Loads local translation tasks entity.
 */
function tmgmt_local_task_load_multiple(array $tltids = array(), $conditions = array()) {
  return entity_load('tmgmt_local_task', $tltids, $conditions);
}

/**
 * Loads a local translation task items entity.
 *
 * @return TMGMTLocalTaskItem
 */
function tmgmt_local_task_item_load($tltiid) {
  return entity_load_single('tmgmt_local_task_item', $tltiid);
}

/**
 * Loads local translation task items entity.
 */
function tmgmt_local_task_item_load_multiple(array $tltiids = array(), $conditions = array()) {
  return entity_load('tmgmt_local_task_item', $tltiids, $conditions);
}

/**
 * Creates a translation task entity.
 *
 * @param $values
 *   (Optional) An array of additional entity values.
 *
 * @return TMGMTLocalTask
 *   The local translation task entity.
 */
function tmgmt_local_task_create(array $values = array()) {
  return entity_create('tmgmt_local_task', $values);
}

/**
 * Deletes multiple local tasks entities.
 *
 * @param $tltids
 *   An array of local tasks IDs.
 */
function tmgmt_local_task_delete_multiple(array $tltids) {
  entity_get_controller('tmgmt_local_task')
    ->delete($tltids);
}

/**
 * Access callback for the local task entity.
 *
 * @param $op
 *   The operation being performed.
 * @param $item
 *   (Optional) A TMGMTLocalTask entity to check access for. If no entity is
 *   given, it will be determined whether access is allowed for all entities.
 * @param $account
 *   (Optional) The user to check for. Leave it to NULL to check for the global
 *   user.
 *
 * @return boolean
 *   TRUE if access is allowed, FALSE otherwise.
 */
function tmgmt_local_task_access($op, $task = NULL, $account = NULL) {
  if (user_access('administer tmgmt', $account) || user_access('administer translation tasks', $account)) {

    // Administrators can do everything.
    return TRUE;
  }
  if (!$account) {
    global $user;
    $account = $user;
  }

  // @todo - probably need refinement when we introduce more module permissions.
  switch ($op) {
    case 'view':
    case 'update':
      return user_access('provide translation services', $account);
      break;
    case 'unassign':
      return !empty($task->tuid) && $task->tuid == $account->uid && user_access('provide translation services', $account);
  }
}

/**
 * Access callback for the local task item entity.
 *
 * @param $op
 *   The operation being performed.
 * @param $item
 *   (Optional) A TMGMTLocalTaskItem entity to check access for. If no entity is
 *   given, it will be determined whether access is allowed for all entities.
 * @param $account
 *   (Optional) The user to check for. Leave it to NULL to check for the global
 *   user.
 *
 * @return boolean
 *   TRUE if access is allowed, FALSE otherwise.
 */
function tmgmt_local_task_item_access($op, TMGMTLocalTaskItem $item = NULL, $account = NULL) {
  $task = NULL;
  if ($item) {
    $task = $item
      ->getTask();
  }
  return entity_access($op, 'tmgmt_local_task', $task, $account);
}

/**
 * Loads an array with the word and status statistics of a task.
 *
 * @param $tltids
 *   An array of local task ids.
 *
 * @return
 *   An array of objects with the keys word_count, count_pending,
 *   count_accepted, count_translated and loop_count.
 */
function tmgmt_local_task_statistics_load(array $tltids) {
  $statistics =& drupal_static(__FUNCTION__, array());

  // First try to get the values from the cache.
  $return = array();
  $tltids_to_load = array();
  foreach ($tltids as $tltid) {
    if (isset($statistics[$tltid])) {

      // Info exists in cache, get it from there.
      $return[$tltid] = $statistics[$tltid];
    }
    else {

      // Info doesn't exist in cache, add job to the list that needs to be
      // fetched.
      $tltids_to_load[] = $tltid;
    }
  }

  // If there are remaining jobs, build a query to fetch them.
  if (!empty($tltids_to_load)) {

    // Build the query to fetch the statistics.
    $query = db_select('tmgmt_local_task_item', 'tlti');
    $query
      ->join('tmgmt_local_task', 'tlt', 'tlt.tltid = tlti.tltid');
    $query
      ->join('tmgmt_job_item', 'tji', 'tji.tjiid = tlti.tjiid');
    $query
      ->fields('tlt', array(
      'tltid',
    ));
    $query
      ->addExpression('SUM(tji.word_count)', 'word_count');
    $query
      ->addExpression('SUM(tlti.count_untranslated)', 'count_untranslated');
    $query
      ->addExpression('SUM(tlti.count_translated)', 'count_translated');
    $query
      ->addExpression('SUM(tlti.count_completed)', 'count_completed');
    $result = $query
      ->groupBy('tlt.tltid')
      ->condition('tlt.tltid', $tltids_to_load)
      ->execute();
    foreach ($result as $row) {
      $return[$row->tltid] = $statistics[$row->tltid] = $row;
    }
  }
  return $return;
}

/**
 * Returns a specific statistic of a task.
 *
 * @param $task
 *   The translation task entity.
 * @param $key
 *   One of word_count, loop_count, count_pending, count_accepted and
 *   count_translated.
 *
 * @return
 *   The requested information as an integer.
 */
function tmgmt_local_task_statistic(TMGMTLocalTask $task, $key) {
  $statistics = tmgmt_local_task_statistics_load(array(
    $task->tltid,
  ));
  if (isset($statistics[$task->tltid]->{$key})) {
    return $statistics[$task->tltid]->{$key};
  }
  return 0;
}

/**
 * Retrieve a labeled list of all available statuses.
 *
 * @return array
 *   A list of all available statuses.
 */
function tmgmt_local_task_statuses() {
  return $statuses = array(
    TMGMT_LOCAL_TASK_STATUS_UNASSIGNED => t('Unassigned'),
    TMGMT_LOCAL_TASK_STATUS_PENDING => t('Pending'),
    TMGMT_LOCAL_TASK_STATUS_COMPLETED => t('Completed'),
    TMGMT_LOCAL_TASK_STATUS_REJECTED => t('Rejected'),
    TMGMT_LOCAL_TASK_STATUS_CLOSED => t('Closed'),
  );
}

/**
 * Retrieve a labeled list of all available statuses for task items.
 *
 * @return array
 *   A list of all available statuses.
 */
function tmgmt_local_task_item_statuses() {
  return $statuses = array(
    TMGMT_LOCAL_TASK_ITEM_STATUS_PENDING => t('Untranslated'),
    TMGMT_LOCAL_TASK_ITEM_STATUS_COMPLETED => t('Translated'),
    TMGMT_LOCAL_TASK_ITEM_STATUS_REJECTED => t('Rejected'),
    TMGMT_LOCAL_TASK_ITEM_STATUS_CLOSED => t('Completed'),
  );
}

/**
 * Gets all involved language pairs for given tasks.
 *
 * @param array $tasks
 *   Array of tasks ids.
 *
 * @return array
 *   Array of involved languages.
 */
function tmgmt_local_tasks_languages($tasks) {
  $query = db_select('tmgmt_local_task', 't');
  $query
    ->condition('tltid', $tasks);
  $query
    ->join('tmgmt_job', 'j', 't.tjid = j.tjid');
  $query
    ->fields('j', array(
    'source_language',
    'target_language',
  ));
  $query
    ->groupBy('target_language');
  $result = $query
    ->execute();
  $languages = array();
  foreach ($result as $row) {
    if (empty($languages[$row->source_language]) || !in_array($row->target_language, $languages[$row->source_language])) {
      $languages[$row->source_language][] = $row->target_language;
    }
  }
  return $languages;
}

/**
 * Gets translators able to translate all given tasks.
 *
 * @param array $tasks
 *   Array of tasks ids.
 *
 * @return array
 *   List of uid => name values.
 */
function tmgmt_local_get_translators_for_tasks($tasks) {
  $translators = array();
  foreach (tmgmt_local_tasks_languages($tasks) as $source_language => $target_languages) {
    $translators[] = tmgmt_local_translators($source_language, $target_languages);
  }
  if (count($translators) > 1) {
    return call_user_func_array('array_intersect', $translators);
  }
  elseif (count($translators) == 1) {
    return array_shift($translators);
  }
  return array();
}

/**
 * @} End of "addtogroup tmgmt_local_task".
 */

/**
 * Implements hook_tmgmt_job_item_update().
 *
 * @todo: Move this to the translator plugin API.
 */
function tmgmt_local_tmgmt_job_item_update(TMGMTJobItem $job_item) {
  if ($job_item
    ->isAccepted() && !$job_item->original
    ->isAccepted()) {
    $tltiid = db_query('SELECT tltiid FROM {tmgmt_local_task_item} ti INNER JOIN {tmgmt_local_task} t ON ti.tltid = t.tltid WHERE t.tjid = :tjid AND ti.tjiid = :tjiid', array(
      ':tjid' => $job_item->tjid,
      ':tjiid' => $job_item->tjiid,
    ))
      ->fetchField();
    if ($tltiid) {
      $task_item = tmgmt_local_task_item_load($tltiid);
      $task_item
        ->closed();
      $task_item
        ->save();

      // Check if the task can be marked as closed as well.
      $query = new EntityFieldQuery();
      $unclosed_tasks = $query
        ->entityCondition('entity_type', 'tmgmt_local_task_item')
        ->propertyCondition('tltid', $task_item->tltid)
        ->propertyCondition('status', TMGMT_LOCAL_TASK_ITEM_STATUS_CLOSED, '<>')
        ->count()
        ->execute();
      if ($unclosed_tasks == 0) {
        $task = $task_item
          ->getTask();
        $task
          ->setStatus(TMGMT_LOCAL_TASK_STATUS_CLOSED);
        $task
          ->save();
      }
    }
  }
}

/**
 * Implements hook_tmgmt_job_delete().
 */
function tmgmt_local_tmgmt_job_delete(TMGMTJob $job) {
  $query = new EntityFieldQuery();
  $result = $query
    ->entityCondition('entity_type', 'tmgmt_local_task')
    ->propertyCondition('tjid', $job->tjid)
    ->execute();
  if (!empty($result['tmgmt_local_task'])) {
    entity_delete_multiple('tmgmt_local_task', array_keys($result['tmgmt_local_task']));
  }
}

/**
 * Implements hook_field_access().
 */
function tmgmt_local_field_access($op, $field, $entity_type, $entity = NULL, $account = NULL) {
  if ($field['field_name'] == 'tmgmt_translation_skills' && $entity_type == 'user') {
    $account = !empty($account) ? $account : $GLOBALS['user'];

    // If the field is just being viewed, grant access.
    if ($op == 'view') {
      return TRUE;
    }

    // User can provide transl. services and is dealing with own account.
    if (!empty($entity) && $entity->uid == $account->uid) {
      return user_access('provide translation services', $entity);
    }

    // Administrators are allowed to deal with others only.
    if (user_access('administer tmgmt', $account)) {
      return TRUE;
    }
    return FALSE;
  }
}

/**
 * Implements hook_field_attach_insert().
 */
function tmgmt_local_field_attach_insert($entity_type, $entity) {
  if ($entity_type != 'user' || !array_intersect_key(user_roles(TRUE, 'provide translation services'), $entity->roles)) {
    return;
  }
  tmgmt_local_clear_languages_cache();
}

/**
 * Implements hook_field_attach_update().
 */
function tmgmt_local_field_attach_update($entity_type, $entity) {
  if ($entity_type != 'user' || !array_intersect_key(user_roles(TRUE, 'provide translation services'), $entity->roles)) {
    return;
  }
  tmgmt_local_clear_languages_cache();
}

/**
 * Implements hook_field_attach_delete().
 */
function tmgmt_local_field_attach_delete($entity_type, $entity) {
  if ($entity_type != 'user' || !array_intersect_key(user_roles(TRUE, 'provide translation services'), $entity->roles)) {
    return;
  }
  tmgmt_local_clear_languages_cache();
}

/**
 * Gets list of language pairs.
 *
 * @param string $source_language
 *   Source language code for which to limit the selection.
 * @param array $uids
 *   List of user ids for whom to get the language pairs.
 *
 * @return array
 *   List of language pairs where a pair is defined by associative array of
 *   source_language and target_language keys.
 */
function tmgmt_local_supported_language_pairs($source_language = NULL, $uids = array()) {
  $language_pairs =& drupal_static(__FUNCTION__);
  $cache_key = $source_language . '_' . implode('_', $uids);
  if (isset($language_pairs[$cache_key])) {
    return $language_pairs[$cache_key];
  }
  $language_pairs[$cache_key] = array();
  foreach (tmgmt_local_capabilities($source_language, NULL, $uids) as $row) {

    // Prevent duplicates.
    $pair_key = $row->tmgmt_translation_skills_language_from . '__' . $row->tmgmt_translation_skills_language_to;
    $language_pairs[$cache_key][$pair_key] = array(
      'source_language' => $row->tmgmt_translation_skills_language_from,
      'target_language' => $row->tmgmt_translation_skills_language_to,
    );
  }
  return $language_pairs[$cache_key];
}

/**
 * Gets supported target languages.
 *
 * @param string $source_language
 *   Source language for which to get target languages.
 * @param array $uids
 *   List of user ids for whom to get the target languages.
 *
 * @return array
 *   List of target languages where code is the key as well as the value.
 */
function tmgmt_local_supported_target_languages($source_language, $uids = array()) {
  $pairs = tmgmt_local_supported_language_pairs($source_language, $uids);
  $supported_languages = array();
  foreach ($pairs as $pair) {
    $supported_languages[$pair['target_language']] = $pair['target_language'];
  }
  return $supported_languages;
}

/**
 * Gets local translator for given language combination.
 *
 * @param string $source_language
 *   (optional) Source language to limit on.
 * @param array $target_languages
 *   (optional) List of target languages to limit to.
 *
 * @return array
 *   Array of uid => name translators or empty array if there are no translator
 *   users.
 */
function tmgmt_local_translators($source_language = NULL, array $target_languages = array()) {
  $translators =& drupal_static(__FUNCTION__);
  $key = $source_language . '_' . implode('_', $target_languages);
  if (isset($translators[$key])) {
    return $translators[$key];
  }

  // Get all capabilities keyed by uids for given source language.
  $translators_capabilities = array();
  foreach (tmgmt_local_capabilities($source_language) as $row) {
    $translators_capabilities[$row->uid][] = $row->tmgmt_translation_skills_language_to;
  }

  // Filter out translator uids who's capabilities are not sufficient for given
  // target languages.
  $translators_uids = array();
  foreach ($translators_capabilities as $uid => $translator_capabilities) {

    // In case provided target languages exceed users capabilities exclude.
    if (!empty($target_languages) && count(array_diff($target_languages, $translator_capabilities)) > 0) {
      continue;
    }
    $translators_uids[] = $uid;
  }

  // Finally build the translators list.
  $translators[$key] = array();
  if (!empty($translators_uids)) {
    foreach (user_load_multiple($translators_uids) as $account) {
      $translators[$key][$account->uid] = entity_label('user', $account);
    }
  }
  return $translators[$key];
}

/**
 * Gets language capabilities.
 *
 * @param string $source_language
 *   (optional) Limit the source language.
 * @param string $target_language
 *   (optional) Limit the target language.
 * @param array $uids
 *   (optional) Limit to specific users.
 *
 * @return array
 *   Array of language capabilities with following data:
 *   - tmgmt_translation_skills_language_from
 *   - tmgmt_translation_skills_language_to
 *   - uid
 *   - name
 *   - mail
 */
function tmgmt_local_capabilities($source_language = NULL, $target_language = NULL, $uids = array()) {
  $roles = tmgmt_local_translator_roles();

  // If there are no roles that have the required permission, return an empty
  // array.
  if (empty($roles)) {
    return array();
  }
  $query = db_select('field_data_tmgmt_translation_skills', 'ts')
    ->fields('ts', array(
    'tmgmt_translation_skills_language_from',
    'tmgmt_translation_skills_language_to',
  ))
    ->condition('ts.deleted', 0)
    ->condition('ts.entity_type', 'user');
  if ($source_language) {
    $query
      ->condition('ts.tmgmt_translation_skills_language_from', $source_language);
  }
  if ($target_language) {
    $query
      ->condition('ts.tmgmt_translation_skills_language_to', $target_language);
  }

  // Join only active users.
  $query
    ->innerJoin('users', 'u', 'u.uid = ts.entity_id AND u.status = 1');
  $query
    ->fields('u', array(
    'uid',
    'name',
    'mail',
  ));
  if (!empty($uids)) {
    $query
      ->condition('u.uid', $uids);
  }

  // If the authenticated user role has the required permission we do not have
  // to do the role check.
  if (!in_array('authenticated user', $roles)) {
    $query
      ->leftJoin('users_roles', 'ur', "ur.uid = u.uid AND ur.rid IN (:roles)", array(
      ':roles' => array_keys($roles),
    ));
  }

  // Add a tag so other modules can alter this query at will.
  $query
    ->addTag('tmgmt_translation_combination');
  return $query
    ->execute()
    ->fetchAll();
}

/**
 * Get roles with 'provide translation services' permissions.
 *
 * @return array
 *   An associative array with the role id as the key and the role name as
 *   value.
 */
function tmgmt_local_translator_roles() {
  return user_roles(TRUE, 'provide translation services');
}

/**
 * Implements hook_rules_action_info_alter().
 */
function tmgmt_local_rules_action_info_alter(&$actions) {
  if (isset($actions['component_rules_tmgmt_local_task_assign_to_me'])) {
    $actions['component_rules_tmgmt_local_task_assign_to_me']['access callback'] = 'tmgmt_local_rules_component_access';
  }
  if (isset($actions['component_rules_tmgmt_local_task_assign'])) {
    $actions['component_rules_tmgmt_local_task_assign']['access callback'] = 'tmgmt_local_rules_component_access';
  }
}

/**
 * Access callback to translation tasks rules component actions.
 */
function tmgmt_local_rules_component_access($type, $name) {
  switch ($name) {
    case 'component_rules_tmgmt_local_task_assign_to_me':
      return user_access('provide translation services');
    case 'component_rules_tmgmt_local_task_assign':
      return user_access('administer translation tasks');
  }
}

Functions

Namesort descending Description
tmgmt_local_capabilities Gets language capabilities.
tmgmt_local_clear_languages_cache Helper function for clearing the languages cache of all local translators.
tmgmt_local_entity_info Implements hook_entity_info().
tmgmt_local_field_access Implements hook_field_access().
tmgmt_local_field_attach_delete Implements hook_field_attach_delete().
tmgmt_local_field_attach_insert Implements hook_field_attach_insert().
tmgmt_local_field_attach_update Implements hook_field_attach_update().
tmgmt_local_get_translators_for_tasks Gets translators able to translate all given tasks.
tmgmt_local_menu Implements hook_menu().
tmgmt_local_permission Implements hook_permission().
tmgmt_local_rules_action_info_alter Implements hook_rules_action_info_alter().
tmgmt_local_rules_component_access Access callback to translation tasks rules component actions.
tmgmt_local_supported_language_pairs Gets list of language pairs.
tmgmt_local_supported_target_languages Gets supported target languages.
tmgmt_local_tasks_languages Gets all involved language pairs for given tasks.
tmgmt_local_task_access Access callback for the local task entity.
tmgmt_local_task_create Creates a translation task entity.
tmgmt_local_task_delete_multiple Deletes multiple local tasks entities.
tmgmt_local_task_item_access Access callback for the local task item entity.
tmgmt_local_task_item_load Loads a local translation task items entity.
tmgmt_local_task_item_load_multiple Loads local translation task items entity.
tmgmt_local_task_item_statuses Retrieve a labeled list of all available statuses for task items.
tmgmt_local_task_load Loads a local translation task entity.
tmgmt_local_task_load_multiple Loads local translation tasks entity.
tmgmt_local_task_statistic Returns a specific statistic of a task.
tmgmt_local_task_statistics_load Loads an array with the word and status statistics of a task.
tmgmt_local_task_statuses Retrieve a labeled list of all available statuses.
tmgmt_local_theme Implements hook_theme().
tmgmt_local_tmgmt_job_delete Implements hook_tmgmt_job_delete().
tmgmt_local_tmgmt_job_item_update Implements hook_tmgmt_job_item_update().
tmgmt_local_tmgmt_translator_plugin_info Implements hook_tmgmt_translator_plugin_info().
tmgmt_local_translation_access Determine whether the current user is allowed to translate a given translation task.
tmgmt_local_translators Gets local translator for given language combination.
tmgmt_local_translator_roles Get roles with 'provide translation services' permissions.
tmgmt_local_views_api Implements hook_views_api().
tmgmt_local_views_default_views Implements hook_default_views().

Constants

Namesort descending Description
TMGMT_DATA_ITEM_STATE_UNTRANSLATED Untranslated translation data item.
TMGMT_LOCAL_TASK_ITEM_STATUS_CLOSED The translation task item has been completed and closed.
TMGMT_LOCAL_TASK_ITEM_STATUS_COMPLETED Translation task item is translated and pending review of the job item.
TMGMT_LOCAL_TASK_ITEM_STATUS_PENDING Translation task item is untranslated.
TMGMT_LOCAL_TASK_ITEM_STATUS_REJECTED Translation job item has been rejected and the task needs to be updated.
TMGMT_LOCAL_TASK_STATUS_CLOSED Translation task is closed.
TMGMT_LOCAL_TASK_STATUS_COMPLETED Translation task is completed (all job items are translated).
TMGMT_LOCAL_TASK_STATUS_PENDING Translation task is pending.
TMGMT_LOCAL_TASK_STATUS_REJECTED Translation task is rejected (at least some job items are rejected).
TMGMT_LOCAL_TASK_STATUS_UNASSIGNED Translation task is not assigned to translator.
TMGMT_LOCAL_TRANSLATION_ACCESS_ALLOW Modules should return this value from hook_tmgmt_local_translation_access() to allow access to a node.
TMGMT_LOCAL_TRANSLATION_ACCESS_DENY Modules should return this value from hook_tmgmt_local_translation_access() to deny access to a node.
TMGMT_LOCAL_TRANSLATION_ACCESS_IGNORE Modules should return this value from hook_tmgmt_local_translation_access() to not affect node access.