diff --git a/includes/callback_bundle_filter.inc b/includes/callback_bundle_filter.inc index 08fcba4..6a36e6e 100644 --- a/includes/callback_bundle_filter.inc +++ b/includes/callback_bundle_filter.inc @@ -14,24 +14,47 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { * {@inheritdoc} */ public function supportsIndex(SearchApiIndex $index) { - $support = $index->getEntityType() && ($info = entity_get_info($index->getEntityType())) && self::hasBundles($info); - $support &= empty($index->options['datasource']['bundles']) || count($index->options['datasource']['bundles']) > 1; - return $support; + if ($this->isMultiEntityIndex($index)) { + $info = entity_get_info(); + foreach ($index->options['datasource']['types'] as $type) { + if (isset($info[$type]) && self::hasBundles($info[$type])) { + return TRUE; + } + } + return FALSE; + } + return $index->getEntityType() && ($info = entity_get_info($index->getEntityType())) && self::hasBundles($info); } /** * {@inheritdoc} */ public function alterItems(array &$items) { - $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']; - $bundle_prop = $info['entity keys']['bundle']; - foreach ($items as $id => $item) { - if (isset($bundles[$item->$bundle_prop]) == $default) { - unset($items[$id]); + if (!$this->supportsIndex($this->index) || !isset($this->options['bundles'])) { + 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']; + + $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) { + unset($items[$id]); } } } @@ -40,20 +63,35 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { * {@inheritdoc} */ public function configurationForm() { - $info = entity_get_info($this->index->getEntityType()); - if (self::hasBundles($info)) { + if ($this->supportsIndex($this->index)) { $options = array(); - foreach ($info['bundles'] as $bundle => $bundle_info) { - $options[$bundle] = isset($bundle_info['label']) ? $bundle_info['label'] : $bundle; + if ($this->isMultiEntityIndex()) { + $info = entity_get_info(); + $unsupported_types = array(); + foreach ($this->index->options['datasource']['types'] as $type) { + if (isset($info[$type]) && self::hasBundles($info[$type])) { + foreach ($info[$type]['bundles'] as $bundle => $bundle_info) { + $options["$type:$bundle"] = $info[$type]['label'] . ' ยป ' . $bundle_info['label']; + } + } + else { + $unsupported_types[] = isset($info[$type]['label']) ? $info[$type]['label'] : $type; + } + } + if ($unsupported_types) { + $form['unsupported_types']['#markup'] = '

' . t('The following entity types do not contain any bundles: @types. All items of those types will therefore be included in the index.', array('@types' => implode(', ', $unsupported_types))) . '

'; + } + } + else { + $info = entity_get_info($this->index->getEntityType()); + foreach ($info['bundles'] as $bundle => $bundle_info) { + $options[$bundle] = isset($bundle_info['label']) ? $bundle_info['label'] : $bundle; + } } if (!empty($this->index->options['datasource']['bundles'])) { $form['message']['#markup'] = '

' . t("Note: This index is already restricted to certain bundles. If you use this data alteration, those will be reduced further. However, the index setting is better supported in the user interface and should therefore be prefered. For example, using this data alteration will not reduce the displayed total number of items to index (even though some of them will not be indexed). Consider creating a new index with appropriate bundle settings instead.") . '

'; - $included_bundles = drupal_map_assoc($this->index->options['datasource']['bundles']); - foreach ($options as $bundle => $label) { - if (!isset($included_bundles[$bundle])) { - unset($options[$bundle]); - } - } + $included_bundles = array_flip($this->index->options['datasource']['bundles']); + $options = array_intersect_key($options, $included_bundles); } $form['default'] = array( '#type' => 'radios', @@ -90,10 +128,25 @@ class SearchApiAlterBundleFilter extends SearchApiAbstractAlterCallback { * The entity type's entity_get_info() array. * * @return bool - * TRUE if the entity type has bundles, FASLE otherwise. + * TRUE if the entity type has bundles, FALSE otherwise. */ protected static function hasBundles(array $entity_info) { return !empty($entity_info['entity keys']['bundle']) && !empty($entity_info['bundles']); } + /** + * Determines whether the given index contains multiple types of entities. + * + * @param SearchApiIndex|null $index + * (optional) The index to examine. Defaults to the index set for this + * plugin. + * + * @return bool + * TRUE if the index is a multi-entity index, FALSE otherwise. + */ + protected function isMultiEntityIndex(SearchApiIndex $index = NULL) { + $index = $index ? $index : $this->index; + return $index->datasource() instanceof SearchApiCombinedEntityDataSourceController; + } + }