diff --git a/src/Plugin/views/field/SearchApiFieldTrait.php b/src/Plugin/views/field/SearchApiFieldTrait.php index fbd563b..c320add 100644 --- a/src/Plugin/views/field/SearchApiFieldTrait.php +++ b/src/Plugin/views/field/SearchApiFieldTrait.php @@ -9,6 +9,7 @@ use Drupal\Core\TypedData\DataReferenceInterface; use Drupal\Core\TypedData\ListInterface; use Drupal\search_api\Plugin\views\SearchApiHandlerTrait; +use Drupal\search_api\Processor\ConfigurablePropertyInterface; use Drupal\search_api\Processor\ProcessorPropertyInterface; use Drupal\search_api\Utility\Utility; use Drupal\views\Plugin\views\field\MultiItemsFieldHandlerInterface; @@ -209,7 +210,6 @@ protected function addRetrievedProperty($combined_property_path) { $this->getQuery()->addRetrievedProperty($combined_property_path); list($datasource_id, $property_path) = Utility::splitCombinedId($combined_property_path); - // If $datasource_id is NULL, it will be an empty string key in the array. $this->retrievedProperties[$datasource_id][$property_path] = $combined_property_path; return $this; } @@ -289,6 +289,7 @@ public function getValue(ResultRow $values, $field = NULL) { * @see \Drupal\views\Plugin\views\field\FieldHandlerInterface::preRender() */ public function preRender(&$values) { + $index = $this->getIndex(); // We deal with the properties one by one, always loading the necessary // values for any nested properties coming afterwards. // @todo This works quite well, but will load each item/entity individually. @@ -300,6 +301,9 @@ public function preRender(&$values) { // expandRequiredProperties() would have to provide more information, or // provide a separate properties list for each row. foreach ($this->expandRequiredProperties() as $datasource_id => $properties) { + if ($datasource_id === '') { + $datasource_id = NULL; + } foreach ($properties as $property_path => $combined_property_path) { // Determine the path of the parent property, and the property key to // take from it for this property. If the name is "_object", we just @@ -316,7 +320,7 @@ public function preRender(&$values) { // Bail for rows with the wrong datasource for this property, or for // which this field doesn't even apply (which will usually be the // same, though). - if (($datasource_id && $datasource_id != $row->search_api_datasource) || !$this->isActiveForRow($row)) { + if (!$this->isActiveForRow($row)) { continue; } // Check whether there are parent objects present. If no, either load @@ -356,6 +360,30 @@ public function preRender(&$values) { if (!($parent instanceof ComplexDataInterface)) { continue; } + // Check whether this is a processor-generated property and use + // special code to retrieve it in this case. + $definitions = $index->getPropertyDefinitions($datasource_id); + if (!$parent_path && isset($definitions[$name])) { + $definition = $definitions[$name]; + if ($definition instanceof ProcessorPropertyInterface) { + // @todo Create dummy field and put it in dummy item, then use + // the processor to add the field's values. See code for + // extracting processor-generated properties in + // \Drupal\search_api\Processor\ProcessorPluginBase::extractItemValues(). + if ($set_values) { + $row->{$combined_property_path} = array(); + } + foreach ($dummy_field->getValues() as $value) { + if ($set_values) { + $row->{$combined_property_path}[] = $value; + } + $typed_data = \Drupal::service('typed_data_manager') + ->create($definition, $value); + $row->_relationship_objects[$property_path][] = $typed_data; + } + continue; + } + } // Add the typed data for the property to our relationship objects // for this property path. To treat list properties correctly // regarding possible child properties, add all the list items @@ -392,21 +420,6 @@ public function preRender(&$values) { // that only exists on a different bundle. Unfortunately, there // is no ComplexDataInterface::hasProperty() method, so we can // only catch and ignore the exception. - if (empty($datasource_id)) { - $item = $row->_item; - - $definitions = $item->getIndex()->getPropertyDefinitions(); - if (isset($definitions[$name]) && $definitions[$name] instanceof ProcessorPropertyInterface) { - $field = $item->getField($name); - $field_values = $item->getField($name)->getValues(); - $row->_relationship_objects[$property_path] = [ - \Drupal::service('typed_data_manager')->create( - $field->getDataDefinition(), - reset($field_values) - ), - ]; - } - } } } } @@ -451,6 +464,9 @@ public function preRender(&$values) { protected function expandRequiredProperties() { $required_properties = array(); foreach ($this->retrievedProperties as $datasource_id => $properties) { + if ($datasource_id === '') { + $datasource_id = NULL; + } foreach (array_keys($properties) as $property_path) { $path_to_add = ''; foreach (explode(':', $property_path) as $component) { @@ -477,8 +493,8 @@ protected function expandRequiredProperties() { * otherwise. */ protected function isActiveForRow(ResultRow $row) { - $datasource_id = $this->getDatasourceId(); - return !$datasource_id || $row->search_api_datasource === $datasource_id; + $datasource_ids = array(NULL, $row->search_api_datasource); + return in_array($this->getDatasourceId(), $datasource_ids, TRUE); } /** diff --git a/src/Utility/Utility.php b/src/Utility/Utility.php index 6937e50..f247c90 100644 --- a/src/Utility/Utility.php +++ b/src/Utility/Utility.php @@ -421,7 +421,7 @@ public static function deepCopy(array $array) { * \Drupal\search_api\IndexInterface::DATASOURCE_ID_SEPARATOR. */ public static function createCombinedId($datasource_id, $raw_id) { - if (empty($datasource_id)) { + if (!isset($datasource_id)) { return $raw_id; } return $datasource_id . IndexInterface::DATASOURCE_ID_SEPARATOR . $raw_id;