'Selection', 'description' => 'Configure extended options for multilingual content and translations.', 'page callback' => 'drupal_get_form', 'page arguments' => array('i18n_select_admin_settings'), 'access arguments' => array('administer site configuration'), 'file' => 'i18n_select.admin.inc', 'type' => MENU_LOCAL_TASK, ); return $items; } /** * Get current mode for i18n selection * * @param $type * Selection type: 'nodes', 'taxonomy', etc.. */ function i18n_select_mode($type = NULL) { if (i18n_select() && (!$type || variable_get('i18n_select_' . $type, TRUE))) { return variable_get('i18n_select_missing_translation', FALSE) ? I18N_SELECT_MISSING : I18N_SELECT_NORMAL; } else { return I18N_SELECT_NONE; } } /** * Check current path to enable selection * * This works pretty much like block visibility */ function i18n_select_page() { $visibility = variable_get('i18n_select_page_mode', I18N_SELECT_PAGE_NOTLISTED); if ($pages = variable_get('i18n_select_page_list', 'admin/*')) { // Convert path to lowercase. This allows comparison of the same path // with different case. Ex: /Page, /page, /PAGE. $pages = drupal_strtolower($pages); if ($visibility < I18N_SELECT_PAGE_PHP) { // Convert the Drupal path to lowercase $path = drupal_strtolower(drupal_get_path_alias($_GET['q'])); // Compare the lowercase internal and lowercase path alias (if any). $page_match = drupal_match_path($path, $pages); if ($path != $_GET['q']) { $page_match = $page_match || drupal_match_path($_GET['q'], $pages); } // When $visibility has a value of 0 (I18N_SELECT_PAGE_NOTLISTED), // the block is displayed on all pages except those listed in $pages. // When set to 1 (I18N_SELECT_PAGE_LISTED), it is displayed only on those // pages listed in $pages. return !($visibility xor $page_match); } elseif (module_exists('php')) { return php_eval($pages); } else { return FALSE; } } else { // No pages defined, still respect the setting (unlike blocks) return $visibility == I18N_SELECT_PAGE_NOTLISTED; } } /** * Implementation of hook_query_node_access_alter(). * * Rewrite node queries so language selection options are enforced. */ function i18n_select_query_node_access_alter(QueryAlterableInterface $query) { $mode = i18n_select_mode('nodes'); if ($mode && ($table_alias = i18n_select_check_table($query, 'node')) && i18n_select_check_query($query, $table_alias)) { // if the language field is present we don't want to do any filtering. $fields = $query->getFields(); if (isset($fields['language'])) { return; } $language = i18n_select_language(); $default_lang = language_default('language'); if (($mode & I18N_SELECT_MISSING) && $language != $default_lang) { // we want to include nodes from the default language that haven't been // translated to the current language // SELECT * FROM node n // LEFT JOIN node i18n ON n.tnid > 0 AND n.tnid = i18n.tnid AND i18n.language = 'es' // WHERE n.language='es' OR (n.language='en' AND i18n.nid IS NULL) // Make sure the conditions refer to the node table. eg using 'n.promote' instead of 'promote' i18n_select_check_conditions($query, $table_alias); $query->leftjoin('node', 'i18n', $table_alias . '.tnid > 0 AND ' . $table_alias . '.tnid = i18n.tnid AND i18n.language = :lang', array(':lang' => $language)); $query->where($table_alias . '.language=:lang OR (' . $table_alias . '.language=:default_lang AND i18n.nid IS NULL)', array(':lang' => $language, ':default_lang' => $default_lang)); } else { $query->condition($table_alias . '.language', i18n_select_langcodes()); } // Mark query as altered $query->addTag('i18n_select'); } } /** * Implementation of hook_query_term_access_alter(). * * Rewrite taxonomy term queries so language selection options are enforced. */ function i18n_select_query_term_access_alter(QueryAlterableInterface $query) { $mode = i18n_select_mode('taxonomy'); if (module_exists('i18n_taxonomy') && $mode && ($table_alias = i18n_select_check_table($query, 'taxonomy_term_data')) && i18n_select_check_query($query, $table_alias)) { $query->condition($table_alias . '.language', i18n_select_langcodes()); // Mark query as altered $query->addTag('i18n_select'); } } /** * Check table exists in query and get alias for it * * @todo Should we add the table if not there? */ function i18n_select_check_table($query, $table_name) { foreach ($query->getTables() as $table) { if ($table['table'] == $table_name) { return !empty($table['alias']) ? $table['alias'] : $table_name; } } } /** * Check all query conditions have a table alias */ function i18n_select_check_conditions($query, $table_alias) { $conditions =& $query->conditions(); foreach ($conditions as $index => $condition) { if (is_array($condition) && isset($condition['field'])) { if (strpos($condition['field'], '.') === FALSE) { $conditions[$index]['field'] = $table_alias . '.' . $condition['field']; } } } } /** * Check whether we should apply language conditions here: * - The query has not been tagged with 'i18n_select' * - The query doesn't have already a language condition */ function i18n_select_check_query($query, $table_alias, $field_name = 'language') { static $tags; // Skip queries with certain tags if (!isset($tags)) { $tags = ($skip = variable_get('i18n_select_skip_tags', 'views')) ? array_map('trim', explode(',', $skip)) : array(); $tags[] = 'i18n_select'; } foreach ($tags as $tag) { if ($query->hasTag($tag)) { return FALSE; } } $fields = $query->getFields(); $table_field = $table_alias . '.' . $field_name; foreach ($query->conditions() as $condition) { // @todo Research under which conditions field is not string, see http://drupal.org/node/1062054 if (is_array($condition) && isset($condition['field']) && is_string($condition['field']) && ($condition['field'] == $field_name || $condition['field'] == $table_field)) { return FALSE; } } return TRUE; } /** * Get main language code for content selection */ function i18n_select_language() { return $GLOBALS['language_content']->language; } /** * Get language codes for content selection to use in query conditions */ function i18n_select_langcodes() { return array(i18n_select_language(), LANGUAGE_NONE); }