diff --git a/contrib/search_api_facetapi/search_api_facetapi.module b/contrib/search_api_facetapi/search_api_facetapi.module index b452734..feff684 100644 --- a/contrib/search_api_facetapi/search_api_facetapi.module +++ b/contrib/search_api_facetapi/search_api_facetapi.module @@ -65,6 +65,9 @@ function search_api_facetapi_facetapi_searcher_info() { 'supports facet mincount' => TRUE, 'include default facets' => FALSE, ); + if (($entity_type = $index->getEntityType()) && $entity_type !== $index->item_type) { + $info[$searcher_name]['types'][] = $entity_type; + } } } return $info; @@ -80,7 +83,7 @@ function search_api_facetapi_facetapi_facet_info(array $searcher_info) { if (!empty($index->options['fields'])) { $wrapper = $index->entityWrapper(); $bundle_key = NULL; - if (($entity_info = entity_get_info($index->item_type)) && !empty($entity_info['bundle keys']['bundle'])) { + if ($index->getEntityType() && ($entity_info = entity_get_info($index->getEntityType())) && !empty($entity_info['bundle keys']['bundle'])) { $bundle_key = $entity_info['bundle keys']['bundle']; } @@ -144,7 +147,7 @@ function search_api_facetapi_facetapi_facet_info(array $searcher_info) { if ($bundle_key) { if ($key === $bundle_key) { // Set entity type this field contains bundle information for. - $facet_info[$key]['field api bundles'][] = $index->item_type; + $facet_info[$key]['field api bundles'][] = $index->getEntityType(); } else { // Add "bundle" as possible dependency plugin. diff --git a/contrib/search_api_views/includes/query.inc b/contrib/search_api_views/includes/query.inc index b5c8fa6..f9d6f90 100644 --- a/contrib/search_api_views/includes/query.inc +++ b/contrib/search_api_views/includes/query.inc @@ -388,11 +388,11 @@ class SearchApiViewsQuery extends views_plugin_query { * query backend. */ public function get_result_wrappers($results, $relationship = NULL, $field = NULL) { - $is_entity = (boolean) entity_get_info($this->index->item_type); + $entity_type = $this->index->getEntityType(); $wrappers = array(); $load_entities = array(); foreach ($results as $row_index => $row) { - if ($is_entity && isset($row->entity)) { + if ($entity_type && isset($row->entity)) { // If this entity isn't load, register it for pre-loading. if (!is_object($row->entity)) { $load_entities[$row->entity] = $row_index; @@ -405,14 +405,14 @@ class SearchApiViewsQuery extends views_plugin_query { // If the results are entities, we pre-load them to make use of a multiple // load. (Otherwise, each result would be loaded individually.) if (!empty($load_entities)) { - $entities = entity_load($this->index->item_type, array_keys($load_entities)); + $entities = entity_load($entity_type, array_keys($load_entities)); foreach ($entities as $entity_id => $entity) { $wrappers[$load_entities[$entity_id]] = $this->index->entityWrapper($entity); } } // Apply the relationship, if necessary. - $type = $this->index->item_type; + $type = $entity_type ? $entity_type : $this->index->item_type; $selector_suffix = ''; if ($field && ($pos = strrpos($field, ':'))) { $selector_suffix = substr($field, 0, $pos); diff --git a/contrib/search_api_views/search_api_views.views.inc b/contrib/search_api_views/search_api_views.views.inc index 3fc2b8f..5d2337c 100644 --- a/contrib/search_api_views/search_api_views.views.inc +++ b/contrib/search_api_views/search_api_views.views.inc @@ -20,9 +20,9 @@ function search_api_views_views_data() { 'help' => t('Use the %name search index for filtering and retrieving data.', array('%name' => $index->name)), 'query class' => 'search_api_views_query', ); - if (isset($entity_types[$index->item_type])) { + if (isset($entity_types[$index->getEntityType()])) { $table['table'] += array( - 'entity type' => $index->item_type, + 'entity type' => $index->getEntityType(), 'skip entity load' => TRUE, ); } diff --git a/includes/callback_add_viewed_entity.inc b/includes/callback_add_viewed_entity.inc index bd0f8d8..2adcad0 100644 --- a/includes/callback_add_viewed_entity.inc +++ b/includes/callback_add_viewed_entity.inc @@ -11,14 +11,16 @@ class SearchApiAlterAddViewedEntity extends SearchApiAbstractAlterCallback { * @see SearchApiAlterCallbackInterface::supportsIndex() */ public function supportsIndex(SearchApiIndex $index) { - return (bool) entity_get_info($index->item_type); + return (bool) $index->getEntityType(); } public function configurationForm() { - $info = entity_get_info($this->index->item_type); $view_modes = array(); - foreach ($info['view modes'] as $key => $mode) { - $view_modes[$key] = $mode['label']; + if ($entity_type = $this->index->getEntityType()) { + $info = entity_get_info($entity_type); + foreach ($info['view modes'] as $key => $mode) { + $view_modes[$key] = $mode['label']; + } } $this->options += array('mode' => reset($view_modes)); if (count($view_modes) > 1) { @@ -60,7 +62,7 @@ class SearchApiAlterAddViewedEntity extends SearchApiAbstractAlterCallback { $original_user = $GLOBALS['user']; $GLOBALS['user'] = drupal_anonymous_user(); - $type = $this->index->item_type; + $type = $this->index->getEntityType(); $mode = empty($this->options['mode']) ? 'full' : $this->options['mode']; foreach ($items as $id => &$item) { // Since we can't really know what happens in entity_view() and render(), diff --git a/includes/callback_bundle_filter.inc b/includes/callback_bundle_filter.inc index 4c758c3..e1072b6 100644 --- a/includes/callback_bundle_filter.inc +++ b/includes/callback_bundle_filter.inc @@ -7,11 +7,11 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { public function supportsIndex(SearchApiIndex $index) { - return ($info = entity_get_info($index->item_type)) && self::hasBundles($info); + return $index->getEntityType() && ($info = entity_get_info($index->getEntityType())) && self::hasBundles($info); } public function alterItems(array &$items) { - $info = entity_get_info($this->index->item_type); + $info = entity_get_info($this->index->getEntityType()); if (self::hasBundles($info) && isset($this->options['bundles'])) { $bundles = array_flip($this->options['bundles']); $default = (bool) $this->options['default']; @@ -25,7 +25,7 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { } public function configurationForm() { - $info = entity_get_info($this->index->item_type); + $info = entity_get_info($this->index->getEntityType()); if (self::hasBundles($info)) { $options = array(); foreach ($info['bundles'] as $bundle => $bundle_info) { diff --git a/includes/callback_node_access.inc b/includes/callback_node_access.inc index ce671d7..5acc76c 100644 --- a/includes/callback_node_access.inc +++ b/includes/callback_node_access.inc @@ -22,7 +22,7 @@ class SearchApiAlterNodeAccess extends SearchApiAbstractAlterCallback { */ public function supportsIndex(SearchApiIndex $index) { // Currently only node access is supported. - return $index->item_type === 'node'; + return $index->getEntityType() === 'node'; } /** diff --git a/includes/callback_node_status.inc b/includes/callback_node_status.inc index bfe35e2..ee57c38 100644 --- a/includes/callback_node_status.inc +++ b/includes/callback_node_status.inc @@ -22,7 +22,7 @@ class SearchApiAlterNodeStatus extends SearchApiAbstractAlterCallback { * TRUE if the callback can run on the given index; FALSE otherwise. */ public function supportsIndex(SearchApiIndex $index) { - return $index->item_type === 'node'; + return $index->getEntityType() === 'node'; } /** diff --git a/includes/datasource.inc b/includes/datasource.inc index 21a6157..b4ef5f6 100644 --- a/includes/datasource.inc +++ b/includes/datasource.inc @@ -237,6 +237,14 @@ interface SearchApiDataSourceControllerInterface { */ public function getIndexStatus(SearchApiIndex $index); + /** + * Get the entity type of items from this datasource. + * + * @return string|null + * An entity type string if the items provided by this datasource are + * entities; NULL otherwise. + */ + public function getEntityType(); } /** @@ -265,6 +273,15 @@ abstract class SearchApiAbstractDataSourceController implements SearchApiDataSou protected $type; /** + * The entity type for this controller instance. + * + * @var string|null + * + * @see getEntityType() + */ + protected $entityType = NULL; + + /** * The info array for the item type, as specified via * hook_search_api_item_type_info(). * @@ -314,6 +331,21 @@ abstract class SearchApiAbstractDataSourceController implements SearchApiDataSou public function __construct($type) { $this->type = $type; $this->info = search_api_get_item_type_info($type); + + if (!empty($this->info['entity_type'])) { + $this->entityType = $this->info['entity_type']; + } + } + + /** + * Get the entity type of items from this datasource. + * + * @return string|null + * An entity type string if the items provided by this datasource are + * entities; NULL otherwise. + */ + public function getEntityType() { + return $this->entityType; } /** @@ -333,7 +365,7 @@ abstract class SearchApiAbstractDataSourceController implements SearchApiDataSou */ public function getMetadataWrapper($item = NULL, array $info = array()) { $info += $this->getPropertyInfo(); - return entity_metadata_wrapper($this->type, $item, $info); + return entity_metadata_wrapper($this->entityType ? $this->entityType : $this->type, $item, $info); } /** @@ -689,8 +721,10 @@ abstract class SearchApiAbstractDataSourceController implements SearchApiDataSou if ($index->item_type != $this->type) { $index_type = search_api_get_item_type_info($index->item_type); $index_type = empty($index_type['name']) ? $index->item_type : $index_type['name']; - $msg = t('Invalid index @index of type @index_type passed to data source controller for type @this_type.', - array('@index' => $index->name, '@index_type' => $index_type, '@this_type' => $this->info['name'])); + $msg = t( + 'Invalid index @index of type @index_type passed to data source controller for type @this_type.', + array('@index' => $index->name, '@index_type' => $index_type, '@this_type' => $this->info['name']) + ); throw new SearchApiDataSourceException($msg); } } diff --git a/includes/datasource_entity.inc b/includes/datasource_entity.inc index 641a939..6f15ec5 100644 --- a/includes/datasource_entity.inc +++ b/includes/datasource_entity.inc @@ -20,8 +20,8 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * search_api_field_types(). List types ("list<*>") are not allowed. */ public function getIdFieldInfo() { - $info = entity_get_info($this->type); - $properties = entity_get_property_info($this->type); + $info = entity_get_info($this->entityType); + $properties = entity_get_property_info($this->entityType); if (empty($info['entity keys']['id'])) { throw new SearchApiDataSourceException(t("Entity type @type doesn't specify an ID key.", array('@type' => $info['label']))); } @@ -52,7 +52,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * The loaded items, keyed by ID. */ public function loadItems(array $ids) { - $items = entity_load($this->type, $ids); + $items = entity_load($this->entityType, $ids); // If some items couldn't be loaded, remove them from tracking. if (count($items) != count($ids)) { $ids = array_flip($ids); @@ -80,7 +80,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * @see entity_metadata_wrapper() */ public function getMetadataWrapper($item = NULL, array $info = array()) { - return entity_metadata_wrapper($this->type, $item, $info); + return entity_metadata_wrapper($this->entityType, $item, $info); } /** @@ -93,7 +93,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * Either the unique ID of the item, or NULL if none is available. */ public function getItemId($item) { - $id = entity_id($this->type, $item); + $id = entity_id($this->entityType, $item); return $id ? $id : NULL; } @@ -107,7 +107,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * Either a human-readable label for the item, or NULL if none is available. */ public function getItemLabel($item) { - $label = entity_label($this->type, $item); + $label = entity_label($this->entityType, $item); return $label ? $label : NULL; } @@ -123,7 +123,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * item has no URL of its own. */ public function getItemUrl($item) { - if ($this->type == 'file') { + if ($this->entityType == 'file') { return array( 'path' => file_create_url($item->uri), 'options' => array( @@ -132,7 +132,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon ), ); } - $url = entity_uri($this->type, $item); + $url = entity_uri($this->entityType, $item); return $url ? $url : NULL; } @@ -158,7 +158,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon // all items again without any key conflicts. $this->stopTracking($indexes); - $entity_info = entity_get_info($this->type); + $entity_info = entity_get_info($this->entityType); if (!empty($entity_info['base table'])) { // Use a subselect, which will probably be much faster than entity_load(). @@ -200,7 +200,7 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon * An array containing all item IDs for this type. */ protected function getAllItemIds() { - return array_keys(entity_load($this->type)); + return array_keys(entity_load($this->entityType)); } } diff --git a/includes/index_entity.inc b/includes/index_entity.inc index f12bfbd..fdc6673 100644 --- a/includes/index_entity.inc +++ b/includes/index_entity.inc @@ -366,6 +366,17 @@ class SearchApiIndex extends Entity { } /** + * Get the entity type of items in this index. + * + * @return string|null + * An entity type string if the items in this index are entities; NULL + * otherwise. + */ + public function getEntityType() { + return $this->datasource()->getEntityType(); + } + + /** * Get the server this index lies on. * * @param $reset diff --git a/search_api.api.php b/search_api.api.php index 555688b..d1b8336 100644 --- a/search_api.api.php +++ b/search_api.api.php @@ -95,6 +95,9 @@ function hook_search_api_service_info_alter(array &$service_info) { * - datasource controller: A class implementing the * SearchApiDataSourceControllerInterface interface which will be used as * the data source controller for this type. + * - entity_type: (optional) If the type represents entities, the entity type. + * This is used by SearchApiAbstractDataSourceController for determining the + * entity type of items. Other datasource controllers might ignore this. * Other, datasource-specific settings might also be placed here. These should * be specified with the data source controller in question. * @@ -287,7 +290,7 @@ function hook_search_api_index_items_alter(array &$items, SearchApiIndex $index) * An array containing the indexed items' IDs. */ function hook_search_api_items_indexed(SearchApiIndex $index, array $item_ids) { - if ($index->item_type == 'node') { + if ($index->getEntityType() == 'node') { // Flush page cache of the search page. cache_clear_all(url('search'), 'cache_page'); } @@ -300,8 +303,11 @@ function hook_search_api_items_indexed(SearchApiIndex $index, array $item_ids) { * The SearchApiQueryInterface object representing the search query. */ function hook_search_api_query_alter(SearchApiQueryInterface $query) { - $info = entity_get_info($index->item_type); - $query->condition($info['entity keys']['id'], 0, '!='); + // Exclude entities with ID 0. (Assume the ID field is always indexed.) + if ($query->getIndex()->getEntityType()) { + $info = entity_get_info($query->getIndex()->getEntityType()); + $query->condition($info['entity keys']['id'], 0, '!='); + } } /** diff --git a/search_api.module b/search_api.module index fd77b41..b1ae7e9 100644 --- a/search_api.module +++ b/search_api.module @@ -773,6 +773,7 @@ function search_api_search_api_item_type_info() { $types[$type] = array( 'name' => $info['label'], 'datasource controller' => 'SearchApiEntityDataSourceController', + 'entity_type' => $type, ); } }