function setUp() { parent::setUp(); // Add two new languages. ConfigurableLanguage::createFromLangcode('fr')->save(); ConfigurableLanguage::createFromLangcode('es')->save(); // Set up term names. $this->termNames = array('en' => 'Food in Paris', 'es' => 'Comida en Paris', 'fr' => 'Nouriture en Paris'); // Create a vocabulary. $this->vocabulary = Vocabulary::create(['name' => 'Views testing tags', 'vid' => 'views_testing_tags']); $this->vocabulary->save(); // Add a translatable field to the vocabulary. $field = FieldStorageConfig::create(array('field_name' => 'field_foo', 'entity_type' => 'taxonomy_term', 'type' => 'text')); $field->save(); FieldConfig::create(['field_name' => 'field_foo', 'entity_type' => 'taxonomy_term', 'label' => 'Foo', 'bundle' => 'views_testing_tags'])->save(); // Create term with translations. $taxonomy = $this->createTermWithProperties(array('name' => $this->termNames['en'], 'langcode' => 'en', 'description' => $this->termNames['en'], 'field_foo' => $this->termNames['en'])); foreach (array('es', 'fr') as $langcode) { $translation = $taxonomy->addTranslation($langcode, array('name' => $this->termNames[$langcode])); $translation->description->value = $this->termNames[$langcode]; $translation->field_foo->value = $this->termNames[$langcode]; } $taxonomy->save(); Views::viewsData()->clear(); ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views')); $this->container->get('router.builder')->rebuild(); }
/** * Provide a form for setting options. */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); if (isset($this->base_table)) { $executable = $form_state->get('view')->getExecutable(); // A whole bunch of code to figure out what relationships are valid for // this item. $relationships = $executable->display_handler->getOption('relationships'); $relationship_options = array(); foreach ($relationships as $relationship) { $relationship_handler = Views::handlerManager('relationship')->getHandler($relationship); // If this relationship is valid for this type, add it to the list. $data = Views::viewsData()->get($relationship['table']); $base = $data[$relationship['field']]['relationship']['base']; if ($base == $this->base_table) { $relationship_handler->init($executable, $relationship); $relationship_options[$relationship['id']] = $relationship_handler->adminLabel(); } } if (!empty($relationship_options)) { $relationship_options = array_merge(array('none' => $this->t('Do not use a relationship')), $relationship_options); $rel = empty($this->options['relationship']) ? 'none' : $this->options['relationship']; if (empty($relationship_options[$rel])) { // Pick the first relationship. $rel = key($relationship_options); } $form['relationship'] = array('#type' => 'select', '#title' => $this->t('Relationship'), '#options' => $relationship_options, '#default_value' => $rel); } else { $form['relationship'] = array('#type' => 'value', '#value' => 'none'); } } }
/** * {@inheritdoc} */ protected function setUpFixtures() { $this->installEntitySchema('user'); $this->installConfig(array('user')); parent::setUpFixtures(); // Create a record for uid 1. $this->rootUser = User::create(['name' => $this->randomMachineName()]); $this->rootUser->save(); Views::viewsData()->clear(); }
/** * Overrides \Drupal\views\Tests\ViewUnitTestBase::setUpFixtures(). */ protected function setUpFixtures() { $this->installEntitySchema('user'); $this->installConfig(array('user')); parent::setUpFixtures(); // Create a record for uid 1. $this->installSchema('system', 'sequences'); $this->root_user = entity_create('user', array('name' => $this->randomMachineName())); $this->root_user->save(); Views::viewsData()->clear(); }
/** * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { $views_data = Views::viewsData(); $base_tables = array_keys($views_data->fetchBaseTables()); $this->derivatives = array(); foreach ($base_tables as $table) { $views_info = $views_data->get($table); if (empty($views_info['table']['wizard_id'])) { $this->derivatives[$table] = array('id' => 'standard', 'base_table' => $table, 'title' => $views_info['table']['base']['title'], 'class' => 'Drupal\\views\\Plugin\\views\\wizard\\Standard'); } } return parent::getDerivativeDefinitions($base_plugin_definition); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $view = $form_state['view']; foreach ($form_state['values'] as $key => $value) { // Only save values onto the view if they're actual view properties // (as opposed to 'op' or 'form_build_id'). if (isset($form['details'][$key])) { $view->set($key, $value); } } $bases = Views::viewsData()->fetchBaseTables(); $form_state['#page_title'] = $view->label(); if (isset($bases[$view->get('base_table')])) { $form_state['#page_title'] .= ' (' . $bases[$view->get('base_table')]['title'] . ')'; } $view->cacheSet(); }
/** * Tests the taxonomy parent plugin UI. */ public function testTaxonomyRelationships() { // Check the generated views data of taxonomy_index. $views_data = Views::viewsData()->get('taxonomy_index'); // Check the table join data. $this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['left_field'], 'tid'); $this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['field'], 'tid'); $this->assertEqual($views_data['table']['join']['node_field_data']['left_field'], 'nid'); $this->assertEqual($views_data['table']['join']['node_field_data']['field'], 'nid'); $this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['left_field'], 'tid'); $this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['field'], 'tid'); // Check the generated views data of taxonomy_term_hierarchy. $views_data = Views::viewsData()->get('taxonomy_term_hierarchy'); // Check the table join data. $this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['left_field'], 'tid'); $this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['field'], 'parent'); $this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['left_field'], 'tid'); $this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['field'], 'tid'); // Check the parent relationship data. $this->assertEqual($views_data['parent']['relationship']['base'], 'taxonomy_term_field_data'); $this->assertEqual($views_data['parent']['relationship']['field'], 'parent'); $this->assertEqual($views_data['parent']['relationship']['label'], t('Parent')); $this->assertEqual($views_data['parent']['relationship']['id'], 'standard'); // Check the parent filter and argument data. $this->assertEqual($views_data['parent']['filter']['id'], 'numeric'); $this->assertEqual($views_data['parent']['argument']['id'], 'taxonomy'); // Check an actual test view. $view = Views::getView('test_taxonomy_term_relationship'); $this->executeView($view); /** @var \Drupal\views\ResultRow $row */ foreach ($view->result as $index => $row) { // Check that the actual ID of the entity is the expected one. $this->assertEqual($row->tid, $this->terms[$index]->id()); // Also check that we have the correct result entity. $this->assertEqual($row->_entity->id(), $this->terms[$index]->id()); $this->assertTrue($row->_entity instanceof TermInterface); if (!$index) { $this->assertTrue($row->_relationship_entities['parent'] instanceof TermInterface); $this->assertEqual($row->_relationship_entities['parent']->id(), $this->term2->id()); $this->assertEqual($row->taxonomy_term_field_data_taxonomy_term_hierarchy_tid, $this->term2->id()); } $this->assertTrue($row->_relationship_entities['nid'] instanceof NodeInterface); $this->assertEqual($row->_relationship_entities['nid']->id(), $this->nodes[$index]->id()); } }
/** * Tests views data generated for image field relationship. * * @see image_field_views_data() * @see image_field_views_data_views_data_alter() */ public function testRelationshipViewsData() { // Create image field to entity_test. FieldStorageConfig::create(array('entity_type' => 'entity_test', 'field_name' => 'field_base_image', 'type' => 'image'))->save(); FieldConfig::create(array('entity_type' => 'entity_test', 'field_name' => 'field_base_image', 'bundle' => 'entity_test'))->save(); // Check the generated views data. $views_data = Views::viewsData()->get('entity_test__field_base_image'); $relationship = $views_data['field_base_image_target_id']['relationship']; $this->assertEqual($relationship['id'], 'standard'); $this->assertEqual($relationship['base'], 'file_managed'); $this->assertEqual($relationship['base field'], 'fid'); $this->assertEqual($relationship['entity type'], 'file'); // Check the backwards reference. $views_data = Views::viewsData()->get('file_managed'); $relationship = $views_data['reverse_field_base_image_entity_test']['relationship']; $this->assertEqual($relationship['id'], 'entity_reverse'); $this->assertEqual($relationship['base'], 'entity_test'); $this->assertEqual($relationship['base field'], 'id'); $this->assertEqual($relationship['field table'], 'entity_test__field_base_image'); $this->assertEqual($relationship['field field'], 'field_base_image_target_id'); $this->assertEqual($relationship['field_name'], 'field_base_image'); $this->assertEqual($relationship['entity_type'], 'entity_test'); $this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]); // Create image field to entity_test_mul. FieldStorageConfig::create(array('entity_type' => 'entity_test_mul', 'field_name' => 'field_data_image', 'type' => 'image'))->save(); FieldConfig::create(array('entity_type' => 'entity_test_mul', 'field_name' => 'field_data_image', 'bundle' => 'entity_test_mul'))->save(); // Check the generated views data. $views_data = Views::viewsData()->get('entity_test_mul__field_data_image'); $relationship = $views_data['field_data_image_target_id']['relationship']; $this->assertEqual($relationship['id'], 'standard'); $this->assertEqual($relationship['base'], 'file_managed'); $this->assertEqual($relationship['base field'], 'fid'); $this->assertEqual($relationship['entity type'], 'file'); // Check the backwards reference. $views_data = Views::viewsData()->get('file_managed'); $relationship = $views_data['reverse_field_data_image_entity_test_mul']['relationship']; $this->assertEqual($relationship['id'], 'entity_reverse'); $this->assertEqual($relationship['base'], 'entity_test_mul_property_data'); $this->assertEqual($relationship['base field'], 'id'); $this->assertEqual($relationship['field table'], 'entity_test_mul__field_data_image'); $this->assertEqual($relationship['field field'], 'field_data_image_target_id'); $this->assertEqual($relationship['field_name'], 'field_data_image'); $this->assertEqual($relationship['entity_type'], 'entity_test_mul'); $this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]); }
protected function getTableEntityType($table) { static $recursion = 0; if ($table = Views::viewsData()->get($table)) { if (!empty($table['table']['entity type'])) { // Reset recursion when we found a value. $recursion = 0; return $table['table']['entity type']; } elseif (!empty($table['table']['join']) && count($table['table']['join']) == 1) { if (empty($recursion)) { $join_table = array_pop(array_keys($table['table']['join'])); $recursion++; return $this->getTableEntityType($join_table); } } } return NULL; }
/** * Tests using the views relationship. */ public function testRelationship() { // Check just the generated views data. $views_data_field_test = Views::viewsData()->get('entity_test__field_test'); $this->assertEqual($views_data_field_test['field_test']['relationship']['id'], 'standard'); $this->assertEqual($views_data_field_test['field_test']['relationship']['base'], 'entity_test'); $this->assertEqual($views_data_field_test['field_test']['relationship']['base field'], 'id'); $this->assertEqual($views_data_field_test['field_test']['relationship']['relationship field'], 'field_test_target_id'); // Check the backwards reference. $views_data_entity_test = Views::viewsData()->get('entity_test'); $this->assertEqual($views_data_entity_test['reverse__entity_test__field_test']['relationship']['id'], 'entity_reverse'); $this->assertEqual($views_data_entity_test['reverse__entity_test__field_test']['relationship']['base'], 'entity_test'); $this->assertEqual($views_data_entity_test['reverse__entity_test__field_test']['relationship']['base field'], 'id'); $this->assertEqual($views_data_entity_test['reverse__entity_test__field_test']['relationship']['field table'], 'entity_test__field_test'); $this->assertEqual($views_data_entity_test['reverse__entity_test__field_test']['relationship']['field field'], 'field_test_target_id'); // Check an actual test view. $view = Views::getView('test_entity_reference_view'); $this->executeView($view); foreach (array_keys($view->result) as $index) { // Check that the actual ID of the entity is the expected one. $this->assertEqual($view->result[$index]->id, $this->entities[$index + 1]->id()); // Also check that we have the correct result entity. $this->assertEqual($view->result[$index]->_entity->id(), $this->entities[$index + 1]->id()); // Test the forward relationship. // The second and third entity refer to the first one. // The value key on the result will be in the format // BASE_TABLE_FIELD_NAME. $this->assertEqual($view->result[$index]->entity_test_entity_test__field_test_id, $index == 0 ? NULL : 1); if ($index > 0) { // Test that the correct relationship entity is on the row. $this->assertEqual($view->result[$index]->_relationship_entities['test_relationship']->id(), 1); } } $view->destroy(); $this->executeView($view, 'embed_1'); foreach (array_keys($view->result) as $index) { $this->assertEqual($view->result[$index]->id, $this->entities[$index + 1]->id()); $this->assertEqual($view->result[$index]->_entity->id(), $this->entities[$index + 1]->id()); // The second and third entity refer to the first one. $this->assertEqual($view->result[$index]->entity_test_entity_test__field_test_id, $index == 0 ? NULL : 1); } }
/** * Tests views relationship with multiple referenced entities. * * Relationship is required, so only users with profiles will be listed. */ public function testProfileRelationship() { $profile_type = $this->createProfileType(); $user[0] = $user1 = $this->createUser(); $user2 = $this->createUser(); $user[1] = $user3 = $this->createUser(); $user4 = $this->createUser(); $profile[0] = $this->createProfile($profile_type, $user1); $profile[1] = $this->createProfile($profile_type, $user3); Views::viewsData()->clear(); // Check table relationship exists. $views_data = Views::viewsData()->get('users_field_data'); $this->assertEqual($views_data['profile']['relationship']['base'], 'profile'); $this->assertEqual($views_data['profile']['relationship']['base field'], 'uid'); $view = Views::getView('users'); $this->executeView($view); // Ensure values are populated for user and profiles. foreach ($view->result as $index => $row) { $this->assertEqual($row->uid, $user[$index]->id(), 'User ' . $user[$index]->id() . ' found on row: ' . $index); $this->assertEqual($row->profile_users_field_data_profile_id, $profile[$index]->id(), 'Profile ' . $profile[$index]->id() . ' found on view: ' . $index); } }
/** * Called to implement a relationship in a query. */ public function query() { $this->ensureMyTable(); // First, relate our base table to the current base table to the // field, using the base table's id field to the field's column. $views_data = Views::viewsData()->get($this->table); $left_field = $views_data['table']['base']['field']; $first = array('left_table' => $this->tableAlias, 'left_field' => $left_field, 'table' => $this->definition['field table'], 'field' => $this->definition['field field'], 'adjusted' => TRUE); if (!empty($this->options['required'])) { $first['type'] = 'INNER'; } if (!empty($this->definition['join_extra'])) { $first['extra'] = $this->definition['join_extra']; } if (!empty($def['join_id'])) { $id = $def['join_id']; } else { $id = 'standard'; } $first_join = $this->joinManager->createInstance($id, $first); $this->first_alias = $this->query->addTable($this->definition['field table'], $this->relationship, $first_join); // Second, relate the field table to the entity specified using // the entity id on the field table and the entity's id field. $second = array('left_table' => $this->first_alias, 'left_field' => 'entity_id', 'table' => $this->definition['base'], 'field' => $this->definition['base field'], 'adjusted' => TRUE); if (!empty($this->options['required'])) { $second['type'] = 'INNER'; } if (!empty($def['join_id'])) { $id = $def['join_id']; } else { $id = 'standard'; } $second_join = $this->joinManager->createInstance($id, $second); $second_join->adjusted = TRUE; // use a short alias for this: $alias = $this->definition['field_name'] . '_' . $this->table; $this->alias = $this->query->addRelationship($alias, $second_join, $this->definition['base'], $this->relationship); }
/** * Executes the query and fills the associated view object with according * values. * * Values to set: $view->result, $view->total_rows, $view->execute_time, * $view->current_page. */ public function execute(ViewExecutable $view) { $query = $view->build_info['query']; $count_query = $view->build_info['count_query']; $query->addMetaData('view', $view); $count_query->addMetaData('view', $view); if (empty($this->options['disable_sql_rewrite'])) { $base_table_data = Views::viewsData()->get($this->view->storage->get('base_table')); if (isset($base_table_data['table']['base']['access query tag'])) { $access_tag = $base_table_data['table']['base']['access query tag']; $query->addTag($access_tag); $count_query->addTag($access_tag); } if (isset($base_table_data['table']['base']['query metadata'])) { foreach ($base_table_data['table']['base']['query metadata'] as $key => $value) { $query->addMetaData($key, $value); $count_query->addMetaData($key, $value); } } } if ($query) { $additional_arguments = \Drupal::moduleHandler()->invokeAll('views_query_substitutions', array($view)); // Count queries must be run through the preExecute() method. // If not, then hook_query_node_access_alter() may munge the count by // adding a distinct against an empty query string // (e.g. COUNT DISTINCT(1) ...) and no pager will return. // See pager.inc > PagerDefault::execute() // http://api.drupal.org/api/drupal/includes--pager.inc/function/PagerDefault::execute/7 // See https://www.drupal.org/node/1046170. $count_query->preExecute(); // Build the count query. $count_query = $count_query->countQuery(); // Add additional arguments as a fake condition. // XXX: this doesn't work, because PDO mandates that all bound arguments // are used on the query. TODO: Find a better way to do this. if (!empty($additional_arguments)) { // $query->where('1 = 1', $additional_arguments); // $count_query->where('1 = 1', $additional_arguments); } $start = microtime(TRUE); try { if ($view->pager->useCountQuery() || !empty($view->get_total_rows)) { $view->pager->executeCountQuery($count_query); } // Let the pager modify the query to add limits. $view->pager->preExecute($query); if (!empty($this->limit) || !empty($this->offset)) { // We can't have an offset without a limit, so provide a very large limit instead. $limit = intval(!empty($this->limit) ? $this->limit : 999999); $offset = intval(!empty($this->offset) ? $this->offset : 0); $query->range($offset, $limit); } $result = $query->execute(); $result->setFetchMode(\PDO::FETCH_CLASS, 'Drupal\views\ResultRow'); // Setup the result row objects. $view->result = iterator_to_array($result); array_walk($view->result, function(ResultRow $row, $index) { $row->index = $index; }); $view->pager->postExecute($view->result); $view->pager->updatePageInfo(); $view->total_rows = $view->pager->getTotalItems(); // Load all entities contained in the results. $this->loadEntities($view->result); } catch (DatabaseExceptionWrapper $e) { $view->result = array(); if (!empty($view->live_preview)) { drupal_set_message($e->getMessage(), 'error'); } else { throw new DatabaseExceptionWrapper("Exception in {$view->storage->label()}[{$view->storage->id()}]: {$e->getMessage()}"); } } } else { $start = microtime(TRUE); } $view->execute_time = microtime(TRUE) - $start; }
/** * Tests views data generated for relationship. * * @see entity_reference_field_views_data() */ public function testDataTableRelationshipWithLongFieldName() { // Create some test entities which link each other. $referenced_entity = EntityTest::create(); $referenced_entity->save(); $entity = EntityTestMulChanged::create(); $entity->field_test_data_with_a_long_name->target_id = $referenced_entity->id(); $entity->save(); $this->entities[] = $entity; $entity = EntityTestMulChanged::create(); $entity->field_test_data_with_a_long_name->target_id = $referenced_entity->id(); $entity->save(); $this->entities[] = $entity; Views::viewsData()->clear(); // Check an actual test view. $view = Views::getView('test_entity_reference_entity_test_view_long'); $this->executeView($view); /** @var \Drupal\views\ResultRow $row */ foreach ($view->result as $index => $row) { // Check that the actual ID of the entity is the expected one. $this->assertEqual($row->id, $this->entities[$index]->id()); // Also check that we have the correct result entity. $this->assertEqual($row->_entity->id(), $this->entities[$index]->id()); // Test the forward relationship. //$this->assertEqual($row->entity_test_entity_test_mul__field_data_test_id, 1); // Test that the correct relationship entity is on the row. $this->assertEqual($row->_relationship_entities['field_test_data_with_a_long_name']->id(), 1); $this->assertEqual($row->_relationship_entities['field_test_data_with_a_long_name']->bundle(), 'entity_test'); } }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->installEntitySchema('entity_test'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test_rev'); // Bypass any field access. $this->adminUser = User::create(['name' => $this->randomString()]); $this->adminUser->save(); $this->container->get('current_user')->setAccount($this->adminUser); $this->testUsers = []; for ($i = 0; $i < 5; $i++) { $this->testUsers[$i] = User::create(['name' => 'test ' . $i, 'timezone' => User::getAllowedTimezones()[$i]]); $this->testUsers[$i]->save(); } // Setup a field storage and field, but also change the views data for the // entity_test entity type. $field_storage = FieldStorageConfig::create(['field_name' => 'field_test', 'type' => 'integer', 'entity_type' => 'entity_test']); $field_storage->save(); $field = FieldConfig::create(['field_name' => 'field_test', 'entity_type' => 'entity_test', 'bundle' => 'entity_test']); $field->save(); $field_storage_multiple = FieldStorageConfig::create(['field_name' => 'field_test_multiple', 'type' => 'integer', 'entity_type' => 'entity_test', 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED]); $field_storage_multiple->save(); $field_multiple = FieldConfig::create(['field_name' => 'field_test_multiple', 'entity_type' => 'entity_test', 'bundle' => 'entity_test']); $field_multiple->save(); $random_number = (string) 30856; $random_number_multiple = (string) 1370359990; for ($i = 0; $i < 5; $i++) { $this->entities[$i] = $entity = EntityTest::create(['bundle' => 'entity_test', 'name' => 'test ' . $i, 'field_test' => $random_number[$i], 'field_test_multiple' => [$random_number_multiple[$i * 2], $random_number_multiple[$i * 2 + 1]], 'user_id' => $this->testUsers[$i]->id()]); $entity->save(); } // Setup some test data for entities with revisions. // We are testing both base field revisions and field config revisions. $field_storage = FieldStorageConfig::create(['field_name' => 'field_test', 'type' => 'integer', 'entity_type' => 'entity_test_rev']); $field_storage->save(); $field = FieldConfig::create(['field_name' => 'field_test', 'entity_type' => 'entity_test_rev', 'bundle' => 'entity_test_rev']); $field->save(); $field_storage_multiple = FieldStorageConfig::create(['field_name' => 'field_test_multiple', 'type' => 'integer', 'entity_type' => 'entity_test_rev', 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED]); $field_storage_multiple->save(); $field_multiple = FieldConfig::create(['field_name' => 'field_test_multiple', 'entity_type' => 'entity_test_rev', 'bundle' => 'entity_test_rev']); $field_multiple->save(); $this->entityRevision = []; $this->entityRevision[0] = $entity = EntityTestRev::create(['name' => 'base value', 'field_test' => 1, 'field_test_multiple' => [1, 3, 7], 'user_id' => $this->testUsers[0]->id()]); $entity->save(); $original_entity = clone $entity; $entity = clone $original_entity; $entity->setNewRevision(TRUE); $entity->name->value = 'revision value1'; $entity->field_test->value = 2; $entity->field_test_multiple[0]->value = 0; $entity->field_test_multiple[1]->value = 3; $entity->field_test_multiple[2]->value = 5; $entity->user_id->target_id = $this->testUsers[1]->id(); $entity->save(); $this->entityRevision[1] = $entity; $entity = clone $original_entity; $entity->setNewRevision(TRUE); $entity->name->value = 'revision value2'; $entity->field_test->value = 3; $entity->field_test_multiple[0]->value = 9; $entity->field_test_multiple[1]->value = 9; $entity->field_test_multiple[2]->value = 9; $entity->user_id->target_id = $this->testUsers[2]->id(); $entity->save(); $this->entityRevision[2] = $entity; $this->entityRevision[3] = $entity = EntityTestRev::create(['name' => 'next entity value', 'field_test' => 4, 'field_test_multiple' => [2, 9, 9], 'user_id' => $this->testUsers[3]->id()]); $entity->save(); \Drupal::state()->set('entity_test.views_data', ['entity_test' => ['id' => ['field' => ['id' => 'field']]], 'entity_test_rev_revision' => ['id' => ['field' => ['id' => 'field']]]]); Views::viewsData()->clear(); }
/** * Tests native name display in language field. */ public function testNativeLanguageField() { $this->assertLanguageNames(); // Modify test view to display native language names and set translations. $config = $this->config('views.view.test_language'); $config->set('display.default.display_options.fields.langcode.settings.native_language', TRUE); $config->save(); \Drupal::languageManager()->getLanguageConfigOverride('fr', 'language.entity.fr')->set('label', 'Français')->save(); \Drupal::languageManager()->getLanguageConfigOverride('es', 'language.entity.es')->set('label', 'Español')->save(); $this->assertLanguageNames(TRUE); // Modify test view to use the views built-in language field and test that. \Drupal::state()->set('node_test_views.use_basic_handler', TRUE); Views::viewsData()->clear(); $config = $this->config('views.view.test_language'); $config->set('display.default.display_options.fields.langcode.native_language', FALSE); $config->clear('display.default.display_options.fields.langcode.settings'); $config->clear('display.default.display_options.fields.langcode.type'); $config->set('display.default.display_options.fields.langcode.plugin_id', 'language'); $config->save(); $this->assertLanguageNames(); $config->set('display.default.display_options.fields.langcode.native_language', TRUE)->save(); $this->assertLanguageNames(TRUE); }
/** * {@inheritdoc} */ public static function postDelete(EntityStorageInterface $storage, array $entities) { parent::postDelete($storage, $entities); if (\Drupal::moduleHandler()->moduleExists('views')) { Views::viewsData()->clear(); // Remove this line when https://www.drupal.org/node/2370365 gets fixed. Cache::invalidateTags(array('extension:views')); \Drupal::cache('discovery')->delete('views:wizard'); } /** @var \Drupal\user\SharedTempStore $temp_store */ $temp_store = \Drupal::service('user.shared_tempstore')->get('search_api_index'); foreach ($entities as $entity) { try { $temp_store->delete($entity->id()); } catch (TempStoreException $e) { // Can't really be helped, I guess. But is also very unlikely to happen. // Ignore it. } } }
/** * Do some common building initialization. */ public function initQuery() { if (!empty($this->query)) { $class = get_class($this->query); if ($class && $class != 'stdClass') { // return if query is already initialized. return TRUE; } } // Create and initialize the query object. $views_data = Views::viewsData()->get($this->storage->get('base_table')); $this->storage->set('base_field', !empty($views_data['table']['base']['field']) ? $views_data['table']['base']['field'] : ''); if (!empty($views_data['table']['base']['database'])) { $this->base_database = $views_data['table']['base']['database']; } $this->query = $this->display_handler->getPlugin('query'); return TRUE; }
/** * Retrieves sort information based on user input for the default display. * * @param array $form * The full wizard form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the wizard form. * * @return array * An array of sort arrays keyed by ID. A sort array contains the options * accepted by a sort handler. */ protected function defaultDisplaySortsUser($form, FormStateInterface $form_state) { $sorts = array(); // Don't add a sort if there is no form value or the user set the sort to // 'none'. if (($sort_type = $form_state->getValue(array('show', 'sort'))) && $sort_type != 'none') { list($column, $sort) = explode(':', $sort_type); // Column either be a column-name or the table-columnn-ame. $column = explode('-', $column); if (count($column) > 1) { $table = $column[0]; $column = $column[1]; } else { $table = $this->base_table; $column = $column[0]; } // If the input is invalid, for example when the #default_value contains // created from node, but the wizard type is another base table, make // sure it is not added. This usually don't happen if you have js // enabled. $data = Views::viewsData()->get($table); if (isset($data[$column]['sort'])) { $sorts[$column] = array('id' => $column, 'table' => $table, 'field' => $column, 'order' => $sort); } } return $sorts; }
/** * Returns an array of all tables from the query that map to an entity type. * * Includes the base table and all relationships, if eligible. * * Available keys for each table: * - base: The actual base table (i.e. "user" for an author relationship). * - relationship_id: The id of the relationship, or "none". * - alias: The alias used for the relationship. * - entity_type: The entity type matching the base table. * - revision: A boolean that specifies whether the table is a base table or * a revision table of the entity type. * * @return array * An array of table information, keyed by table alias. */ public function getEntityTableInfo() { // Start with the base table. $entity_tables = array(); $views_data = Views::viewsData(); $base_table = $this->view->storage->get('base_table'); $base_table_data = $views_data->get($base_table); if (isset($base_table_data['table']['entity type'])) { $entity_tables[$base_table_data['table']['entity type']] = array('base' => $base_table, 'alias' => $base_table, 'relationship_id' => 'none', 'entity_type' => $base_table_data['table']['entity type'], 'revision' => FALSE); } // Include all relationships. foreach ($this->view->relationship as $relationship_id => $relationship) { $table_data = $views_data->get($relationship->definition['base']); if (isset($table_data['table']['entity type'])) { $entity_tables[$table_data['table']['entity type']] = array('base' => $relationship->definition['base'], 'relationship_id' => $relationship_id, 'alias' => $relationship->alias, 'entity_type' => $table_data['table']['entity type'], 'revision' => FALSE); } } // Determine which of the tables are revision tables. foreach ($entity_tables as $table_alias => $table) { $entity_type = \Drupal::entityManager()->getDefinition($table['entity_type']); if ($entity_type->getRevisionTable() == $table['base']) { $entity_tables[$table_alias]['revision'] = TRUE; } } return $entity_tables; }
/** * {@inheritdoc} */ public function query() { // Figure out what base table this relationship brings to the party. $table_data = Views::viewsData()->get($this->definition['base']); $base_field = empty($this->definition['base field']) ? $table_data['table']['base']['field'] : $this->definition['base field']; $this->ensureMyTable(); $def = $this->definition; $def['table'] = $this->definition['base']; $def['field'] = $base_field; $def['left_table'] = $this->tableAlias; $def['left_field'] = $this->field; $def['adjusted'] = TRUE; if (!empty($this->options['required'])) { $def['type'] = 'INNER'; } if ($this->options['subquery_regenerate']) { // For testing only, regenerate the subquery each time. $def['left_query'] = $this->leftQuery($this->options); } else { // Get the stored subquery SQL string. $cid = 'views_relationship_groupwise_max:' . $this->view->storage->id() . ':' . $this->view->current_display . ':' . $this->options['id']; $cache = \Drupal::cache('data')->get($cid); if (isset($cache->data)) { $def['left_query'] = $cache->data; } else { $def['left_query'] = $this->leftQuery($this->options); \Drupal::cache('data')->set($cid, $def['left_query']); } } if (!empty($def['join_id'])) { $id = $def['join_id']; } else { $id = 'subquery'; } $join = Views::pluginManager('join')->createInstance($id, $def); // use a short alias for this: $alias = $def['table'] . '_' . $this->table; $this->alias = $this->query->addRelationship($alias, $join, $this->definition['base'], $this->relationship); }
/** * {@inheritdoc} */ public function postSave(EntityStorageInterface $storage, $update = TRUE) { parent::postSave($storage, $update); $this->resetCaches(); try { // Fake an original for inserts to make code cleaner. $original = $update ? $this->original : static::create(array('status' => FALSE)); if ($this->status() && $original->status()) { // React on possible changes that would require re-indexing, etc. $this->reactToServerSwitch($original); $this->reactToDatasourceSwitch($original); $this->reactToTrackerSwitch($original); } elseif (!$this->status() && $original->status()) { if ($this->hasValidTracker()) { Utility::getIndexTaskManager()->stopTracking($this); } if ($original->isServerEnabled()) { $original->getServer()->removeIndex($this); } } elseif ($this->status() && !$original->status()) { $this->getServer()->addIndex($this); if ($this->hasValidTracker()) { Utility::getIndexTaskManager()->startTracking($this); } } if (\Drupal::moduleHandler()->moduleExists('views')) { Views::viewsData()->clear(); } $this->resetCaches(); } catch (SearchApiException $e) { watchdog_exception('search_api', $e); } }
/** * Tests views data generated for relationship. * * @see entity_reference_field_views_data() */ public function testDataTableRelationship() { // Create some test entities which link each other. $referenced_entity = EntityTest::create(); $referenced_entity->save(); $entity = EntityTestMul::create(); $entity->field_data_test->target_id = $referenced_entity->id(); $entity->save(); $this->assertEqual($entity->field_data_test[0]->entity->id(), $referenced_entity->id()); $this->entities[] = $entity; $entity = EntityTestMul::create(); $entity->field_data_test->target_id = $referenced_entity->id(); $entity->save(); $this->assertEqual($entity->field_data_test[0]->entity->id(), $referenced_entity->id()); $this->entities[] = $entity; Views::viewsData()->clear(); // Check the generated views data. $views_data = Views::viewsData()->get('entity_test_mul__field_data_test'); $this->assertEqual($views_data['field_data_test']['relationship']['id'], 'standard'); $this->assertEqual($views_data['field_data_test']['relationship']['base'], 'entity_test'); $this->assertEqual($views_data['field_data_test']['relationship']['base field'], 'id'); $this->assertEqual($views_data['field_data_test']['relationship']['relationship field'], 'field_data_test_target_id'); $this->assertEqual($views_data['field_data_test']['relationship']['entity type'], 'entity_test'); // Check the backwards reference. $views_data = Views::viewsData()->get('entity_test'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['id'], 'entity_reverse'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['base'], 'entity_test_mul_property_data'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['base field'], 'id'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['field table'], 'entity_test_mul__field_data_test'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['field field'], 'field_data_test_target_id'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['field_name'], 'field_data_test'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['entity_type'], 'entity_test_mul'); $this->assertEqual($views_data['reverse__entity_test_mul__field_data_test']['relationship']['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]); // Check an actual test view. $view = Views::getView('test_entity_reference_entity_test_mul_view'); $this->executeView($view); /** @var \Drupal\views\ResultRow $row */ foreach ($view->result as $index => $row) { // Check that the actual ID of the entity is the expected one. $this->assertEqual($row->id, $this->entities[$index]->id()); // Also check that we have the correct result entity. $this->assertEqual($row->_entity->id(), $this->entities[$index]->id()); // Test the forward relationship. $this->assertEqual($row->entity_test_entity_test_mul__field_data_test_id, 1); // Test that the correct relationship entity is on the row. $this->assertEqual($row->_relationship_entities['field_data_test']->id(), 1); $this->assertEqual($row->_relationship_entities['field_data_test']->bundle(), 'entity_test'); } // Check the backwards reference view. $view = Views::getView('test_entity_reference_reverse_entity_test_mul_view'); $this->executeView($view); /** @var \Drupal\views\ResultRow $row */ foreach ($view->result as $index => $row) { $this->assertEqual($row->id, 1); $this->assertEqual($row->_entity->id(), 1); // Test the backwards relationship. $this->assertEqual($row->field_data_test_entity_test_id, $this->entities[$index]->id()); // Test that the correct relationship entity is on the row. $this->assertEqual($row->_relationship_entities['reverse__entity_test_mul__field_data_test']->id(), $this->entities[$index]->id()); $this->assertEqual($row->_relationship_entities['reverse__entity_test_mul__field_data_test']->bundle(), 'entity_test_mul'); } }
/** * {@inheritdoc} */ public function query() { // Figure out what base table this relationship brings to the party. $table_data = Views::viewsData()->get($this->definition['base']); $base_field = empty($this->definition['base field']) ? $table_data['table']['base']['field'] : $this->definition['base field']; $this->ensureMyTable(); $def = $this->definition; $def['table'] = $this->definition['base']; $def['field'] = $base_field; $def['left_table'] = $this->tableAlias; $def['left_field'] = $this->realField; $def['adjusted'] = TRUE; if (!empty($this->options['required'])) { $def['type'] = 'INNER'; } if (!empty($this->definition['extra'])) { $def['extra'] = $this->definition['extra']; } if (!empty($def['join_id'])) { $id = $def['join_id']; } else { $id = 'standard'; } $join = Views::pluginManager('join')->createInstance($id, $def); // use a short alias for this: $alias = $def['table'] . '_' . $this->table; $this->alias = $this->query->addRelationship($alias, $join, $this->definition['base'], $this->relationship); // Add access tags if the base table provide it. if (empty($this->query->options['disable_sql_rewrite']) && isset($table_data['table']['base']['access query tag'])) { $access_tag = $table_data['table']['base']['access query tag']; $this->query->addTag($access_tag); } }
/** * Adds an instance of a handler to the view. * * Items may be fields, filters, sort criteria, or arguments. * * @param string $display_id * The machine name of the display. * @param string $type * The type of handler being added. * @param string $table * The name of the table this handler is from. * @param string $field * The name of the field this handler is from. * @param array $options * (optional) Extra options for this instance. Defaults to an empty array. * @param string $id * (optional) A unique ID for this handler instance. Defaults to NULL, in * which case one will be generated. * * @return string * The unique ID for this handler instance. */ public function addHandler($display_id, $type, $table, $field, $options = array(), $id = NULL) { $types = $this::getHandlerTypes(); $this->setDisplay($display_id); $fields = $this->displayHandlers->get($display_id)->getOption($types[$type]['plural']); if (empty($id)) { $id = $this->generateHandlerId($field, $fields); } // If the desired type is not found, use the original value directly. $handler_type = !empty($types[$type]['type']) ? $types[$type]['type'] : $type; $fields[$id] = array('id' => $id, 'table' => $table, 'field' => $field) + $options; // Load the plugin ID if available. $data = Views::viewsData()->get($table); if (isset($data[$field][$handler_type]['id'])) { $fields[$id]['plugin_id'] = $data[$field][$handler_type]['id']; if ($definition = Views::pluginManager($handler_type)->getDefinition($fields[$id]['plugin_id'], FALSE)) { $fields[$id]['provider'] = isset($definition['provider']) ? $definition['provider'] : 'views'; } } $this->displayHandlers->get($display_id)->setOption($types[$type]['plural'], $fields); return $id; }
/** * Returns whether the base table is of a translatable entity type. * * @return bool * TRUE if the base table is of a translatable entity type, FALSE otherwise. */ protected function isBaseTableTranslatable() { $view_base_table = $this->view->storage->get('base_table'); $views_data = Views::viewsData()->get($view_base_table); if (!empty($views_data['table']['entity type'])) { $entity_type_id = $views_data['table']['entity type']; return \Drupal::entityManager()->getDefinition($entity_type_id)->isTranslatable(); } return FALSE; }
/** * {@inheritdoc} */ public static function getTableJoin($table, $base_table) { $data = Views::viewsData()->get($table); if (isset($data['table']['join'][$base_table])) { $join_info = $data['table']['join'][$base_table]; if (!empty($join_info['join_id'])) { $id = $join_info['join_id']; } else { $id = 'standard'; } $configuration = $join_info; // Fill in some easy defaults. if (empty($configuration['table'])) { $configuration['table'] = $table; } // If this is empty, it's a direct link. if (empty($configuration['left_table'])) { $configuration['left_table'] = $base_table; } if (isset($join_info['arguments'])) { foreach ($join_info['arguments'] as $key => $argument) { $configuration[$key] = $argument; } } $join = Views::pluginManager('join')->createInstance($id, $configuration); return $join; } }
/** * {@inheritdoc} */ public function buildForm(array $form, array &$form_state) { $view = $form_state['view']; $display_id = $form_state['display_id']; $type = $form_state['type']; $id = $form_state['id']; $form = array('options' => array('#tree' => TRUE, '#theme_wrappers' => array('container'), '#attributes' => array('class' => array('scroll'), 'data-drupal-views-scroll' => TRUE))); $executable = $view->getExecutable(); $save_ui_cache = FALSE; $executable->setDisplay($display_id); $item = $executable->getHandler($display_id, $type, $id); if ($item) { $handler = $executable->display_handler->getHandler($type, $id); if (empty($handler)) { $form['markup'] = array('#markup' => $this->t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $types = ViewExecutable::getHandlerTypes(); // If this item can come from the default display, show a dropdown // that lets the user choose which display the changes should apply to. if ($executable->display_handler->defaultableSections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } // A whole bunch of code to figure out what relationships are valid for // this item. $relationships = $executable->display_handler->getOption('relationships'); $relationship_options = array(); foreach ($relationships as $relationship) { // relationships can't link back to self. But also, due to ordering, // relationships can only link to prior relationships. if ($type == 'relationship' && $id == $relationship['id']) { break; } $relationship_handler = Views::handlerManager('relationship')->getHandler($relationship); // ignore invalid/broken relationships. if (empty($relationship_handler)) { continue; } // If this relationship is valid for this type, add it to the list. $data = Views::viewsData()->get($relationship['table']); if (isset($data[$relationship['field']]['relationship']['base']) && ($base = $data[$relationship['field']]['relationship']['base'])) { $base_fields = Views::viewsDataHelper()->fetchFields($base, $form_state['type'], $executable->display_handler->useGroupBy()); if (isset($base_fields[$item['table'] . '.' . $item['field']])) { $relationship_handler->init($executable, $executable->display_handler, $relationship); $relationship_options[$relationship['id']] = $relationship_handler->adminLabel(); } } } if (!empty($relationship_options)) { // Make sure the existing relationship is even valid. If not, force // it to none. $base_fields = Views::viewsDataHelper()->fetchFields($view->get('base_table'), $form_state['type'], $executable->display_handler->useGroupBy()); if (isset($base_fields[$item['table'] . '.' . $item['field']])) { $relationship_options = array_merge(array('none' => $this->t('Do not use a relationship')), $relationship_options); } $rel = empty($item['relationship']) ? 'none' : $item['relationship']; if (empty($relationship_options[$rel])) { // Pick the first relationship. $rel = key($relationship_options); // We want this relationship option to get saved even if the user // skips submitting the form. $executable->setHandlerOption($display_id, $type, $id, 'relationship', $rel); $save_ui_cache = TRUE; } $form['options']['relationship'] = array('#type' => 'select', '#title' => $this->t('Relationship'), '#options' => $relationship_options, '#default_value' => $rel, '#weight' => -500); } else { $form['options']['relationship'] = array('#type' => 'value', '#value' => 'none'); } $form['#title'] = $this->t('Configure @type: @item', array('@type' => $types[$type]['lstitle'], '@item' => $handler->adminLabel())); if (!empty($handler->definition['help'])) { $form['options']['form_description'] = array('#markup' => $handler->definition['help'], '#theme_wrappers' => array('container'), '#attributes' => array('class' => array('form-item description')), '#weight' => -1000); } $form['#section'] = $display_id . '-' . $type . '-' . $id; // Get form from the handler. $handler->buildOptionsForm($form['options'], $form_state); $form_state['handler'] = $handler; } $name = NULL; if (isset($form_state['update_name'])) { $name = $form_state['update_name']; } $view->getStandardButtons($form, $form_state, 'views_ui_config_item_form', $name); // Add a 'remove' button. $form['actions']['remove'] = array('#type' => 'submit', '#value' => $this->t('Remove'), '#submit' => array(array($this, 'remove')), '#limit_validation_errors' => array(array('override')), '#ajax' => array('path' => current_path())); } if ($save_ui_cache) { $view->cacheSet(); } return $form; }
/** * Get the instance of a plugin, for example style or row. * * @param string $type * The type of the plugin. * * @return \Drupal\views\Plugin\views\PluginBase */ public function getPlugin($type) { // Look up the plugin name to use for this instance. $options = $this->getOption($type); // Return now if no options have been loaded. if (empty($options) || !isset($options['type'])) { return; } // Query plugins allow specifying a specific query class per base table. if ($type == 'query') { $views_data = Views::viewsData()->get($this->view->storage->get('base_table')); $name = isset($views_data['table']['base']['query_id']) ? $views_data['table']['base']['query_id'] : 'views_query'; } else { $name = $options['type']; } // Plugin instances are stored on the display for re-use. if (!isset($this->plugins[$type][$name])) { $plugin = Views::pluginManager($type)->createInstance($name); // Initialize the plugin. $plugin->init($this->view, $this, $options['options']); $this->plugins[$type][$name] = $plugin; } return $this->plugins[$type][$name]; }
/** * {@inheritdoc} */ public function getCacheContexts() { $contexts = []; if (($views_data = Views::viewsData()->get($this->view->storage->get('base_table'))) && !empty($views_data['table']['entity type'])) { $entity_type_id = $views_data['table']['entity type']; $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id); $contexts = $entity_type->getListCacheContexts(); } return $contexts; }