diff --git a/src/Item/Field.php b/src/Item/Field.php index 97637ad..6d69216 100644 --- a/src/Item/Field.php +++ b/src/Item/Field.php @@ -8,6 +8,7 @@ namespace Drupal\search_api\Item; use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\TypedData\ComplexDataDefinitionInterface; use Drupal\search_api\Entity\Index; use Drupal\search_api\IndexInterface; use Drupal\search_api\SearchApiException; @@ -94,20 +95,6 @@ class Field implements \IteratorAggregate, FieldInterface { protected $labelPrefix; /** - * Whether this field should be hidden from the user. - * - * @var bool - */ - protected $hidden; - - /** - * The field's values. - * - * @var array - */ - protected $values = array(); - - /** * The Search API data type of this field. * * @var string @@ -115,25 +102,18 @@ class Field implements \IteratorAggregate, FieldInterface { protected $type; /** - * The original data type of this field. + * The boost assigned to this field, if any. * - * @var string + * @var float */ - protected $originalType; + protected $boost; /** - * The state of this field in the index, whether indexed or not. + * Whether this field should be hidden from the user. * * @var bool */ - protected $indexed; - - /** - * The boost assigned to this field, if any. - * - * @var float - */ - protected $boost; + protected $hidden; /** * Whether this field should always be enabled/indexed. @@ -150,6 +130,20 @@ class Field implements \IteratorAggregate, FieldInterface { protected $typeLocked; /** + * The field's values. + * + * @var array + */ + protected $values = array(); + + /** + * The original data type of this field. + * + * @var string + */ + protected $originalType; + + /** * Constructs a Field object. * * @param \Drupal\search_api\IndexInterface $index @@ -196,12 +190,6 @@ class Field implements \IteratorAggregate, FieldInterface { 'datasource_id' => $this->getDatasourceId(), 'property_path' => $this->getPropertyPath(), 'type' => $this->getType(), - // @todo Check whether YAML/schema magic will add those anyways, or - // whether them not being present is a problem. -// 'boost' => $this->getBoost(), -// 'indexed_locked' => $this->isIndexedLocked(), -// 'type_locked' => $this->isTypeLocked(), -// 'hidden' => $this->isHidden(), ); if ($this->getBoost() != 1.0) { $settings['boost'] = $this->getBoost(); @@ -247,12 +235,6 @@ class Field implements \IteratorAggregate, FieldInterface { * {@inheritdoc} */ public function getPropertyPath() { - if (!isset($this->propertyPath)) { - $fields = $this->getIndex()->getFields(); - if (isset($fields[$this->getFieldIdentifier()]) && $fields[$this->getFieldIdentifier()] != $this) { - $this->propertyPath = $fields[$this->getFieldIdentifier()]->getPropertyPath(); - } - } return $this->propertyPath; } @@ -357,22 +339,48 @@ class Field implements \IteratorAggregate, FieldInterface { /** * {@inheritdoc} */ - // @todo This currently only works for unnested fields, since - // Index::getPropertyDefinitions() won't return any nested ones. public function getDataDefinition() { if (!isset($this->dataDefinition)) { - $definitions = $this->index->getPropertyDefinitions($this->datasourceId); - if (!isset($definitions[$this->propertyPath])) { - $args['@field'] = $this->fieldIdentifier; - $args['%index'] = $this->index->label(); - throw new SearchApiException(new FormattableMarkup('Could not retrieve data definition for field "@field" on index %index.', $args)); + $definitions = $this->index->getPropertyDefinitions($this->getDatasourceId()); + $definition = $this->getNestedDefinition($definitions, explode(':', $this->getPropertyPath())); + if (!$definition) { + $args['%field'] = $this->getLabel(); + $args['%index'] = $this->getIndex()->label(); + throw new SearchApiException(new FormattableMarkup('Could not retrieve data definition for field %field on index %index.', $args)); } - $this->dataDefinition = $definitions[$this->propertyPath]; + $this->dataDefinition = $definition; } return $this->dataDefinition; } /** + * Retrieves a nested property definition from an array of definitions. + * + * @param \Drupal\Core\TypedData\DataDefinitionInterface[] $properties + * The given array of base definitions. + * @param string[] $keys + * An array of keys to apply to the definitions to arrive at the one that + * should be returned. + * + * @return \Drupal\Core\TypedData\DataDefinitionInterface|null + * The requested property definition, or NULL if it could not be found. + */ + protected function getNestedDefinition(array $properties, array $keys) { + $key = array_shift($keys); + if (!isset($properties[$key])) { + return NULL; + } + $property = Utility::getInnerProperty($properties[$key]); + if (!$keys) { + return $property; + } + if (!$property instanceof ComplexDataDefinitionInterface) { + return NULL; + } + return $this->getNestedDefinition($property->getPropertyDefinitions(), $keys); + } + + /** * {@inheritdoc} */ public function getType() { @@ -383,6 +391,11 @@ class Field implements \IteratorAggregate, FieldInterface { * {@inheritdoc} */ public function setType($type) { + if ($this->isTypeLocked()) { + $args['%field'] = $this->getLabel(); + $args['%index'] = $this->getIndex()->label(); + throw new SearchApiException(new FormattableMarkup('Trying to change the type of field %field on index %index, which is locked.', $args)); + } $this->type = $type; return $this; } @@ -438,11 +451,7 @@ class Field implements \IteratorAggregate, FieldInterface { * {@inheritdoc} */ public function getBoost() { - if (!isset($this->boost)) { - $fields = $this->index->getFieldSettings(); - $this->boost = isset($fields[$this->fieldIdentifier]['boost']) ? (float) $fields[$this->fieldIdentifier]['boost'] : 1.0; - } - return $this->boost; + return isset($this->boost) ? $this->boost : 1.0; } /** diff --git a/src/Item/FieldInterface.php b/src/Item/FieldInterface.php index 57e3f58..873463d 100644 --- a/src/Item/FieldInterface.php +++ b/src/Item/FieldInterface.php @@ -95,9 +95,6 @@ interface FieldInterface extends \Traversable { * * @return string * The property path. - * - * @throws \Drupal\search_api\SearchApiException - * Thrown if no property path was set before and it couldn't be loaded. */ public function getPropertyPath(); @@ -235,6 +232,9 @@ interface FieldInterface extends \Traversable { * The data type of the field. * * @return $this + * + * @throws \Drupal\search_api\SearchApiException + * Thrown if the type of this field is locked. */ public function setType($type);