diff --git a/i18n_forum/i18n_forum.info b/i18n_forum/i18n_forum.info index a42d8f6..2825a84 100644 --- a/i18n_forum/i18n_forum.info +++ b/i18n_forum/i18n_forum.info @@ -5,4 +5,4 @@ dependencies[] = i18n_taxonomy dependencies[] = i18n_node package = Multilingual - Internationalization core = 7.x - +files[] = i18n_forum.test diff --git a/i18n_forum/i18n_forum.test b/i18n_forum/i18n_forum.test new file mode 100644 index 0000000..717162f --- /dev/null +++ b/i18n_forum/i18n_forum.test @@ -0,0 +1,26 @@ + 'Multilingual forum', + 'group' => 'Internationalization', + 'description' => 'Tests multilingual forum', + ); + } + + public function setUp() { + parent::setUp('translation', 'i18n_select', 'i18n_forum'); + parent::setUpLanguages(); + parent::setUpContentTranslation(); + } + + /** + * Tests i18n_select integration. + */ + public function testI18nSelectTest() { + // @TODO: improve test. its just a quick test against the PDO exception + // @see http://drupal.org/node/1437932 + $this->i18nGet($this->default_language, 'forum'); + } +} \ No newline at end of file diff --git a/i18n_select/i18n_select.module b/i18n_select/i18n_select.module index 66d187f..54a9527 100644 --- a/i18n_select/i18n_select.module +++ b/i18n_select/i18n_select.module @@ -2,9 +2,9 @@ /** * @file * Multilingual content selection module. - * + * * Alters content queries to add language conditions. - * + * * Queries tagged with 'i18n_select' or that already have a language condition will not be altered. */ @@ -33,7 +33,7 @@ define('I18N_SELECT_PAGE_PHP', 2); */ function i18n_select_init() { // Determine selection mode for this page - i18n_select(i18n_select_page()); + i18n_select(i18n_select_page()); } /** @@ -42,7 +42,7 @@ function i18n_select_init() { * Dirty trick to enable selection for blocks though it may be disabled for the current page. */ function i18n_select_block_list_alter(&$blocks) { - // Still, skip for form submission. There are pages like the ones produced + // Still, skip for form submission. There are pages like the ones produced // by overlay that render the blocks before the page. // See overlay_init(), overlay_overlay_child_initialize() if (empty($_POST) && !isset($_GET['token']) && variable_get('i18n_select_page_block', TRUE)) { @@ -62,13 +62,13 @@ function i18n_select_menu() { '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.. */ @@ -83,15 +83,15 @@ function i18n_select_mode($type = NULL) { /** * Check current path to enable selection - * + * * This works pretty much like block visibility - * + * * @return boolean * TRUE if content selection should be enabled for this page. */ function i18n_select_page() { static $mode; - + if (!isset($mode)) { $mode = &drupal_static(__FUNCTION__); $visibility = variable_get('i18n_select_page_mode', I18N_SELECT_PAGE_NOTLISTED); @@ -135,38 +135,22 @@ function i18n_select_page() { * 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', 'nid')) && 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 (i18n_select_mode('nodes') && i18n_select_check_query($query) && + ($table_alias = i18n_select_check_table($query, 'node', 'nid'))) { $query->condition($table_alias . '.language', i18n_select_langcodes()); // Mark query as altered $query->addTag('i18n_select'); } - - // Rewrite pager for taxonomy term pages. - if ($mode && ($table_alias = i18n_select_check_table($query, 'taxonomy_index', 'tid')) && i18n_select_check_query($query, $table_alias)) { - $query->join('node', 'n', 't.nid = n.nid'); - $query->condition('n.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', 'tid')) && i18n_select_check_query($query, $table_alias)) { + if (module_exists('i18n_taxonomy') && i18n_select_mode('taxonomy') && i18n_select_check_query($query) && + ($table_alias = i18n_select_check_table($query, 'taxonomy_term_data', 'tid'))) { $query->condition($table_alias . '.language', i18n_select_langcodes()); // Mark query as altered $query->addTag('i18n_select'); @@ -176,44 +160,92 @@ function i18n_select_query_term_access_alter(QueryAlterableInterface $query) { /** * Check table exists in query and get alias for it. * - * If is not there, try to join it based on $field_name. + * @param $query + * Query object + * @param $table_name + * Table name to find. + * @param $field_name + * field to join the table if needed. + * + * @return + * Table alias if found, none if not. */ function i18n_select_check_table($query, $table_name, $field_name) { - foreach ($query->getTables() as $table) { + $tables = $query->getTables(); + foreach ($tables as $table) { if (!($table instanceof SelectQueryInterface) && $table['table'] == $table_name) { - return !empty($table['alias']) ? $table['alias'] : $table_name; + return _i18n_select_table_alias($table); } } - - // If node table doesn't exist, look for the nid column, join with node - // and then return the alias of that. - foreach ($query->getFields() as $field) { - if ($field['field'] == $field_name) { - return $query->join('node', 'node', $field['table'] . '.' . $field_name . ' = %alias.' . $field['field']); + // Join the table if we can find the key field on any of the tables + // And all the conditions have a table alias (or there's a unique table). + if (count($tables) == 1) { + $table = reset($tables); + $table_alias = _i18n_select_table_alias($table); + if (i18n_select_check_conditions($query, $table_alias)) { + $join_table = $table_alias; + } + } + elseif (i18n_select_check_conditions($query)) { + // Try to find the right field in the table schema. + foreach ($tables as $table) { + $schema = drupal_get_schema($table['table']); + if ($schema && !empty($schema['fields'][$field_name])) { + $join_table = _i18n_select_table_alias($table); + break; + } } } + if (!empty($join_table)) { + return $query->join($table_name, $table_name, $join_table . '.' . $field_name . ' = %alias.' . $field_name); + } + else { + return FALSE; + } } /** - * Check all query conditions have a table alias + * Get table alias */ -function i18n_select_check_conditions($query, $table_alias) { +function _i18n_select_table_alias($table) { + return !empty($table['alias']) ? $table['alias'] : $table['table']; +} + +/** + * Check all query conditions have a table alias. + * + * @param $table_alias + * Optional table alias for fields without table. + * + * @return boolean + * TRUE if table conditions are ok, FALSE otherwise. + */ +function i18n_select_check_conditions($query, $table_alias = NULL) { $conditions =& $query->conditions(); foreach ($conditions as $index => $condition) { - if (is_array($condition) && isset($condition['field']) && is_string($condition['field'])) { + if (is_array($condition) && isset($condition['field'])) { if (strpos($condition['field'], '.') === FALSE) { - $conditions[$index]['field'] = $table_alias . '.' . $condition['field']; + if ($table_alias) { + // Change the condition to include a table alias. + $conditions[$index]['field'] = $table_alias . '.' . $condition['field']; + } + else { + // We won't risk joining anything here. + return FALSE; + } } } } + return TRUE; } /** * 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 + * - All the conditions have a table alias or there's only one table. */ -function i18n_select_check_query($query, $table_alias, $field_name = 'language') { +function i18n_select_check_query($query) { static $tags; // Skip queries with certain tags if (!isset($tags)) { @@ -225,14 +257,34 @@ function i18n_select_check_query($query, $table_alias, $field_name = 'language') return FALSE; } } - $fields = $query->getFields(); - $table_field = $table_alias . '.' . $field_name; + // Check all the conditions to see whether the query is suitable for altering. 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; + if (is_array($condition)) { + // @todo Research under which conditions field is not string, see http://drupal.org/node/1062054 + if (!isset($condition['field']) && !is_string($condition['field'])) { + // There's a weird condition field, we won't take any chances. + return FALSE; + } + else { + // Just check the condition doesn't include the language field + if (strpos($condition['field'], '.') === FALSE) { + $field = $condition['field']; + } + else { + list($table, $field) = explode('.', $condition['field']); + } + if ($field == 'language') { + return FALSE; + } + } } } + // if the language field is present we don't want to do any filtering. + $fields = $query->getFields(); + if (isset($fields['language'])) { + return FALSE; + } + return TRUE; }