You are here

public function Field::synonymsFind in Synonyms 8

Same name and namespace in other branches
  1. 2.0.x src/Plugin/Synonyms/Provider/Field.php \Drupal\synonyms\Plugin\Synonyms\Provider\Field::synonymsFind()

Look up entities by their synonyms within a behavior implementation.

You are provided with a SQL condition that you should apply to the storage of synonyms within the provided behavior implementation. And then return result: what entities are matched by the provided condition through what synonyms.

Parameters

\Drupal\Core\Database\Query\ConditionInterface $condition: Condition that defines what to search for. Apart from normal SQL conditions as known in Drupal, it may contain the following placeholders:

For ease of work with these placeholders, you may use the SynonymsFindTrait and then just invoke the $this->synonymsFindProcessCondition() method, so you won't have to worry much about it.

Return value

\Traversable Traversable result set of found synonyms and entity IDs to which those belong. Each element in the result set should be an object and should have the following structure:

  • synonym: (string) Synonym that was found and which satisfies the provided condition
  • entity_id: (int) ID of the entity to which the found synonym belongs

Overrides SynonymsFindProviderInterface::synonymsFind

File

src/Plugin/Synonyms/Provider/Field.php, line 112

Class

Field
Provide synonyms from attached simple fields.

Namespace

Drupal\synonyms\Plugin\Synonyms\Provider

Code

public function synonymsFind(ConditionInterface $condition) {
  $entity_type_definition = $this->entityTypeManager
    ->getDefinition($this
    ->getPluginDefinition()['controlled_entity_type']);
  $field = $this->entityFieldManager
    ->getFieldDefinitions($this
    ->getPluginDefinition()['controlled_entity_type'], $this
    ->getPluginDefinition()['controlled_bundle']);
  $field = $field[$this
    ->getPluginDefinition()['field']];
  $field_property = $this->fieldTypeToSynonyms
    ->getSimpleFieldTypeToPropertyMap();
  if (isset($field_property[$field
    ->getType()])) {
    $field_property = $field_property[$field
      ->getType()];
  }
  else {
    return [];
  }
  $query = new FieldQuery($entity_type_definition, 'AND', $this->database, QueryBase::getNamespaces($this->entityTypeManager
    ->getStorage($entity_type_definition
    ->id())
    ->getQuery()));
  if ($entity_type_definition
    ->hasKey('bundle')) {
    $query
      ->condition($entity_type_definition
      ->getKey('bundle'), $this
      ->getPluginDefinition()['controlled_bundle']);
  }
  $synonym_column = $field
    ->getName() . '.' . $field_property;
  $this
    ->synonymsFindProcessCondition($condition, $synonym_column, $entity_type_definition
    ->getKey('id'));
  $conditions_array = $condition
    ->conditions();
  $entity_condition = new Condition($conditions_array['#conjunction'], $query);

  // We will insert a dummy condition for a synonym column just to have the
  // actual table.column data on the synonym column.
  $hash = md5($synonym_column);
  $query
    ->condition($synonym_column, $hash);
  unset($conditions_array['#conjunction']);
  foreach ($conditions_array as $v) {
    $entity_condition
      ->condition($v['field'], $v['value'], $v['operator']);
  }
  $query
    ->condition($entity_condition);

  // We need run the entity query in order to force it into building a normal
  // SQL query.
  $query
    ->execute();

  // Now let's get "demapped" normal SQL query that will tell us explicitly
  // where all entity properties/fields are stored among the SQL tables. Such
  // data is what we need and we do not want to demap it manually.
  $sql_query = $query
    ->getSqlQuery();

  // Swap the entity_id column into the alias "entity_id" as we are supposed
  // to do in this method implementation.
  $select_fields =& $sql_query
    ->getFields();
  $select_fields = [
    'entity_id' => $select_fields[$entity_type_definition
      ->getKey('id')],
  ];
  $select_fields['entity_id']['alias'] = 'entity_id';

  // We need some dummy extra condition to force them into re-compilation.
  $sql_query
    ->where('1 = 1');
  $conditions_array =& $sql_query
    ->conditions();
  foreach ($conditions_array as $k => $condition_array) {
    if (isset($condition_array['value']) && $condition_array['value'] == $hash) {
      list($table_alias, $column) = explode('.', $condition_array['field']);
      unset($conditions_array[$k]);

      // Also unsetting the table aliased by this condition.
      $tables =& $sql_query
        ->getTables();
      $real_table = $tables[$table_alias]['table'];
      foreach ($tables as $k2 => $v2) {
        if ($k2 != $table_alias && $real_table == $v2['table']) {
          unset($tables[$table_alias]);
          $table_alias = $k2;
        }
      }
      $sql_query
        ->addField($table_alias, $column, 'synonym');
      break;
    }
  }
  $result = $sql_query
    ->execute();
  return $result;
}