public function page(Request $request, $search_api_page, $keyword = '') { $build = array(); /** @var $searchApiPage SearchApiPageInterface */ $searchApiPage = SearchApiPage::load($search_api_page); // Page title. $build['#title'] = $searchApiPage->label(); /** @var $searchApiIndex IndexInterface */ $searchApiIndex = Index::load($searchApiPage->getIndex()); // Create the query. $query = $searchApiIndex->query(['parse_mode' => 'direct', 'limit' => $searchApiPage->getLimit(), 'offset' => !is_null($request->get('page')) ? $request->get('page') : 0, 'search id' => 'search_api_page:' . $searchApiPage->id()]); // Keywords. if (!empty($keyword)) { $query->keys($keyword); } // Index fields. $query->setFulltextFields(array('rendered_item')); $result = $query->execute(); $items = $result->getResultItems(); /** @var $item ItemInterface*/ $results = array(); foreach ($items as $item) { list(, $path, $langcode) = explode(':', $item->getId()); list($entity_type, $id) = explode('/', $path); $entity = $this->entityManager()->getStorage($entity_type)->load($id); $results[] = $this->entityManager()->getViewBuilder($entity_type)->view($entity, 'teaser'); } if (!empty($results)) { $build['results'] = $results; // Build pager. pager_default_initialize($result->getResultCount(), $searchApiPage->getLimit()); $build['pager'] = array('#type' => 'pager'); } return $build; }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->drupalLogin($this->adminUser); $this->indexId = 'test_index'; Index::create(array('name' => 'Test index', 'id' => $this->indexId, 'status' => 1, 'datasource_settings' => array('entity:node' => array('plugin_id' => 'entity:node', 'settings' => array()))))->save(); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); $this->installSchema('system', array('router')); $this->installSchema('user', array('users_data')); $this->setUpExampleStructure(); $this->installConfig(array('search_api_test_db')); $this->insertExampleContent(); // Create a test server. $this->server = Server::create(array( 'name' => $this->randomString(), 'id' => $this->randomMachineName(), 'status' => 1, 'backend' => 'search_api_test_backend', )); $this->server->save(); $this->index = Index::load('database_search_index'); $this->index->setServer($this->server); }
/** * {@inheritdoc} */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); unset($form['break_phrase']); unset($form['not']); $index = Index::load(substr($this->table, 17)); $fields = array(); foreach ($index->getFields() as $key => $field) { $fields[$key] = $field->getLabel(); } if ($fields) { $form['fields'] = array( '#type' => 'select', '#title' => $this->t('Fields for similarity'), '#description' => $this->t('Select the fields that will be used for finding similar content. If no fields are selected, all available fields will be used.'), '#options' => $fields, '#size' => min(8, count($fields)), '#multiple' => TRUE, '#default_value' => $this->options['fields'], ); } else { $form['fields'] = array( '#type' => 'value', '#value' => array(), ); } }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->setUpExampleStructure(); Utility::getIndexTaskManager()->addItemsAll(Index::load($this->indexId)); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); // Create a test server. $this->server = Server::create(array( 'name' => $this->randomString(), 'id' => $this->randomMachineName(), 'status' => 1, 'backend' => 'search_api_test_backend', )); $this->server->save(); // Create a test index. $this->index = Index::create(array( 'name' => $this->randomString(), 'id' => $this->randomMachineName(), 'status' => 1, 'datasources' => array('entity:' . $this->testEntityTypeId), 'tracker' => 'default', 'server' => $this->server->id(), 'options' => array('index_directly' => FALSE), )); $this->index->save(); Utility::getIndexTaskManager()->addItemsAll($this->index); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); // Enable translation for the entity_test module. \Drupal::state()->set('entity_test.translation', TRUE); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); $this->installEntitySchema('entity_test_mul'); // Create the default languages. $this->installConfig(array('language')); $this->langcodes = array(); for ($i = 0; $i < 3; ++$i) { /** @var \Drupal\language\Entity\ConfigurableLanguage $language */ $language = ConfigurableLanguage::create(array('id' => 'l' . $i, 'label' => 'language - ' . $i, 'weight' => $i)); $this->langcodes[$i] = $language->getId(); $language->save(); } // Do not use a batch for tracking the initial items after creating an // index when running the tests via the GUI. Otherwise, it seems Drupal's // Batch API gets confused and the test fails. \Drupal::state()->set('search_api_use_tracking_batch', FALSE); // Create a test server. $this->server = Server::create(array('name' => 'Test Server', 'id' => 'test_server', 'status' => 1, 'backend' => 'search_api_test_backend')); $this->server->save(); // Create a test index. $this->index = Index::create(array('name' => 'Test Index', 'id' => 'test_index', 'status' => 1, 'datasource_settings' => array('entity:' . $this->testEntityTypeId => array('plugin_id' => 'entity:' . $this->testEntityTypeId, 'settings' => array())), 'tracker_settings' => array('default' => array('plugin_id' => 'default', 'settings' => array())), 'server' => $this->server->id(), 'options' => array('index_directly' => FALSE))); $this->index->save(); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->setUpExampleStructure(); \Drupal::getContainer()->get('search_api.index_task_manager')->addItemsAll(Index::load($this->indexId)); $this->insertExampleContent(); $this->indexItems($this->indexId); }
/** * Performs setup tasks before each individual test method is run. * * Installs commonly used schemas and sets up a search server and an index, * with the specified processor enabled. * * @param string|null $processor * (optional) The plugin ID of the processor that should be set up for * testing. */ public function setUp($processor = NULL) { parent::setUp(); $this->installSchema('node', array('node_access')); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); $server_name = $this->randomMachineName(); $this->server = Server::create(array( 'id' => strtolower($server_name), 'name' => $server_name, 'status' => TRUE, 'backend' => 'search_api_db', 'backend_config' => array( 'min_chars' => 3, 'database' => 'default:default', ), )); $this->server->save(); $index_name = $this->randomMachineName(); $this->index = Index::create(array( 'id' => strtolower($index_name), 'name' => $index_name, 'status' => TRUE, 'datasources' => array('entity:comment', 'entity:node'), 'server' => $server_name, 'tracker' => 'default', )); $this->index->setServer($this->server); $this->index->setOption('fields', array( 'entity:comment/subject' => array( 'type' => 'text', ), 'entity:node/title' => array( 'type' => 'text', ), )); if ($processor) { $this->index->setOption('processors', array( $processor => array( 'processor_id' => $processor, 'weights' => array(), 'settings' => array(), ), )); /** @var \Drupal\search_api\Processor\ProcessorPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.search_api.processor'); $this->processor = $plugin_manager->createInstance($processor, array('index' => $this->index)); } $this->index->save(); \Drupal::configFactory() ->getEditable('search_api.settings') ->set('tracking_page_size', 100) ->save(); Utility::getIndexTaskManager()->addItemsAll($this->index); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); // Add a test server and index. $this->getTestServer(); $this->getTestIndex(); // Set up example structure and content and populate the test index with // that content. $this->setUpExampleStructure(); $this->insertExampleContent(); \Drupal::getContainer()->get('search_api.index_task_manager')->addItemsAll(Index::load($this->indexId)); $this->indexItems($this->indexId); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->state = $this->container->get('state'); $this->installEntitySchema('user'); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); // Create a test server. $this->server = Server::create(array('name' => $this->randomString(), 'id' => $this->randomMachineName(), 'status' => 1, 'backend' => 'search_api_test_backend')); $this->server->save(); // Create a test index. $this->index = Index::create(array('name' => $this->randomString(), 'id' => $this->randomMachineName(), 'status' => 1, 'datasources' => array('entity:user'), 'tracker' => 'default', 'server' => $this->server->id(), 'options' => array('index_directly' => FALSE))); $this->index->save(); $this->serverTaskManager = $this->container->get('search_api.server_task_manager'); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->installSchema('system', 'key_value_expire'); // The server tasks manager is needed when removing a server. $mock = $this->getMock('Drupal\\search_api\\Task\\ServerTaskManagerInterface'); $this->container->set('search_api.server_task_manager', $mock); // Create the index object, but don't save it yet since we want to change // its settings anyways in every test. $this->index = Index::create(array('id' => 'test_index', 'name' => 'Test index', 'tracker_settings' => array('default' => array('plugin_id' => 'default', 'settings' => array())), 'datasource_settings' => array('entity:user' => array('plugin_id' => 'entity:user', 'settings' => array())))); // Use a search server as the dependency, since we have that available // anyways. The entity type should not matter at all, though. $this->dependency = Server::create(array('id' => 'dependency', 'name' => 'Test dependency', 'backend' => 'search_api_test_backend')); $this->dependency->save(); }
/** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); /* @var $search_api_page \Drupal\search_api_page\SearchApiPageInterface */ $search_api_page = $this->entity; $form['label'] = array('#type' => 'textfield', '#title' => $this->t('Title'), '#maxlength' => 255, '#default_value' => $search_api_page->label(), '#required' => TRUE, '#description' => $this->t('This will also be used as the page title.')); $form['id'] = array('#type' => 'machine_name', '#default_value' => $search_api_page->id(), '#machine_name' => array('exists' => '\\Drupal\\search_api_page\\Entity\\SearchApiPage::load'), '#disabled' => !$search_api_page->isNew()); // Default index and states. $default_index = $search_api_page->getIndex(); $default_index_states = array('visible' => array(':input[name="index"]' => array('value' => $default_index))); $index_options = array(); $search_api_indexes = $this->entityTypeManager->getStorage('search_api_index')->loadMultiple(); /* @var $search_api_index \Drupal\search_api\IndexInterface */ foreach ($search_api_indexes as $search_api_index) { $index_options[$search_api_index->id()] = $search_api_index->label(); } $form['index_fieldset'] = array('#type' => 'fieldset', '#title' => $this->t('Index')); $form['index_fieldset']['index'] = array('#type' => 'select', '#title' => $this->t('Search API index'), '#options' => $index_options, '#default_value' => $default_index, '#required' => TRUE); $form['index_fieldset']['previous_index'] = array('#type' => 'value', '#value' => $default_index); $searched_fields = $search_api_page->getFullTextFields(); $form['index_fieldset']['searched_fields'] = array('#type' => 'select', '#multiple' => TRUE, '#options' => $searched_fields, '#size' => min(4, count($searched_fields)), '#title' => $this->t('Searched fields'), '#description' => $this->t('Select the fields that will be searched. If no fields are selected, all available fulltext fields will be searched.'), '#default_value' => $search_api_page->getSearchedFields(), '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset'] = array('#type' => 'fieldset', '#title' => $this->t('Page'), '#states' => array('visible' => array(':input[name="index"]' => array('value' => $default_index))), '#access' => !empty($default_index)); $form['page_fieldset']['path'] = array('#type' => 'textfield', '#title' => $this->t('Path'), '#maxlength' => 255, '#default_value' => $search_api_page->getPath(), '#description' => $this->t("Do not include a trailing slash."), '#required' => TRUE, '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset']['previous_path'] = array('#type' => 'value', '#value' => $search_api_page->getPath(), '#access' => !empty($default_index)); $form['page_fieldset']['clean_url'] = array('#type' => 'checkbox', '#title' => $this->t('Use clean URL\'s'), '#default_value' => $search_api_page->getCleanUrl(), '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset']['previous_clean_url'] = array('#type' => 'value', '#default_value' => $search_api_page->getCleanUrl()); $form['page_fieldset']['limit'] = array('#type' => 'number', '#title' => $this->t('Limit'), '#default_value' => $search_api_page->getLimit(), '#min' => 1, '#required' => TRUE, '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset']['show_search_form'] = array('#type' => 'checkbox', '#title' => $this->t('Show search form above results'), '#default_value' => $search_api_page->showSearchForm(), '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset']['show_all_when_no_keys'] = array('#type' => 'checkbox', '#title' => $this->t('Show all results when no search is performed'), '#default_value' => $search_api_page->showAllResultsWhenNoSearchIsPerformed(), '#access' => !empty($default_index), '#states' => $default_index_states); $form['page_fieldset']['style'] = array('#type' => 'radios', '#title' => $this->t('Style'), '#options' => array('view_modes' => $this->t('View modes'), 'search_results' => $this->t('Search results')), '#default_value' => $search_api_page->getStyle(), '#required' => TRUE, '#access' => !empty($default_index), '#states' => $default_index_states); if (!empty($default_index)) { $form['view_mode_configuration'] = array('#type' => 'fieldset', '#tree' => TRUE, '#title' => $this->t('View modes'), '#states' => array('visible' => array(':input[name="style"]' => array('value' => 'view_modes'), ':input[name="index"]' => array('value' => $default_index)))); /* @var $index \Drupal\search_api\IndexInterface */ $index = Index::load($search_api_page->getIndex()); $view_mode_configuration = $search_api_page->getViewModeConfiguration(); foreach ($index->getDatasources() as $datasource_id => $datasource) { $bundles = $datasource->getBundles(); foreach ($bundles as $bundle_id => $bundle_label) { $view_modes = $datasource->getViewModes($bundle_id); $form['view_mode_configuration'][$datasource_id . '_' . $bundle_id] = array('#type' => 'select', '#title' => $this->t('View mode for %datasource » %bundle', array('%datasource' => $datasource->label(), '%bundle' => $bundle_label)), '#options' => $view_modes); if (isset($view_mode_configuration[$datasource_id . '_' . $bundle_id])) { $form['view_mode_configuration'][$datasource_id . '_' . $bundle_id]['#default_value'] = $view_mode_configuration[$datasource_id . '_' . $bundle_id]; } } } } return $form; }
/** * {@inheritdoc} */ public function fillFacetsWithResults($facets) { // Check if there are results in the static cache. $results = $this->searchApiResultsCache->getResults($this->pluginId); // If there are no results, execute the search page and check for results // again. This happens when a page or block is cached, so Search API has // not fired an actual search. if (!$results) { list(, $search_api_page) = explode(':', $this->pluginId); /* @var $search_api_page \Drupal\search_api_page\SearchApiPageInterface */ $search_api_page = SearchApiPageEntity::load($search_api_page); /* @var $search_api_index \Drupal\search_api\IndexInterface */ $search_api_index = Index::load($search_api_page->getIndex()); // Create the query. $query = $search_api_index->query(['parse_mode' => 'direct', 'limit' => $search_api_page->getLimit(), 'offset' => isset($_GET['page']) ? $_GET['page'] : 0, 'search id' => 'search_api_page:' . $search_api_page->id()]); // Keys. $keys = \Drupal::request()->get('keys'); if (!empty($keys)) { $query->keys($keys); } // Index fields. $query->setFulltextFields($search_api_page->getSearchedFields()); // Execute the query. $results = $query->execute(); } // If we got results from the cache, this is the first code executed in this // method, so it's good to double check that we can actually work with // $results. if ($results instanceof ResultSetInterface) { // Get our facet data from the results. $facet_results = $results->getExtraData('search_api_facets'); // Loop over each facet and execute the build method from the given query // type. foreach ($facets as $facet) { if (isset($facet_results[$facet->getFieldIdentifier()])) { $configuration = array('query' => NULL, 'facet' => $facet, 'results' => $facet_results[$facet->getFieldIdentifier()]); // Get the Facet Specific Query Type so we can process the results // using the build() function of the query type. $query_type = $this->queryTypePluginManager->createInstance($facet->getQueryType(), $configuration); $query_type->build(); } } } }
/** * Tests tracking of items when saving an index through the CLI. */ public function testItemTracking() { EntityTest::create(array('name' => 'foo bar baz föö smile' . json_decode('"\\u1F601"'), 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('Orange', 'orange', 'örange', 'Orange'), 'category' => 'item_category'))->save(); EntityTest::create(array('name' => 'foo bar baz föö smile', 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('strawberry', 'llama'), 'category' => 'item_category'))->save(); // Create a test index. /** @var \Drupal\search_api\IndexInterface $index */ $index = Index::create(array('name' => 'Test index', 'id' => 'index', 'status' => 1, 'datasource_settings' => array('entity:entity_test' => array('plugin_id' => 'entity:entity_test', 'settings' => array())), 'tracker_settings' => array('default' => array('plugin_id' => 'default', 'settings' => array())), 'server' => $this->server->id(), 'options' => array('index_directly' => TRUE))); $index->save(); $total_items = $index->getTrackerInstance()->getTotalItemsCount(); $indexed_items = $index->getTrackerInstance()->getIndexedItemsCount(); $this->assertEquals(2, $total_items, 'The 2 items are tracked.'); $this->assertEquals(0, $indexed_items, 'No items are indexed'); EntityTest::create(array('name' => 'foo bar baz föö smile', 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('strawberry', 'llama'), 'category' => 'item_category'))->save(); EntityTest::create(array('name' => 'foo bar baz föö smile', 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('strawberry', 'llama'), 'category' => 'item_category'))->save(); $total_items = $index->getTrackerInstance()->getTotalItemsCount(); $indexed_items = $index->getTrackerInstance()->getIndexedItemsCount(); $this->assertEquals(4, $total_items, 'All 4 items are tracked.'); $this->assertEquals(2, $indexed_items, '2 items are indexed'); }
/** * Performs setup tasks before each individual test method is run. * * Installs commonly used schemas and sets up a search server and an index, * with the specified processor enabled. * * @param string|null $processor * (optional) The plugin ID of the processor that should be set up for * testing. */ public function setUp($processor = NULL) { parent::setUp(); $this->installSchema('node', array('node_access')); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); $this->installEntitySchema('user'); $this->installEntitySchema('node'); $this->installEntitySchema('comment'); $this->installConfig(array('field')); Action::create(['id' => 'foo', 'label' => 'Foobaz', 'plugin' => 'comment_publish_action'])->save(); \Drupal::configFactory()->getEditable('search_api.settings')->set('tracking_page_size', 100)->save(); // Do not use a batch for tracking the initial items after creating an // index when running the tests via the GUI. Otherwise, it seems Drupal's // Batch API gets confused and the test fails. \Drupal::state()->set('search_api_use_tracking_batch', FALSE); $this->server = Server::create(array('id' => 'server', 'name' => 'Server & Name', 'status' => TRUE, 'backend' => 'search_api_db', 'backend_config' => array('min_chars' => 3, 'database' => 'default:default'))); $this->server->save(); $this->index = Index::create(array('id' => 'index', 'name' => 'Index name', 'status' => TRUE, 'datasource_settings' => array('entity:comment' => array('plugin_id' => 'entity:comment', 'settings' => array()), 'entity:node' => array('plugin_id' => 'entity:node', 'settings' => array())), 'server' => 'server', 'tracker_settings' => array('default' => array('plugin_id' => 'default', 'settings' => array())))); $this->index->setServer($this->server); $field_subject = new Field($this->index, 'subject'); $field_subject->setType('text'); $field_subject->setPropertyPath('subject'); $field_subject->setDatasourceId('entity:comment'); $field_subject->setLabel('Subject'); $field_title = new Field($this->index, 'title'); $field_title->setType('text'); $field_title->setPropertyPath('title'); $field_title->setDatasourceId('entity:node'); $field_title->setLabel('Title'); $this->index->addField($field_subject); $this->index->addField($field_title); if ($processor) { /** @var \Drupal\search_api\Processor\ProcessorPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.search_api.processor'); $this->processor = $plugin_manager->createInstance($processor, array('index' => $this->index)); $this->index->addProcessor($this->processor); } $this->index->save(); }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->installSchema('search_api', array('search_api_item', 'search_api_task')); $this->installSchema('system', array('router')); $this->installSchema('user', array('users_data')); $this->installEntitySchema('entity_test'); // Do not use a batch for tracking the initial items after creating an // index when running the tests via the GUI. Otherwise, it seems Drupal's // Batch API gets confused and the test fails. \Drupal::state()->set('search_api_use_tracking_batch', FALSE); $this->installConfig(array('search_api_test_db')); // Create test entities. $this->entities[1] = EntityTest::create(array('name' => 'foo bar baz föö smile' . json_decode('"\\u1F601"'), 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('Orange', 'orange', 'örange', 'Orange'), 'category' => 'item_category')); $this->entities[2] = EntityTest::create(array('name' => 'foo bar baz föö smile', 'body' => 'test test case Case casE', 'type' => 'item', 'keywords' => array('strawberry', 'llama'), 'category' => 'item_category')); $this->entities[1]->save(); $this->entities[2]->save(); // Create a test server. $this->server = Server::create(array('name' => 'Server test ~', 'id' => 'test', 'status' => 1, 'backend' => 'search_api_test_backend')); $this->server->save(); $this->index = Index::load('database_search_index'); $this->index->setServer($this->server); }
/** * Retrieves the search index used by this test. * * @return \Drupal\search_api\IndexInterface * The search index. */ protected function getIndex() { return Index::load($this->indexId); }
/** * Loads the search index belonging to the given Views base table. * * @param string $table * The Views base table ID. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * (optional) The entity manager to use. * * @return \Drupal\search_api\IndexInterface|null * The requested search index, or NULL if it could not be found and loaded. */ public static function getIndexFromTable($table, EntityManagerInterface $entity_manager = NULL) { if (substr($table, 0, 17) == 'search_api_index_') { $index_id = substr($table, 17); if ($entity_manager) { return $entity_manager->getStorage('search_api_index')->load($index_id); } return Index::load($index_id); } return NULL; }
/** * Retrieves a list of all available fulltext fields. * * @return string[] * An options list of fulltext field identifiers mapped to their prefixed * labels. */ protected function getFulltextFields() { $fields = array(); $index = Index::load(substr($this->table, 17)); $fields_info = $index->getFields(); foreach ($index->getFulltextFields() as $field_id) { $fields[$field_id] = $fields_info[$field_id]->getPrefixedLabel(); } return $fields; }
/** * Loads the search index belonging to the given Views base table. * * @param string $table * The Views base table ID. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * (optional) The entity type manager to use. * * @return \Drupal\search_api\IndexInterface|null * The requested search index, or NULL if it could not be found and loaded. */ public static function getIndexFromTable($table, EntityTypeManagerInterface $entity_type_manager = NULL) { // @todo Instead use Views::viewsData() – injected, too – to load the base // table definition and use the "index" (or maybe rename to // "search_api_index") field from there. if (substr($table, 0, 17) == 'search_api_index_') { $index_id = substr($table, 17); if ($entity_type_manager) { return $entity_type_manager->getStorage('search_api_index')->load($index_id); } return Index::load($index_id); } return NULL; }
/** * Retrieves all indexes that are configured to index the given entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity for which to check. * * @return \Drupal\search_api\IndexInterface[] * All indexes that are configured to index the given entity (using this * datasource class). */ public static function getIndexesForEntity(ContentEntityInterface $entity) { $entity_type = $entity->getEntityTypeId(); $datasource_id = 'entity:' . $entity_type; $entity_bundle = $entity->bundle(); $index_names = \Drupal::entityQuery('search_api_index')->condition('datasources.*', $datasource_id)->execute(); if (!$index_names) { return array(); } // Needed for PhpStorm. See https://youtrack.jetbrains.com/issue/WI-23395. /** @var \Drupal\search_api\IndexInterface[] $indexes */ $indexes = Index::loadMultiple($index_names); // If the datasource's entity type supports bundles, we have to filter the // indexes for whether they also include the specific bundle of the given // entity. Otherwise, we are done. if ($entity_type !== $entity_bundle) { foreach ($indexes as $index_id => $index) { try { $config = $index->getDatasource($datasource_id)->getConfiguration(); $default = !empty($config['default']); $bundle_set = !empty($config['bundles'][$entity_bundle]); if ($default == $bundle_set) { unset($indexes[$index_id]); } } catch (SearchApiException $e) { unset($indexes[$index_id]); } } } return $indexes; }
/** * Processes all pending index tasks inside a batch run. * * @param array $context * The current batch context. * @param \Drupal\Core\Config\ConfigImporter $config_importer * The config importer. */ public static function processIndexTasks(array &$context, ConfigImporter $config_importer) { $index_task_manager = \Drupal::getContainer()->get('search_api.index_task_manager'); if (!isset($context['sandbox']['indexes'])) { $context['sandbox']['indexes'] = array(); $indexes = \Drupal::entityTypeManager()->getStorage('search_api_index')->loadByProperties(array('status' => TRUE)); $deleted = $config_importer->getUnprocessedConfiguration('delete'); /** @var \Drupal\search_api\IndexInterface $index */ foreach ($indexes as $index_id => $index) { if (!$index_task_manager->isTrackingComplete($index) && !in_array($index->getConfigDependencyName(), $deleted)) { $context['sandbox']['indexes'][] = $index_id; } } $context['sandbox']['total'] = count($context['sandbox']['indexes']); if (!$context['sandbox']['total']) { $context['finished'] = 1; return; } } $index_id = array_shift($context['sandbox']['indexes']); $index = Index::load($index_id); $added = $index_task_manager->addItemsOnce($index); if ($added !== NULL) { array_unshift($context['sandbox']['indexes'], $index_id); } if (empty($context['sandbox']['indexes'])) { $context['finished'] = 1; } else { $finished = $context['sandbox']['total'] - count($context['sandbox']['indexes']); $context['finished'] = $finished / $context['sandbox']['total']; $args = array('%index' => $index->label(), '@num' => $finished + 1, '@total' => $context['sandbox']['total']); $context['message'] = \Drupal::translation()->translate('Tracking items for search index %index (@num of @total)', $args); } }
/** * Counts the number of tracked items in the test index. * * @return int * The number of tracked items in the test index. */ protected function countTrackedItems() { /** @var \Drupal\search_api\IndexInterface $index */ $index = Index::load($this->indexId); return $index->getTrackerInstance()->getTotalItemsCount(); }
/** * Indexes all (unindexed) items on the specified index. * * @param string $index_id * The ID of the index on which items should be indexed. * * @return int * The number of successfully indexed items. */ protected function indexItems($index_id) { $index = Index::load($index_id); return $index->index(); }
/** * {@inheritdoc} */ public function removeIndex($index) { if (!is_object($index)) { // If the index got deleted, create a dummy to simplify the code. Since we // can't know, we assume the index was read-only, just to be on the safe // side. $index = Index::create(array( 'id' => $index, 'read_only' => TRUE, )); } $db_info = $this->getIndexDbInfo($index); try { if (!isset($db_info['field_tables']) && !isset($db_info['index_table'])) { return; } // Don't delete the index data of read-only indexes. if (!$index->isReadOnly()) { foreach ($db_info['field_tables'] as $field) { if ($this->database->schema()->tableExists($field['table'])) { $this->database->schema()->dropTable($field['table']); } } if ($this->database->schema()->tableExists($db_info['index_table'])) { $this->database->schema()->dropTable($db_info['index_table']); } } $this->getKeyValueStore()->delete($index->id()); } // The database operations might throw PDO or other exceptions, so we catch // them all and re-wrap them appropriately. catch (\Exception $e) { throw new SearchApiException($e->getMessage(), $e->getCode(), $e); } }
/** * {@inheritdoc} */ public function removeIndex($index) { if (!is_object($index)) { // If the index got deleted, create a dummy to simplify the code. Since we // can't know, we assume the index was read-only, just to be on the safe // side. $index = Index::create(array('id' => $index, 'read_only' => TRUE)); } try { if (!isset($this->configuration['field_tables'][$index->id()]) && !isset($this->configuration['index_tables'][$index->id()])) { return; } // Don't delete the index data of read-only indexes. if (!$index->isReadOnly()) { foreach ($this->configuration['field_tables'][$index->id()] as $field) { if ($this->database->schema()->tableExists($field['table'])) { $this->database->schema()->dropTable($field['table']); } } if ($this->database->schema()->tableExists($this->configuration['index_tables'][$index->id()])) { $this->database->schema()->dropTable($this->configuration['index_tables'][$index->id()]); } } unset($this->configuration['field_tables'][$index->id()]); unset($this->configuration['index_tables'][$index->id()]); $this->server->save(); } catch (\Exception $e) { throw new SearchApiException($e->getMessage(), $e->getCode(), $e); } }
/** * {@inheritdoc} */ protected function checkModuleUninstall() { // See whether clearing the server works. // Regression test for #2156151. $server = Server::load($this->serverId); $index = Index::load($this->indexId); $server->deleteAllItems($index); // Deleting items take at least 1 second for Solr to parse it so that drupal // doesn't get timeouts while waiting for Solr. Lets give it 2 seconds to // make sure we are in bounds. sleep(2); $query = $this->buildSearch(); $results = $query->execute(); $this->assertEqual($results->getResultCount(), 0, 'Clearing the server worked correctly.'); }
/** * Tests whether removing the configuration again works as it should. */ protected function checkModuleUninstall() { // See whether clearing the server works. // Regression test for #2156151. $server = Server::load($this->serverId); $index = Index::load($this->indexId); $server->deleteAllIndexItems($index); $query = $this->buildSearch(); $results = $query->execute(); $this->assertEqual($results->getResultCount(), 0, 'Clearing the server worked correctly.'); $table = 'search_api_db_' . $this->indexId; $this->assertTrue(db_table_exists($table), 'The index tables were left in place.'); // Remove first the index and then the server. $index->setServer(); $index->save(); $server = Server::load($this->serverId); $this->assertEqual($server->getBackendConfig()['field_tables'], array(), 'The index was successfully removed from the server.'); $this->assertFalse(db_table_exists($table), 'The index tables were deleted.'); $server->delete(); // Uninstall the module. \Drupal::service('module_installer')->uninstall(array('search_api_db'), FALSE); #\Drupal::moduleHandler()->uninstall(array('search_api_db'), FALSE); $this->assertFalse(\Drupal::moduleHandler()->moduleExists('search_api_db'), 'The Database Search module was successfully disabled.'); $prefix = \Drupal::database()->prefixTables('{search_api_db_}') . '%'; $this->assertEqual(\Drupal::database()->schema()->findTables($prefix), array(), 'The Database Search module was successfully uninstalled.'); }
/** * {@inheritdoc} */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { try { parent::init($view, $display, $options); $this->fields = array(); if (substr($view->storage->get('base_table'), 0, 17) == 'search_api_index_') { $id = substr($view->storage->get('base_table'), 17); $this->index = Index::load($id); $this->query = $this->index->query(array('parse mode' => $this->options['parse_mode'])); } else { $this->abort(SafeMarkup::format('View %view is not based on Search API but tries to use its query plugin.', array('%view' => $view->storage->label()))); } } catch (\Exception $e) { $this->abort($e->getMessage()); } }