diff --git a/includes/callback_bundle_filter.inc b/includes/callback_bundle_filter.inc index 6a36e6e..50a9dc9 100644 --- a/includes/callback_bundle_filter.inc +++ b/includes/callback_bundle_filter.inc @@ -34,26 +34,19 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { return; } - $entity_type = $this->isMultiEntityIndex() ? NULL : $this->index->getEntityType(); - // If the index contains multiple entity type, $info will contain the infos - // of all types, otherwise it's just the info of the relevant type. - $info = entity_get_info($entity_type); - $bundle_prop = $this->isMultiEntityIndex() ? NULL : $info['entity keys']['bundle']; + if ($this->isMultiEntityIndex()) { + $bundle_prop = 'item_bundle'; + } + else { + $info = entity_get_info($this->index->getEntityType()); + $bundle_prop = $info['entity keys']['bundle']; + } $bundles = array_flip($this->options['bundles']); $default = (bool) $this->options['default']; foreach ($items as $id => $item) { - if ($entity_type) { - $bundle = $item->$bundle_prop; - } - else { - if (!isset($info[$item->_type]['entity keys']['bundle'])) { - continue; - } - $bundle = $item->_type . ':' . $item->{$item->_type}->{$info[$item->_type]['entity keys']['bundle']}; - } - if (isset($bundles[$bundle]) == $default) { + if (isset($bundles[$item->$bundle_prop]) == $default) { unset($items[$id]); } } diff --git a/includes/datasource_multiple.inc b/includes/datasource_multiple.inc index 2c3f900..13b8881 100644 --- a/includes/datasource_multiple.inc +++ b/includes/datasource_multiple.inc @@ -20,7 +20,7 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS */ public function getIdFieldInfo() { return array( - 'key' => '_id', + 'key' => 'item_id', 'type' => 'string', ); } @@ -31,19 +31,30 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS public function loadItems(array $ids) { $ids_by_type = array(); foreach ($ids as $id) { - list($type, $type_id) = explode('/', $id); - $ids_by_type[$type][$type_id] = $id; + list($type, $entity_id) = explode('/', $id); + $ids_by_type[$type][$entity_id] = $id; } $items = array(); foreach ($ids_by_type as $type => $type_ids) { - foreach (entity_load($type, array_keys($type_ids)) as $type_id => $item) { - $id = $type_ids[$type_id]; - $item = (object) array($type => $item); - $item->_id = $id; - $item->_type = $type; + foreach (entity_load($type, array_keys($type_ids)) as $entity_id => $entity) { + $id = $type_ids[$entity_id]; + $item = (object) array($type => $entity); + $item->item_id = $id; + $item->item_type = $type; + $item->item_entity_id = $entity_id; + $item->item_bundle = NULL; + try { + list(, , $bundle) = entity_extract_ids($type, $entity); + $item->item_bundle = $bundle ? "$type:$bundle" : NULL; + } + catch (EntityMalformedException $e) { + // Will probably make problems at some other place, but for extracting + // the bundle it is really not critical enough to fail on – just + // ignore this exception. + } $items[$id] = $item; - unset($type_ids[$type_id]); + unset($type_ids[$entity_id]); } if ($type_ids) { search_api_track_item_delete($type, array_keys($type_ids)); @@ -58,17 +69,28 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS */ protected function getPropertyInfo() { $info = array( - '_id' => array( + 'item_id' => array( 'label' => t('ID'), - 'description' => t('The datasource-specific ID of the item.'), - 'type' => 'text', + 'description' => t('The combined ID of the item, containing both entity type and entity ID.'), + 'type' => 'token', ), - '_type' => array( + 'item_type' => array( 'label' => t('Entity type'), 'description' => t('The entity type of the item.'), 'type' => 'token', 'options list' => 'search_api_entity_type_options_list', ), + 'item_entity_id' => array( + 'label' => t('Entity ID'), + 'description' => t('The entity ID of the item.'), + 'type' => 'token', + ), + 'item_bundle' => array( + 'label' => t('Bundle'), + 'description' => t('The bundle of the item, if applicable.'), + 'type' => 'token', + 'options list' => 'search_api_combined_bundle_options_list', + ), ); foreach ($this->getSelectedEntityTypeOptions() as $type => $label) { @@ -86,14 +108,14 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS * {@inheritdoc} */ public function getItemId($item) { - return isset($item->_id) ? $item->_id : NULL; + return isset($item->item_id) ? $item->item_id : NULL; } /** * {@inheritdoc} */ public function getItemLabel($item) { - $label = entity_label($item->_type, $item->{$item->_type}); + $label = entity_label($item->item_type, $item->{$item->item_type}); return $label ? $label : NULL; } @@ -101,7 +123,7 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS * {@inheritdoc} */ public function getItemUrl($item) { - if ($item->_type == 'file') { + if ($item->item_type == 'file') { return array( 'path' => file_create_url($item->file->uri), 'options' => array( @@ -110,7 +132,7 @@ class SearchApiCombinedEntityDataSourceController extends SearchApiAbstractDataS ), ); } - $url = entity_uri($item->_type, $item->{$item->_type}); + $url = entity_uri($item->item_type, $item->{$item->item_type}); return $url ? $url : NULL; } diff --git a/search_api.module b/search_api.module index 6d90a1a..08919e9 100644 --- a/search_api.module +++ b/search_api.module @@ -2862,6 +2862,28 @@ function search_api_entity_type_options_list() { } /** + * Options list callback for entity type bundles. + * + * Will include all bundles for all entity types which specify entity property + * information, in a format combining both entity type and bundle. + * + * @return string[] + * An array of bundle identifiers mapped to their human-readable names. + */ +function search_api_combined_bundle_options_list() { + $types = array(); + foreach (array_keys(entity_get_property_info()) as $type) { + $info = entity_get_info($type); + if (!empty($info['bundles'])) { + foreach ($info['bundles'] as $bundle => $bundle_info) { + $types["$type:$bundle"] = $bundle_info['label']; + } + } + } + return $types; +} + +/** * Shutdown function which indexes all queued items, if any. */ function _search_api_index_queued_items() {