/**
  * Creates a new processor object for use in the tests.
  */
 protected function setUp()
 {
     parent::setUp();
     $this->processor = new RoleFilter(array(), 'role_filter', array());
     /** @var \Drupal\search_api\IndexInterface $index */
     $index = $this->getMock('Drupal\\search_api\\IndexInterface');
     $node_datasource = $this->getMock('Drupal\\search_api\\Datasource\\DatasourceInterface');
     $node_datasource->expects($this->any())->method('getEntityTypeId')->will($this->returnValue('node'));
     /** @var \Drupal\search_api\Datasource\DatasourceInterface $node_datasource */
     $user_datasource = $this->getMock('Drupal\\search_api\\Datasource\\DatasourceInterface');
     $user_datasource->expects($this->any())->method('getEntityTypeId')->will($this->returnValue('user'));
     /** @var \Drupal\search_api\Datasource\DatasourceInterface $user_datasource */
     $item = Utility::createItem($index, Utility::createCombinedId('entity:node', '1:en'), $node_datasource);
     $node = $this->getMockBuilder('Drupal\\Tests\\search_api\\TestNodeInterface')->disableOriginalConstructor()->getMock();
     /** @var \Drupal\node\NodeInterface $node */
     $item->setOriginalObject(EntityAdapter::createFromEntity($node));
     $this->items[$item->getId()] = $item;
     $item = Utility::createItem($index, Utility::createCombinedId('entity:user', '1:en'), $user_datasource);
     $account1 = $this->getMockBuilder('Drupal\\Tests\\search_api\\TestUserInterface')->disableOriginalConstructor()->getMock();
     $account1->expects($this->any())->method('getRoles')->will($this->returnValue(array('authenticated' => 'authenticated', 'editor' => 'editor')));
     /** @var \Drupal\user\UserInterface $account1 */
     $item->setOriginalObject(EntityAdapter::createFromEntity($account1));
     $this->items[$item->getId()] = $item;
     $item = Utility::createItem($index, Utility::createCombinedId('entity:user', '2:en'), $user_datasource);
     $account2 = $this->getMockBuilder('Drupal\\Tests\\search_api\\TestUserInterface')->disableOriginalConstructor()->getMock();
     $account2->expects($this->any())->method('getRoles')->will($this->returnValue(array('authenticated' => 'authenticated')));
     /** @var \Drupal\user\UserInterface $account2 */
     $item->setOriginalObject(EntityAdapter::createFromEntity($account2));
     $this->items[$item->getId()] = $item;
 }
 /**
  * Creates a certain number of test items.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index that should be used for the items.
  * @param int $count
  *   The number of items to create.
  * @param array[] $fields
  *   The fields to create on the items, with keys being combined property
  *   paths and values being arrays with properties to set on the field.
  * @param \Drupal\Core\TypedData\ComplexDataInterface|null $object
  *   (optional) The object to set on each item as the "original object".
  * @param array|null $datasource_ids
  *   (optional) An array of datasource IDs to use for the items, in that order
  *   (starting again from the front if necessary).
  *
  * @return \Drupal\search_api\Item\ItemInterface[]
  *   An array containing the requested test items.
  */
 public function createItems(IndexInterface $index, $count, array $fields, ComplexDataInterface $object = NULL, array $datasource_ids = array('entity:node'))
 {
     $datasource_count = count($datasource_ids);
     $items = array();
     for ($i = 0; $i < $count; ++$i) {
         $datasource_id = $datasource_ids[$i % $datasource_count];
         $this->itemIds[$i] = $item_id = Utility::createCombinedId($datasource_id, $i + 1 . ':en');
         $item = Utility::createItem($index, $item_id);
         if (isset($object)) {
             $item->setOriginalObject($object);
         }
         foreach ($fields as $combined_property_path => $field_info) {
             list($field_info['datasource_id'], $field_info['property_path']) = Utility::splitCombinedId($combined_property_path);
             // Only add fields of the right datasource.
             if (isset($field_info['datasource_id']) && $field_info['datasource_id'] != $datasource_id) {
                 continue;
             }
             $field_id = Utility::getNewFieldId($index, $field_info['property_path']);
             $field = Utility::createField($index, $field_id, $field_info);
             $item->setField($field_id, $field);
         }
         $item->setFieldsExtracted(TRUE);
         $items[$item_id] = $item;
     }
     return $items;
 }
 /**
  * Creates a new processor object for use in the tests.
  */
 protected function setUp()
 {
     parent::setUp();
     $this->processor = new NodeStatus(array(), 'node_status', array());
     $datasource = $this->getMock('Drupal\\search_api\\Datasource\\DatasourceInterface');
     $datasource->expects($this->any())->method('getEntityTypeId')->will($this->returnValue('node'));
     /** @var \Drupal\search_api\Datasource\DatasourceInterface $datasource */
     $index = $this->getMock('Drupal\\search_api\\IndexInterface');
     $index->expects($this->any())->method('getDatasources')->will($this->returnValue(array($datasource)));
     /** @var \Drupal\search_api\IndexInterface $index */
     $item = Utility::createItem($index, Utility::createCombinedId('entity:node', '1:en'), $datasource);
     $unpublished_node = $this->getMockBuilder('Drupal\\Tests\\search_api\\TestNodeInterface')->disableOriginalConstructor()->getMock();
     $unpublished_node->expects($this->any())->method('isPublished')->will($this->returnValue(FALSE));
     /** @var \Drupal\node\NodeInterface $unpublished_node */
     $item->setOriginalObject(EntityAdapter::createFromEntity($unpublished_node));
     $this->items[$item->getId()] = $item;
     $item = Utility::createItem($index, Utility::createCombinedId('entity:node', '2:en'), $datasource);
     $published_node = $this->getMockBuilder('Drupal\\Tests\\search_api\\TestNodeInterface')->disableOriginalConstructor()->getMock();
     $published_node->expects($this->any())->method('isPublished')->will($this->returnValue(TRUE));
     /** @var \Drupal\node\NodeInterface $published_node */
     $item->setOriginalObject(EntityAdapter::createFromEntity($published_node));
     $this->items[$item->getId()] = $item;
 }
Beispiel #4
0
 /**
  * {@inheritdoc}
  */
 public function search(QueryInterface $query)
 {
     $this->checkError(__FUNCTION__);
     $results = Utility::createSearchResultSet($query);
     $result_items = array();
     $datasources = $query->getIndex()->getDatasources();
     /** @var \Drupal\search_api\Datasource\DatasourceInterface $datasource */
     $datasource = reset($datasources);
     $datasource_id = $datasource->getPluginId();
     if ($query->getKeys() && $query->getKeys()[0] == 'test') {
         $item_id = Utility::createCombinedId($datasource_id, '1');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(2);
         $item->setExcerpt('test');
         $result_items[$item_id] = $item;
     } elseif ($query->getOption('search_api_mlt')) {
         $item_id = Utility::createCombinedId($datasource_id, '2');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(2);
         $item->setExcerpt('test test');
         $result_items[$item_id] = $item;
     } else {
         $item_id = Utility::createCombinedId($datasource_id, '1');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(1);
         $result_items[$item_id] = $item;
         $item_id = Utility::createCombinedId($datasource_id, '2');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(1);
         $result_items[$item_id] = $item;
     }
     $results->setResultCount(count($result_items));
     return $results;
 }
 /**
  * Creates a certain number of test items.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index that should be used for the items.
  * @param int $count
  *   The number of items to create.
  * @param array[] $fields
  *   The fields to create on the items, with keys being field IDs and values
  *   being arrays with the following information:
  *   - type: The type to set for the field.
  *   - values: (optional) The values to set for the field.
  * @param \Drupal\Core\TypedData\ComplexDataInterface|null $object
  *   (optional) The object to set on each item as the "original object".
  * @param array|null $datasource_ids
  *   (optional) An array of datasource IDs to use for the items, in that order
  *   (starting again from the front if necessary). Defaults to using
  *   "entity:node" for all items.
  *
  * @return \Drupal\search_api\Item\ItemInterface[]
  *   An array containing the requested test items.
  */
 public function createItems(IndexInterface $index, $count, array $fields, ComplexDataInterface $object = NULL, array $datasource_ids = NULL)
 {
     if (!isset($datasource_ids)) {
         $datasource_ids = array('entity:node');
     }
     $datasource_count = count($datasource_ids);
     $items = array();
     for ($i = 0; $i < $count; ++$i) {
         $datasource_id = $datasource_ids[$i % $datasource_count];
         $this->itemIds[$i] = $item_id = Utility::createCombinedId($datasource_id, $i + 1 . ':en');
         $item = Utility::createItem($index, $item_id);
         if (isset($object)) {
             $item->setOriginalObject($object);
         }
         foreach ($fields as $field_id => $field_info) {
             // Only add fields of the right datasource.
             list($field_datasource_id) = Utility::splitCombinedId($field_id);
             if (isset($field_datasource_id) && $field_datasource_id != $datasource_id) {
                 continue;
             }
             $field = Utility::createField($index, $field_id)->setType($field_info['type']);
             if (isset($field_info['values'])) {
                 $field->setValues($field_info['values']);
             }
             $item->setField($field_id, $field);
         }
         $item->setFieldsExtracted(TRUE);
         $items[$item_id] = $item;
     }
     return $items;
 }
Beispiel #6
0
  /**
   * {@inheritdoc}
   */
  public function search(QueryInterface $query) {
    $this->ignored = $this->warnings = array();
    $index = $query->getIndex();
    $db_info = $this->getIndexDbInfo($index);

    if (!isset($db_info['field_tables'])) {
      throw new SearchApiException(new FormattableMarkup('Unknown index @id.', array('@id' => $index->id())));
    }
    $fields = $this->getFieldInfo($index);

    $db_query = $this->createDbQuery($query, $fields);

    $results = Utility::createSearchResultSet($query);

    $skip_count = $query->getOption('skip result count');
    if (!$skip_count) {
      $count_query = $db_query->countQuery();
      $results->setResultCount($count_query->execute()->fetchField());
    }

    if ($skip_count || $results->getResultCount()) {
      if ($query->getOption('search_api_facets')) {
        $results->setExtraData('search_api_facets', $this->getFacets($query, clone $db_query));
      }

      $query_options = $query->getOptions();
      if (isset($query_options['offset']) || isset($query_options['limit'])) {
        $offset = isset($query_options['offset']) ? $query_options['offset'] : 0;
        $limit = isset($query_options['limit']) ? $query_options['limit'] : 1000000;
        $db_query->range($offset, $limit);
      }

      $sort = $query->getSorts();
      if ($sort) {
        foreach ($sort as $field_name => $order) {
          if ($order != 'ASC' && $order != 'DESC') {
            $msg = $this->t('Unknown sort order @order. Assuming "ASC".', array('@order' => $order));
            $this->warnings[(string) $msg] = 1;
            $order = 'ASC';
          }
          if ($field_name == 'search_api_relevance') {
            $db_query->orderBy('score', $order);
            continue;
          }
          if ($field_name == 'search_api_id') {
            $db_query->orderBy('item_id', $order);
            continue;
          }

          if (!isset($fields[$field_name])) {
            throw new SearchApiException(new FormattableMarkup('Trying to sort on unknown field @field.', array('@field' => $field_name)));
          }
          $alias = $this->getTableAlias(array('table' => $db_info['index_table']), $db_query);
          $db_query->orderBy($alias . '.' . $fields[$field_name]['column'], $order);
          // PostgreSQL automatically adds a field to the SELECT list when
          // sorting on it. Therefore, if we have aggregations present we also
          // have to add the field to the GROUP BY (since Drupal won't do it for
          // us). However, if no aggregations are present, a GROUP BY would lead
          // to another error. Therefore, we only add it if there is already a
          // GROUP BY.
          if ($db_query->getGroupBy()) {
            $db_query->groupBy($alias . '.' . $fields[$field_name]['column']);
          }
        }
      }
      else {
        $db_query->orderBy('score', 'DESC');
      }

      $result = $db_query->execute();

      foreach ($result as $row) {
        $item = Utility::createItem($index, $row->item_id);
        $item->setScore($row->score / self::SCORE_MULTIPLIER);
        $results->addResultItem($item);
      }
      if ($skip_count && !empty($item)) {
        $results->setResultCount(1);
      }
    }

    $results->setWarnings(array_keys($this->warnings));
    $results->setIgnoredSearchKeys(array_keys($this->ignored));

    return $results;
  }
 /**
  * Extract results from a Solr response.
  *
  * @param \Drupal\search_api\Query\QueryInterface $query
  *   The Search API query object.
  * @param \Solarium\Core\Query\Result\ResultInterface $result
  *   A Solarium select response object.
  *
  * @return \Drupal\search_api\Query\ResultSetInterface
  *   A result set object.
  */
 protected function extractResults(QueryInterface $query, ResultInterface $result)
 {
     $index = $query->getIndex();
     $field_names = $this->getFieldNames($index);
     $fields = $index->getFields();
     $site_hash = SearchApiSolrUtility::getSiteHash();
     // We can find the item ID and the score in the special 'search_api_*'
     // properties. Mappings are provided for these properties in
     // SearchApiSolrBackend::getFieldNames().
     $id_field = $field_names['search_api_id'];
     $score_field = $field_names['search_api_relevance'];
     // Set up the results array.
     $result_set = SearchApiUtility::createSearchResultSet($query);
     $result_set->setExtraData('search_api_solr_response', $result->getData());
     // In some rare cases (e.g., MLT query with nonexistent ID) the response
     // will be NULL.
     $is_grouping = $result instanceof Result && $result->getGrouping();
     if (!$result->getResponse() && !$is_grouping) {
         $result_set->setResultCount(0);
         return $result_set;
     }
     // If field collapsing has been enabled for this query, we need to process
     // the results differently.
     $grouping = $query->getOption('search_api_grouping');
     $docs = array();
     if (!empty($grouping['use_grouping']) && $is_grouping) {
         //      $docs = array();
         //      $result_set['result count'] = 0;
         //      foreach ($grouping['fields'] as $field) {
         //        if (!empty($response->grouped->{$fields[$field]})) {
         //          $result_set['result count'] += $response->grouped->{$fields[$field]}->ngroups;
         //          foreach ($response->grouped->{$fields[$field]}->groups as $group) {
         //            foreach ($group->doclist->docs as $doc) {
         //              $docs[] = $doc;
         //            }
         //          }
         //        }
         //      }
     } else {
         $result_set->setResultCount($result->getNumFound());
         $docs = $result->getDocuments();
     }
     // Add each search result to the results array.
     /** @var \Solarium\QueryType\Select\Result\Document $doc */
     foreach ($docs as $doc) {
         $doc_fields = $doc->getFields();
         $item_id = $doc_fields[$id_field];
         // For items coming from a different site, we need to adapt the item ID.
         if (!$this->configuration['site_hash'] && $doc_fields['hash'] != $site_hash) {
             $item_id = $doc_fields['hash'] . '--' . $item_id;
         }
         $result_item = SearchApiUtility::createItem($index, $item_id);
         $result_item->setScore($doc_fields[$score_field]);
         unset($doc_fields[$id_field], $doc_fields[$score_field]);
         // Extract properties from the Solr document, translating from Solr to
         // Search API property names. This reverses the mapping in
         // SearchApiSolrBackend::getFieldNames().
         foreach ($field_names as $search_api_property => $solr_property) {
             if (isset($doc_fields[$solr_property])) {
                 // Date fields need some special treatment to become valid date values
                 // (i.e., timestamps) again.
                 if (isset($fields[$search_api_property]) && $fields[$search_api_property]->getType() == 'date' && preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/', $doc_fields[$solr_property][0])) {
                     $doc_fields[$solr_property][0] = strtotime($doc_fields[$solr_property][0]);
                 }
                 $field = SearchApiUtility::createField($index, $search_api_property);
                 $field->setValues($doc_fields[$solr_property]);
                 $result_item->setField($search_api_property, $field);
             }
         }
         $index_id = $this->getIndexId($index->id());
         $solr_id = $this->createId($index_id, $result_item->getId());
         $item_fields = $result_item->getFields();
         $excerpt = $this->getSolrHelper()->getExcerpt($result->getData(), $solr_id, $item_fields, $field_names);
         if ($excerpt) {
             $result_item->setExcerpt($excerpt);
         }
         $result_set->addResultItem($result_item);
     }
     // Check for spellcheck suggestions.
     /*if (module_exists('search_api_spellcheck') && $query->getOption('search_api_spellcheck')) {
          $result_set->setExtraData('search_api_spellcheck', new SearchApiSpellcheckSolr($result));
       }*/
     return $result_set;
 }