Loading includes/handlers.inc +28 −49 Original line number Diff line number Diff line Loading @@ -996,24 +996,24 @@ class views_many_to_one_helper { return $this->handler->table_alias; } // Case 2: it's an 'and' or an 'or'. // Case 2: it's anything but an 'or'. // We do one join per selected value. if ($this->handler->operator != 'not') { // Clone the join for each table. $this->handler->table_aliases = array(); // Clone the join for each table: $this->handler->table_aliases = []; foreach ($this->handler->value as $value) { $join = $this->get_join(); if ($this->handler->operator == 'and') { $join->type = 'INNER'; } $join->extra = array( array( if (empty($join->extra)) { $join->extra = []; } $join->extra[] = [ 'field' => $this->handler->real_field, 'value' => $value, 'numeric' => !empty($this->handler->definition['numeric']), ), ); ]; // The table alias needs to be unique to this value across the // multiple times the filter or argument is called by the view. if (!isset($this->handler->view->many_to_one_aliases[$field][$value])) { Loading @@ -1021,33 +1021,14 @@ class views_many_to_one_helper { $this->handler->view->many_to_one_count[$this->handler->table] = 0; } $this->handler->view->many_to_one_aliases[$field][$value] = $this->handler->table . '_value_' . ($this->handler->view->many_to_one_count[$this->handler->table]++); } $alias = $this->handler->table_aliases[$value] = $this->add_table($join, $this->handler->view->many_to_one_aliases[$field][$value]); $alias = $this->handler->table_aliases[$value] = $this->add_table($join, $this->handler->view->many_to_one_aliases[$field][$value]); // and set table_alias to the first of these. if (empty($this->handler->table_alias)) { $this->handler->table_alias = $alias; } } } // Case 3: it's a 'not'. // We just do one join. We'll add a where clause during the query phase // to ensure that $table.$field IS NULL. else { $join = $this->get_join(); $join->type = 'LEFT'; $join->extra = array(); $join->extra_type = 'OR'; foreach ($this->handler->value as $value) { $join->extra[] = array( 'field' => $this->handler->real_field, 'value' => $value, 'numeric' => !empty($this->handler->definition['numeric']), ); } $this->handler->table_alias = $this->add_table($join); } } return $this->handler->table_alias; } Loading Loading @@ -1081,12 +1062,7 @@ class views_many_to_one_helper { // Determine whether a single expression is enough(FALSE) or the conditions // should be added via an db_or()/db_and() (TRUE). $add_condition = TRUE; if ($operator == 'not') { $value = NULL; $operator = 'IS NULL'; $add_condition = FALSE; } elseif ($operator == 'or' && empty($options['reduce_duplicates'])) { if ($operator == 'or' && empty($options['reduce_duplicates'])) { if (count($value) > 1) { $operator = 'IN'; } Loading Loading @@ -1120,6 +1096,9 @@ class views_many_to_one_helper { $field = $this->handler->real_field; $clause = $operator == 'or' ? db_or() : db_and(); foreach ($this->handler->table_aliases as $value => $alias) { if ($operator == 'not') { $value = NULL; } $clause->condition("$alias.$field", $value); } Loading tests/views_handler_filter.test 0 → 100644 +161 −0 Original line number Diff line number Diff line <?php /** * @file * Definition of ViewsHandlerFilterTest. */ /** * Tests filter handler. */ class ViewsHandlerFilterTest extends ViewsSqlTest { /** * {@inheritdoc} */ public static function getInfo() { return array( 'name' => 'Handler filter test', 'description' => 'test filter handler definitions', 'group' => 'Views', ); } /** * {@inheritdoc} */ protected function setUp() { // The Views and Views UI modules will be enabled with this. parent::setUp(); // Assign vocabulary 'tag' to user entity. $field_definition = field_read_field('field_tags'); $instance_definition = array( 'field_name' => $field_definition['field_name'], 'entity_type' => 'user', 'bundle' => 'user', 'widget' => array( 'type' => 'taxonomy_autocomplete', ), 'display' => array( 'default' => array( 'type' => 'taxonomy_term_reference_link', 'weight' => 10, ), 'teaser' => array( 'type' => 'taxonomy_term_reference_link', 'weight' => 10, ), ), ); field_create_instance($instance_definition); } /** * Tests "is all of" of filter operation. */ function testFilterInOperatorUi() { $term = $this->drupalCreateTerm(1); $node1 = $this->drupalCreateNode(array('type' => 'article','field_tags_tid' => $term->tid, 'created' => REQUEST_TIME)); $node2 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 1)); $user2 = $this->drupalCreateUser(array('access content')); // $this->drupalLogin($this->drupalCreateUser(['administer users']); $this->drupalLogin($this->drupalCreateUser(['administer users', 'access administration pages', 'administer site configuration', 'administer nodes', 'bypass node access'])); $this->drupalGet('node/1/edit'); $edit['field_tags' . '[' . LANGUAGE_NONE . ']'] = $term->name; $this->drupalPost('node/' . $node1->nid . '/edit', $edit, t('Save')); $edit['field_tags' . '[' . LANGUAGE_NONE . ']'] = $term->name; $this->drupalPost('user/' . $user2->uid . '/edit', $edit, t('Save')); $result[] = array('nid' => $node1->nid); $view = $this->get_sample_view(); $this->executeView($view); $this->assertIdenticalResultset($view, $result); } /** * Sample view. * * @return \view */ protected function get_sample_view() { $view = new view(); $view->name = 'article'; $view->description = ''; $view->tag = 'default'; $view->base_table = 'node'; $view->human_name = 'Article'; $view->core = 7; $view->api_version = '3.0'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Article'; $handler->display->display_options['use_more_always'] = FALSE; $handler->display->display_options['access']['type'] = 'perm'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['exposed_form']['type'] = 'basic'; $handler->display->display_options['pager']['type'] = 'full'; $handler->display->display_options['pager']['options']['items_per_page'] = '10'; $handler->display->display_options['style_plugin'] = 'table'; $handler->display->display_options['style_options']['columns'] = array( 'title' => 'title', ); $handler->display->display_options['style_options']['default'] = '-1'; $handler->display->display_options['style_options']['info'] = array( 'title' => array( 'sortable' => 0, 'default_sort_order' => 'asc', 'align' => '', 'separator' => '', 'empty_column' => 0, ), ); /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'nid'; $handler->display->display_options['fields']['nid']['label'] = ''; $handler->display->display_options['fields']['nid']['element_label_colon'] = FALSE; /* Sort criterion: Content: Post date */ $handler->display->display_options['sorts']['created']['id'] = 'created'; $handler->display->display_options['sorts']['created']['table'] = 'node'; $handler->display->display_options['sorts']['created']['field'] = 'created'; $handler->display->display_options['sorts']['created']['order'] = 'DESC'; /* Filter criterion: Content: Published */ $handler->display->display_options['filters']['status']['id'] = 'status'; $handler->display->display_options['filters']['status']['table'] = 'node'; $handler->display->display_options['filters']['status']['field'] = 'status'; $handler->display->display_options['filters']['status']['value'] = 1; $handler->display->display_options['filters']['status']['group'] = 1; $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE; /* Filter criterion: Field: Tags (field_tags) */ $handler->display->display_options['filters']['field_tags_tid']['id'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['table'] = 'field_data_field_tags'; $handler->display->display_options['filters']['field_tags_tid']['field'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['operator'] = 'and'; $handler->display->display_options['filters']['field_tags_tid']['value'] = array( 0 => '1', ); $handler->display->display_options['filters']['field_tags_tid']['expose']['operator_id'] = 'field_tags_tid_op'; $handler->display->display_options['filters']['field_tags_tid']['expose']['label'] = 'Tags (field_tags)'; $handler->display->display_options['filters']['field_tags_tid']['expose']['operator'] = 'field_tags_tid_op'; $handler->display->display_options['filters']['field_tags_tid']['expose']['identifier'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['expose']['remember_roles'] = array( 2 => '2', ); $handler->display->display_options['filters']['field_tags_tid']['vocabulary'] = 'tags'; /* Display: Page */ $handler = $view->new_display('page', 'Page', 'page'); $handler->display->display_options['path'] = 'article'; return $view; } } tests/views_query.test +18 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,24 @@ abstract class ViewsSqlTest extends ViewsTestCase { $this->checkPermissions(array(), TRUE); } /** * Create a term. * * @param int $vid * The vocabulary ID that the term is to be added to. * * @return object * A full term object with a random name. */ protected function drupalCreateTerm($vid) { $term = new stdClass(); $term->name = $this->randomName(); $term->description = $this->randomName(); $term->vid = $vid; taxonomy_term_save($term); return $term; } /** * This function allows to enable views ui from a higher class which can't * change the setup function anymore. Loading views.info +1 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,7 @@ files[] = tests/views_exposed_form.test files[] = tests/field/views_fieldapi.test files[] = tests/views_glossary.test files[] = tests/views_groupby.test files[] = tests/views_handler_filter.test files[] = tests/views_handlers.test files[] = tests/views_module.test files[] = tests/views_pager.test Loading Loading
includes/handlers.inc +28 −49 Original line number Diff line number Diff line Loading @@ -996,24 +996,24 @@ class views_many_to_one_helper { return $this->handler->table_alias; } // Case 2: it's an 'and' or an 'or'. // Case 2: it's anything but an 'or'. // We do one join per selected value. if ($this->handler->operator != 'not') { // Clone the join for each table. $this->handler->table_aliases = array(); // Clone the join for each table: $this->handler->table_aliases = []; foreach ($this->handler->value as $value) { $join = $this->get_join(); if ($this->handler->operator == 'and') { $join->type = 'INNER'; } $join->extra = array( array( if (empty($join->extra)) { $join->extra = []; } $join->extra[] = [ 'field' => $this->handler->real_field, 'value' => $value, 'numeric' => !empty($this->handler->definition['numeric']), ), ); ]; // The table alias needs to be unique to this value across the // multiple times the filter or argument is called by the view. if (!isset($this->handler->view->many_to_one_aliases[$field][$value])) { Loading @@ -1021,33 +1021,14 @@ class views_many_to_one_helper { $this->handler->view->many_to_one_count[$this->handler->table] = 0; } $this->handler->view->many_to_one_aliases[$field][$value] = $this->handler->table . '_value_' . ($this->handler->view->many_to_one_count[$this->handler->table]++); } $alias = $this->handler->table_aliases[$value] = $this->add_table($join, $this->handler->view->many_to_one_aliases[$field][$value]); $alias = $this->handler->table_aliases[$value] = $this->add_table($join, $this->handler->view->many_to_one_aliases[$field][$value]); // and set table_alias to the first of these. if (empty($this->handler->table_alias)) { $this->handler->table_alias = $alias; } } } // Case 3: it's a 'not'. // We just do one join. We'll add a where clause during the query phase // to ensure that $table.$field IS NULL. else { $join = $this->get_join(); $join->type = 'LEFT'; $join->extra = array(); $join->extra_type = 'OR'; foreach ($this->handler->value as $value) { $join->extra[] = array( 'field' => $this->handler->real_field, 'value' => $value, 'numeric' => !empty($this->handler->definition['numeric']), ); } $this->handler->table_alias = $this->add_table($join); } } return $this->handler->table_alias; } Loading Loading @@ -1081,12 +1062,7 @@ class views_many_to_one_helper { // Determine whether a single expression is enough(FALSE) or the conditions // should be added via an db_or()/db_and() (TRUE). $add_condition = TRUE; if ($operator == 'not') { $value = NULL; $operator = 'IS NULL'; $add_condition = FALSE; } elseif ($operator == 'or' && empty($options['reduce_duplicates'])) { if ($operator == 'or' && empty($options['reduce_duplicates'])) { if (count($value) > 1) { $operator = 'IN'; } Loading Loading @@ -1120,6 +1096,9 @@ class views_many_to_one_helper { $field = $this->handler->real_field; $clause = $operator == 'or' ? db_or() : db_and(); foreach ($this->handler->table_aliases as $value => $alias) { if ($operator == 'not') { $value = NULL; } $clause->condition("$alias.$field", $value); } Loading
tests/views_handler_filter.test 0 → 100644 +161 −0 Original line number Diff line number Diff line <?php /** * @file * Definition of ViewsHandlerFilterTest. */ /** * Tests filter handler. */ class ViewsHandlerFilterTest extends ViewsSqlTest { /** * {@inheritdoc} */ public static function getInfo() { return array( 'name' => 'Handler filter test', 'description' => 'test filter handler definitions', 'group' => 'Views', ); } /** * {@inheritdoc} */ protected function setUp() { // The Views and Views UI modules will be enabled with this. parent::setUp(); // Assign vocabulary 'tag' to user entity. $field_definition = field_read_field('field_tags'); $instance_definition = array( 'field_name' => $field_definition['field_name'], 'entity_type' => 'user', 'bundle' => 'user', 'widget' => array( 'type' => 'taxonomy_autocomplete', ), 'display' => array( 'default' => array( 'type' => 'taxonomy_term_reference_link', 'weight' => 10, ), 'teaser' => array( 'type' => 'taxonomy_term_reference_link', 'weight' => 10, ), ), ); field_create_instance($instance_definition); } /** * Tests "is all of" of filter operation. */ function testFilterInOperatorUi() { $term = $this->drupalCreateTerm(1); $node1 = $this->drupalCreateNode(array('type' => 'article','field_tags_tid' => $term->tid, 'created' => REQUEST_TIME)); $node2 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 1)); $user2 = $this->drupalCreateUser(array('access content')); // $this->drupalLogin($this->drupalCreateUser(['administer users']); $this->drupalLogin($this->drupalCreateUser(['administer users', 'access administration pages', 'administer site configuration', 'administer nodes', 'bypass node access'])); $this->drupalGet('node/1/edit'); $edit['field_tags' . '[' . LANGUAGE_NONE . ']'] = $term->name; $this->drupalPost('node/' . $node1->nid . '/edit', $edit, t('Save')); $edit['field_tags' . '[' . LANGUAGE_NONE . ']'] = $term->name; $this->drupalPost('user/' . $user2->uid . '/edit', $edit, t('Save')); $result[] = array('nid' => $node1->nid); $view = $this->get_sample_view(); $this->executeView($view); $this->assertIdenticalResultset($view, $result); } /** * Sample view. * * @return \view */ protected function get_sample_view() { $view = new view(); $view->name = 'article'; $view->description = ''; $view->tag = 'default'; $view->base_table = 'node'; $view->human_name = 'Article'; $view->core = 7; $view->api_version = '3.0'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Article'; $handler->display->display_options['use_more_always'] = FALSE; $handler->display->display_options['access']['type'] = 'perm'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['exposed_form']['type'] = 'basic'; $handler->display->display_options['pager']['type'] = 'full'; $handler->display->display_options['pager']['options']['items_per_page'] = '10'; $handler->display->display_options['style_plugin'] = 'table'; $handler->display->display_options['style_options']['columns'] = array( 'title' => 'title', ); $handler->display->display_options['style_options']['default'] = '-1'; $handler->display->display_options['style_options']['info'] = array( 'title' => array( 'sortable' => 0, 'default_sort_order' => 'asc', 'align' => '', 'separator' => '', 'empty_column' => 0, ), ); /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'nid'; $handler->display->display_options['fields']['nid']['label'] = ''; $handler->display->display_options['fields']['nid']['element_label_colon'] = FALSE; /* Sort criterion: Content: Post date */ $handler->display->display_options['sorts']['created']['id'] = 'created'; $handler->display->display_options['sorts']['created']['table'] = 'node'; $handler->display->display_options['sorts']['created']['field'] = 'created'; $handler->display->display_options['sorts']['created']['order'] = 'DESC'; /* Filter criterion: Content: Published */ $handler->display->display_options['filters']['status']['id'] = 'status'; $handler->display->display_options['filters']['status']['table'] = 'node'; $handler->display->display_options['filters']['status']['field'] = 'status'; $handler->display->display_options['filters']['status']['value'] = 1; $handler->display->display_options['filters']['status']['group'] = 1; $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE; /* Filter criterion: Field: Tags (field_tags) */ $handler->display->display_options['filters']['field_tags_tid']['id'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['table'] = 'field_data_field_tags'; $handler->display->display_options['filters']['field_tags_tid']['field'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['operator'] = 'and'; $handler->display->display_options['filters']['field_tags_tid']['value'] = array( 0 => '1', ); $handler->display->display_options['filters']['field_tags_tid']['expose']['operator_id'] = 'field_tags_tid_op'; $handler->display->display_options['filters']['field_tags_tid']['expose']['label'] = 'Tags (field_tags)'; $handler->display->display_options['filters']['field_tags_tid']['expose']['operator'] = 'field_tags_tid_op'; $handler->display->display_options['filters']['field_tags_tid']['expose']['identifier'] = 'field_tags_tid'; $handler->display->display_options['filters']['field_tags_tid']['expose']['remember_roles'] = array( 2 => '2', ); $handler->display->display_options['filters']['field_tags_tid']['vocabulary'] = 'tags'; /* Display: Page */ $handler = $view->new_display('page', 'Page', 'page'); $handler->display->display_options['path'] = 'article'; return $view; } }
tests/views_query.test +18 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,24 @@ abstract class ViewsSqlTest extends ViewsTestCase { $this->checkPermissions(array(), TRUE); } /** * Create a term. * * @param int $vid * The vocabulary ID that the term is to be added to. * * @return object * A full term object with a random name. */ protected function drupalCreateTerm($vid) { $term = new stdClass(); $term->name = $this->randomName(); $term->description = $this->randomName(); $term->vid = $vid; taxonomy_term_save($term); return $term; } /** * This function allows to enable views ui from a higher class which can't * change the setup function anymore. Loading
views.info +1 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,7 @@ files[] = tests/views_exposed_form.test files[] = tests/field/views_fieldapi.test files[] = tests/views_glossary.test files[] = tests/views_groupby.test files[] = tests/views_handler_filter.test files[] = tests/views_handlers.test files[] = tests/views_module.test files[] = tests/views_pager.test Loading