diff --git a/includes/EntityReferenceSynonymsBehavior.class.inc b/includes/EntityReferenceSynonymsBehavior.class.inc
index d1a1f3d..4aa818c 100644
--- a/includes/EntityReferenceSynonymsBehavior.class.inc
+++ b/includes/EntityReferenceSynonymsBehavior.class.inc
@@ -8,7 +8,7 @@
 /**
  * Definition of EntityReferenceSynonymsBehavior class.
  */
-class EntityReferenceSynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
+class EntityReferenceSynonymsBehavior extends AbstractSynonymsBehavior implements AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
 
   public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
     $synonyms = array();
diff --git a/includes/SynonymsBehavior.interface.inc b/includes/SynonymsBehavior.interface.inc
index 2c30bca..d264362 100644
--- a/includes/SynonymsBehavior.interface.inc
+++ b/includes/SynonymsBehavior.interface.inc
@@ -11,15 +11,6 @@
  * All synonyms behaviors must extend this interface.
  */
 interface SynonymsBehavior {
-}
-
-/**
- * Interface of "synonyms" behavior.
- *
- * The most basic synonyms behavior.
- */
-interface SynonymsSynonymsBehavior extends SynonymsBehavior {
-
   /**
    * Extract synonyms from a field attached to an entity.
    *
@@ -137,9 +128,9 @@ interface SynonymsSynonymsBehavior extends SynonymsBehavior {
 class SynonymsSynonymsBehaviorException extends Exception {}
 
 /**
- * Starting point for implementing SynonymsSynonymsBehavior interface.
+ * Starting point for implementing SynonymsBehavior interface.
  */
-abstract class AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior {
+abstract class AbstractSynonymsBehavior implements SynonymsBehavior {
 
   /**
    * Constant which denotes placeholder of a synonym column.
@@ -178,11 +169,11 @@ abstract class AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehav
 /**
  * Interface of the autocomplete synonyms behavior.
  */
-interface AutocompleteSynonymsBehavior extends SynonymsSynonymsBehavior {
+interface AutocompleteSynonymsBehavior extends SynonymsBehavior {
 }
 
 /**
  * Interface of the synonyms friendly select behavior.
  */
-interface SelectSynonymsBehavior extends SynonymsSynonymsBehavior {
+interface SelectSynonymsBehavior extends SynonymsBehavior {
 }
diff --git a/includes/TaxonomySynonymsBehavior.class.inc b/includes/TaxonomySynonymsBehavior.class.inc
index 6e58a6c..c3c6f9b 100644
--- a/includes/TaxonomySynonymsBehavior.class.inc
+++ b/includes/TaxonomySynonymsBehavior.class.inc
@@ -8,7 +8,7 @@
 /**
  * Definition of TaxonomySynonymsBehavior class.
  */
-class TaxonomySynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
+class TaxonomySynonymsBehavior extends AbstractSynonymsBehavior implements AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
 
   public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
     $synonyms = array();
diff --git a/includes/TextSynonymsBehavior.class.inc b/includes/TextSynonymsBehavior.class.inc
index 96472e1..4330a2c 100644
--- a/includes/TextSynonymsBehavior.class.inc
+++ b/includes/TextSynonymsBehavior.class.inc
@@ -8,7 +8,7 @@
 /**
  * Definition of TextSynonymsBehavior class.
  */
-class TextSynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
+class TextSynonymsBehavior extends AbstractSynonymsBehavior implements AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
 
   public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
     $synonyms = array();
diff --git a/plugins/arguments/term_synonyms.inc b/plugins/arguments/term_synonyms.inc
index bc3e1d8..9b113a2 100644
--- a/plugins/arguments/term_synonyms.inc
+++ b/plugins/arguments/term_synonyms.inc
@@ -5,16 +5,18 @@
  * Plugin to provide a synonyms-friendly argument handler for a Taxonomy term.
  */
 
-$plugin = array(
-  'title' => t("Taxonomy term: ID (synonyms-friendly)"),
-  'keyword' => 'term',
-  'description' => t('Creates a single taxonomy term from a taxonomy term name or one of its synonyms.'),
-  'context' => 'synonyms_term_synonyms_context',
-  'default' => array('breadcrumb' => TRUE, 'transform' => FALSE),
-  'settings form' => 'synonyms_term_synonyms_settings_form',
-  'placeholder form' => 'synonyms_term_synonyms_ctools_argument_placeholder',
-  'breadcrumb' => 'synonyms_term_synonyms_breadcrumb',
-);
+if (module_exists('taxonomy')) {
+  $plugin = array(
+    'title' => t("Taxonomy term: ID (synonyms-friendly)"),
+    'keyword' => 'term',
+    'description' => t('Creates a single taxonomy term from a taxonomy term name or one of its synonyms.'),
+    'context' => 'synonyms_term_synonyms_context',
+    'default' => array('breadcrumb' => TRUE, 'transform' => FALSE),
+    'settings form' => 'synonyms_term_synonyms_settings_form',
+    'placeholder form' => 'synonyms_term_synonyms_ctools_argument_placeholder',
+    'breadcrumb' => 'synonyms_term_synonyms_breadcrumb',
+  );
+}
 
 /**
  * Discover if this argument gives us the term we crave.
@@ -66,12 +68,12 @@ function synonyms_term_synonyms_context($arg = NULL, $conf = NULL, $empty = FALS
       foreach ($vocabularies as $vocabulary) {
         $condition = db_and();
         if ($conf['transform']) {
-          $condition->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :argument", array(
+          $condition->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :argument", array(
             ':argument' => $arg,
           ));
         }
         else {
-          $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $arg);
+          $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $arg);
         }
         $rows = synonyms_synonyms_find($condition, 'taxonomy_term', $vocabulary->machine_name);
         if (!empty($rows)) {
diff --git a/plugins/behavior/autocomplete.inc b/plugins/behavior/autocomplete.inc
index 6d62b8a..761376b 100644
--- a/plugins/behavior/autocomplete.inc
+++ b/plugins/behavior/autocomplete.inc
@@ -23,8 +23,8 @@ function synonyms_behavior_autocomplete_settings_form($form, &$form_state, $sett
   $element['wording'] = array(
     '#type' => 'textfield',
     '#title' => t('Autocomplete wording'),
-    '#default_value' => isset($settings['wording']) ? $settings['wording'] : '@synonym is a synonym of @term',
-    '#description' => t('Specify with what wording the synonyms should be suggested in the autocomplete feature. You may use: <ul><li><em>@synonym</em> to denote value of the synonym</li><li><em>@term</em> to denote term name</li><li><em>@field_name</em> to denote lowercase label of the field from where the synonym originates</li></ul>'),
+    '#default_value' => isset($settings['wording']) ? $settings['wording'] : '@synonym is a synonym of @entity',
+    '#description' => t('Specify with what wording the synonyms should be suggested in the autocomplete feature. You may use: <ul><li><em>@synonym</em> to denote value of the synonym</li><li><em>@entity</em> to denote entity name</li><li><em>@field_name</em> to denote lowercase label of the field from where the synonym originates</li></ul>'),
     '#required' => TRUE,
   );
 
diff --git a/plugins/behavior/select.inc b/plugins/behavior/select.inc
index e10b6d1..a30d4df 100644
--- a/plugins/behavior/select.inc
+++ b/plugins/behavior/select.inc
@@ -24,7 +24,7 @@ function synonyms_behavior_select_settings_form($form, &$form_state, $settings)
     '#type' => 'textfield',
     '#title' => t('Select wording'),
     '#default_value' => isset($settings['wording']) ? $settings['wording'] : '@synonym',
-    '#description' => t('Specify with what wording the synonyms should be placed in the select form element. You may use: <ul><li><em>@synonym</em> to denote value of the synonym</li><li><em>@term</em> to denote term name</li><li><em>@field_name</em> to denote lowercase label of the field from where the synonym originates</li></ul>'),
+    '#description' => t('Specify with what wording the synonyms should be placed in the select form element. You may use: <ul><li><em>@synonym</em> to denote value of the synonym</li><li><em>@entity</em> to denote entity name</li><li><em>@field_name</em> to denote lowercase label of the field from where the synonym originates</li></ul>'),
     '#required' => TRUE,
   );
 
diff --git a/plugins/behavior/synonyms.inc b/plugins/behavior/synonyms.inc
deleted file mode 100644
index b7c44f7..0000000
--- a/plugins/behavior/synonyms.inc
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Plugin definition for most general synonyms behavior.
- */
-
-$plugin = array(
-  'title' => t('Include into term synonyms'),
-  'description' => t('Basic behavior that includes values of this field into the list of synonyms of its entity.'),
-  'interface' => 'SynonymsSynonymsBehavior',
-);
diff --git a/synonyms.info b/synonyms.info
index 709384a..9a7c5f6 100644
--- a/synonyms.info
+++ b/synonyms.info
@@ -1,9 +1,11 @@
 name = Synonyms
 description = "Provides synonyms feature for working with Drupal Taxonomy"
-package = Taxonomy
+package = Synonyms
 core = 7.x
-dependencies[] = taxonomy
 dependencies[] = ctools
+dependencies[] = entity
+
+test_dependencies[] = entityreference:entityreference
 
 files[] = synonyms.test
 
diff --git a/synonyms.install b/synonyms.install
index dcfd5e6..3d2c47a 100644
--- a/synonyms.install
+++ b/synonyms.install
@@ -65,6 +65,33 @@ function synonyms_uninstall() {
 }
 
 /**
+ * Implements hook_requirements().
+ */
+function synonyms_requirements($phase) {
+  $requirements = array();
+  switch ($phase) {
+    case 'update':
+      // Synonyms has changed its dependencies. It used to be Taxonomy and now
+      // it is Entity module. We make sure Entity is enabled otherwise we halt
+      // the update for Synonyms.
+      // TODO: remove this requirement check at some point, when it becomes
+      // obsolete.
+      $t = get_t();
+      $requirements['synonyms_entity_dependency'] = array(
+        'title' => $t('Synonyms depends on Entity'),
+        'description' => $t('Synonyms module depends on Entity module since 4-Mar-2016. At the same time it no longer depends on Taxonomy module while does integrate with the latter. If you do not have installed/enabled Entity module, do so before running updates on Synonyms module. Until Entity module is enabled and updates are executed, Synonyms module performance may degrade and even trigger PHP errors. See <a href="@url">@url</a> for more info.', array(
+          '@url' => 'https://www.drupal.org/node/1194802',
+        )),
+        'value' => module_exists('entity') ? $t('Passed') : $t('Failed'),
+        'severity' => module_exists('entity') ? REQUIREMENT_INFO : REQUIREMENT_ERROR,
+      );
+      break;
+  }
+
+  return $requirements;
+}
+
+/**
  * Implements hook_update_N().
  *
  * Update to version 7.x-1.1 of Synonyms module.
@@ -188,3 +215,51 @@ function synonyms_update_7102() {
     variable_del($row->name);
   }
 }
+
+/**
+ * Expanding Synonyms module to work with all entity types.
+ *
+ * Namely, the following happens:
+ * - general "synonyms" behavior gets removed as too ambiguous.
+ * - "select" and "autocomplete" behaviors undergo change in settings ("@term"
+ *   placeholder is replaced with "@entity" one)
+ * - taxonomy term reference widgets get renamed to their new names.
+ */
+function synonyms_update_7103() {
+  db_delete('synonyms_settings')
+    ->condition('behavior', 'synonyms')
+    ->execute();
+
+  $alter_behaviors = array('select', 'autocomplete');
+  foreach ($alter_behaviors as $behavior) {
+    foreach (synonyms_behavior_get($behavior, NULL, NULL, TRUE) as $behavior_implementation) {
+      $behavior_implementation['settings']['wording'] = str_replace('@term', '@entity', $behavior_implementation['settings']['wording']);
+      synonyms_behavior_settings_save($behavior_implementation);
+    }
+  }
+
+  // Keys are the old widget names, whereas corresponding values are the new
+  // widget names.
+  $migrate_map = array(
+    'synonyms_select' => 'synonyms_select_taxonomy_term',
+    'synonyms_autocomplete' => 'synonyms_autocomplete_taxonomy_term',
+  );
+  foreach (field_info_field_map() as $field_name => $field_info) {
+    if ($field_info['type'] == 'taxonomy_term_reference') {
+      foreach ($field_info['bundles'] as $entity_type => $bundles) {
+        foreach ($bundles as $bundle) {
+          $instance = field_read_instance($entity_type, $field_name, $bundle);
+          if (in_array($instance['widget']['type'], array_keys($migrate_map))) {
+            $instance['widget']['type'] = $migrate_map[$instance['widget']['type']];
+
+            if ($instance['widget']['type'] == 'synonyms_autocomplete_taxonomy_term' && $instance['widget']['settings']['synonyms_autocomplete_path'] == 'synonyms/autocomplete') {
+              $instance['widget']['settings']['synonyms_autocomplete_path'] = 'synonyms/autocomplete-taxonomy-term';
+            }
+
+            field_update_instance($instance);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/synonyms.module b/synonyms.module
index fe53208..b7212ae 100644
--- a/synonyms.module
+++ b/synonyms.module
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Provide synonyms feature for Drupal Taxonomy.
+ * Provide synonyms feature for Drupal entities.
  */
 
 /**
@@ -11,19 +11,63 @@
 function synonyms_menu() {
   $items = array();
 
-  $items['synonyms/autocomplete/%/%/%'] = array(
+  $items['admin/structure/synonyms'] = array(
+    'title' => 'Synonyms',
+    'description' => 'Manage synonyms settings for all entity types.',
+    'page callback' => 'synonyms_settings_overview',
+    'access arguments' => array('administer synonyms'),
+    'file' => 'synonyms.pages.inc',
+    'type' => MENU_NORMAL_ITEM,
+  );
+
+  $items['admin/structure/synonyms/%synonyms_entity_type/%synonyms_bundle'] = array(
+    'title' => 'Synonyms settings',
+    'title callback' => 'synonyms_settings_title',
+    'title arguments' => array(3, 4),
+    'description' => 'Manage synonyms settings.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('synonyms_settings_form', 3, 4),
+    'access arguments' => array('administer synonyms'),
+    'load arguments' => array(3),
+    'file' => 'synonyms.pages.inc',
+  );
+
+  if (module_exists('taxonomy')) {
+    $items['synonyms/autocomplete-taxonomy-term/%/%/%'] = array(
+      'title' => 'Autocomplete Synonyms',
+      'page callback' => 'synonyms_autocomplete_taxonomy_term',
+      'page arguments' => array(2, 3, 4),
+      'access arguments' => array('access content'),
+      'file' => 'synonyms.pages.inc',
+      'type' => MENU_CALLBACK,
+    );
+  }
+
+  $items['synonyms/autocomplete-entity/%/%/%'] = array(
     'title' => 'Autocomplete Synonyms',
-    'page callback' => 'synonyms_autocomplete',
+    'page callback' => 'synonyms_autocomplete_entity',
     'page arguments' => array(2, 3, 4),
-    'access arguments' => array('access content'),
+    'access callback' => 'entityreference_autocomplete_access_callback',
+    'access arguments' => array('tags', 2, 3, 4),
     'file' => 'synonyms.pages.inc',
     'type' => MENU_CALLBACK,
   );
-
   return $items;
 }
 
 /**
+ * Implements hook_permission().
+ */
+function synonyms_permission() {
+  return array(
+    'administer synonyms' => array(
+      'title' => t('Administer synonyms'),
+      'description' => t('Administer synonyms of all entity types.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_ctools_plugin_type().
  */
 function synonyms_ctools_plugin_type() {
@@ -81,16 +125,22 @@ function synonyms_theme() {
  */
 function synonyms_entity_property_info() {
   $info = array();
-  $properties = &$info['taxonomy_term']['properties'];
-  $properties['synonyms'] = array(
-    'label' => t('Synonyms'),
-    'description' => t('Synonyms of entity.'),
-    'type' => 'list<text>',
-    'getter callback' => 'synonyms_get_sanitized',
-    'computed' => TRUE,
-    'sanitized' => TRUE,
-    'raw getter callback' => 'synonyms_get_raw',
-  );
+
+  foreach (entity_get_info() as $entity_type => $entity_info) {
+    $entity_info = synonyms_entity_type_load($entity_type);
+    if ($entity_info) {
+      $info[$entity_type]['properties']['synonyms'] = array(
+        'label' => t('Synonyms'),
+        'description' => t('Synonyms of entity.'),
+        'type' => 'list<text>',
+        'getter callback' => 'synonyms_get_sanitized',
+        'computed' => TRUE,
+        'sanitized' => TRUE,
+        'raw getter callback' => 'synonyms_get_raw',
+      );
+    }
+  }
+
   return $info;
 }
 
@@ -115,7 +165,6 @@ function synonyms_synonyms_behavior_implementation_info($behavior) {
   switch ($behavior) {
     case 'autocomplete':
     case 'select':
-    case 'synonyms':
       return array(
         'number_integer' => 'TextSynonymsBehavior',
         'number_decimal' => 'TextSynonymsBehavior',
@@ -133,6 +182,8 @@ function synonyms_synonyms_behavior_implementation_info($behavior) {
  * Implements hook_form_FORM_ID_alter().
  */
 function synonyms_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) {
+  // TODO: remove this function after a few releases of Synonyms module, since
+  // now the module oversees synonyms of all entities, not only taxonomy terms.
   if (isset($form_state['confirm_delete']) && $form_state['confirm_delete']) {
     return;
   }
@@ -145,99 +196,14 @@ function synonyms_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) {
     '#type' => 'fieldset',
     '#title' => t('Synonyms'),
     '#collapsible' => TRUE,
-    '#tree' => TRUE,
   );
 
-  $behaviors = synonyms_behaviors();
-  $bundle = field_extract_bundle('taxonomy_term', $form['#vocabulary']);
-
-  $form['synonyms']['behaviors'] = array(
-    '#theme' => 'synonyms_behaviors_settings',
-    '#id' => 'synonyms-behaviors-settings-wrapper',
+  $form['synonyms']['link'] = array(
+    '#markup' => t('You can configure synonyms of @vocabulary following <a href="@url">this link</a>.', array(
+      '@vocabulary' => $form['#vocabulary']->name,
+      '@url' => url('admin/structure/synonyms/taxonomy_term/' . $form['#vocabulary']->machine_name, array('query' => drupal_get_destination())),
+    )),
   );
-
-  foreach ($behaviors as $behavior => $behavior_info) {
-    $form['synonyms']['behaviors'][$behavior] = array(
-      '#title' => $behavior_info['title'],
-    );
-
-    $behavior_implementations = synonyms_behavior_get($behavior, 'taxonomy_term', $bundle);
-
-    foreach ($behavior_implementations as $implementation) {
-      $instance = field_info_instance($implementation['entity_type'], $implementation['field_name'], $implementation['bundle']);
-      $form['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['#title'] = $instance['label'];
-
-      if (isset($form_state['values']['synonyms']['behaviors'][$behavior][$implementation['instance_id']])) {
-        $behavior_settings = (bool) $form_state['values']['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['enabled'];
-      }
-      else {
-        $behavior_settings = !is_null($implementation['settings']);
-      }
-      if ($behavior_settings) {
-        if (isset($form_state['values']['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['settings'])) {
-          $behavior_settings = $form_state['values']['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['settings'];
-        }
-        elseif ($implementation['settings']) {
-          $behavior_settings = $implementation['settings'];
-        }
-        else {
-          $behavior_settings = array();
-        }
-      }
-
-      $form['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['enabled'] = array(
-        '#type' => 'checkbox',
-        '#title' => t('Enable'),
-        '#default_value' => $behavior_settings !== FALSE,
-      );
-
-      $settings_form = ctools_plugin_get_function($behavior_info, 'settings form callback');
-      if ($settings_form) {
-        $form['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['enabled']['#ajax'] = array(
-          'callback' => 'synonyms_behaviors_settings_form_ajax',
-          'wrapper' => $form['synonyms']['behaviors']['#id'],
-        );
-
-        if ($behavior_settings !== FALSE) {
-          $form['synonyms']['behaviors'][$behavior][$implementation['instance_id']]['settings'] = $settings_form($form, $form_state, $behavior_settings);
-        }
-      }
-    }
-  }
-  $form['#submit'][] = 'synonyms_taxonomy_form_vocabulary_submit';
-}
-
-/**
- * Submit handler for Taxonomy vocabulary edit form.
- *
- * Store synonyms behavior settings.
- */
-function synonyms_taxonomy_form_vocabulary_submit($form, &$form_state) {
-  $values = $form_state['values'];
-
-  if ($values['op'] == $form['actions']['submit']['#value']) {
-    foreach ($values['synonyms']['behaviors'] as $behavior => $settings) {
-      foreach ($settings as $instance_id => $behavior_settings) {
-        if ($behavior_settings['enabled']) {
-          synonyms_behavior_settings_save(array(
-            'instance_id' => $instance_id,
-            'behavior' => $behavior,
-            'settings' => isset($behavior_settings['settings']) ? $behavior_settings['settings'] : NULL,
-          ));
-        }
-        else {
-          synonyms_behavior_settings_delete($instance_id, $behavior);
-        }
-      }
-    }
-  }
-}
-
-/**
- * Ajax callback function for synonyms behavior settings form.
- */
-function synonyms_behaviors_settings_form_ajax($form, &$form_state) {
-  return $form['synonyms']['behaviors'];
 }
 
 /**
@@ -245,12 +211,12 @@ function synonyms_behaviors_settings_form_ajax($form, &$form_state) {
  */
 function synonyms_field_widget_info() {
   return array(
-    'synonyms_autocomplete' => array(
-      'label' => t('Synonyms friendly autocomplete term widget'),
+    'synonyms_autocomplete_taxonomy_term' => array(
+      'label' => t('Synonyms friendly autocomplete'),
       'field types' => array('taxonomy_term_reference'),
       'settings' => array(
         'size' => 60,
-        'synonyms_autocomplete_path' => 'synonyms/autocomplete',
+        'synonyms_autocomplete_path' => 'synonyms/autocomplete-taxonomy-term',
         'suggestion_size' => 10,
         'suggest_only_unique' => FALSE,
         'auto_creation' => 1,
@@ -259,7 +225,21 @@ function synonyms_field_widget_info() {
         'multiple values' => FIELD_BEHAVIOR_CUSTOM,
       ),
     ),
-    'synonyms_select' => array(
+    'synonyms_autocomplete_entity' => array(
+      'label' => t('Synonyms friendly autocomplete'),
+      'field types' => array('entityreference'),
+      'settings' => array(
+        'size' => 60,
+        'synonyms_autocomplete_path' => 'synonyms/autocomplete-entity',
+        'suggestion_size' => 10,
+        'suggest_only_unique' => FALSE,
+        'auto_creation' => FALSE,
+      ),
+      'behaviors' => array(
+        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
+      ),
+    ),
+    'synonyms_select_taxonomy_term' => array(
       'label' => t('Synonyms friendly select list'),
       'field types' => array('taxonomy_term_reference'),
       'settings' => array(
@@ -269,6 +249,14 @@ function synonyms_field_widget_info() {
         'multiple values' => FIELD_BEHAVIOR_CUSTOM,
       ),
     ),
+    'synonyms_select_entity' => array(
+      'label' => t('Synonyms friendly select list'),
+      'field types' => array('entityreference'),
+      'settings' => array(),
+      'behaviors' => array(
+        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
+      ),
+    ),
   );
 }
 
@@ -282,13 +270,16 @@ function synonyms_field_widget_settings_form($field, $instance) {
   $form = array();
 
   switch  ($widget['type']) {
-    case 'synonyms_autocomplete':
-      $form['auto_creation'] = array(
-        '#type' => 'checkbox',
-        '#title' => t('Allow auto-creation?'),
-        '#description' => t('Whether users may create a new term by typing in a non-existing name into this field.'),
-        '#default_value' => $settings['auto_creation'],
-      );
+    case 'synonyms_autocomplete_taxonomy_term':
+    case 'synonyms_autocomplete_entity':
+      if ($widget['type'] == 'synonyms_autocomplete_taxonomy_term') {
+        $form['auto_creation'] = array(
+          '#type' => 'checkbox',
+          '#title' => t('Allow auto-creation?'),
+          '#description' => t('Whether users may create a new term by typing in a non-existing name into this field.'),
+          '#default_value' => $settings['auto_creation'],
+        );
+      }
 
       $form['suggestion_size'] = array(
         '#type' => 'textfield',
@@ -307,7 +298,7 @@ function synonyms_field_widget_settings_form($field, $instance) {
       );
       break;
 
-    case 'synonyms_select':
+    case 'synonyms_select_taxonomy_term':
       $form['sort'] = array(
         '#type' => 'radios',
         '#title' => t('Sort'),
@@ -329,21 +320,43 @@ function synonyms_field_widget_settings_form($field, $instance) {
  */
 function synonyms_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
   $default_value = array();
+  $column = array_keys($field['columns']);
+  $column = reset($column);
   foreach ($items as $item) {
-    $default_value[] = $item['tid'];
+    $default_value[] = $item[$column];
   }
 
   switch ($instance['widget']['type']) {
-    case 'synonyms_autocomplete':
-      $tags = taxonomy_term_load_multiple($default_value);
+    case 'synonyms_autocomplete_taxonomy_term':
+    case 'synonyms_autocomplete_entity':
+      switch ($instance['widget']['type']) {
+        case 'synonyms_autocomplete_taxonomy_term':
+          $default_value_string = taxonomy_implode_tags(taxonomy_term_load_multiple($default_value));
+          $element_validate = array('taxonomy_autocomplete_validate', 'synonyms_autocomplete_taxonomy_term_validate');
+          break;
+
+        case 'synonyms_autocomplete_entity':
+          $default_value_string = array();
+          $entity = isset($element['#entity']) ? $element['#entity'] : NULL;
+          $handler = entityreference_get_selection_handler($field, $instance, $instance['entity_type'], $entity);
+
+          $target_entities = entity_load($field['settings']['target_type'], $default_value);
+          foreach ($target_entities as $target_entity_id => $target_entity) {
+            $default_value_string[] = synonyms_autocomplete_escape($handler->getLabel($target_entity));
+          }
+          $default_value_string = implode(', ', $default_value_string);
+
+          $element_validate = array('synonyms_autocomplete_entity_validate');
+          break;
+      }
 
       $element += array(
         '#type' => 'textfield',
-        '#default_value' => taxonomy_implode_tags($tags),
+        '#default_value' => $default_value_string,
         '#autocomplete_path' => $instance['widget']['settings']['synonyms_autocomplete_path'] . '/' . $field['field_name'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'],
         '#size' => $instance['widget']['settings']['size'],
         '#maxlength' => 1024,
-        '#element_validate' => array('taxonomy_autocomplete_validate', 'synonyms_autocomplete_validate'),
+        '#element_validate' => $element_validate,
         '#auto_creation' => $instance['widget']['settings']['auto_creation'],
         '#attached' => array(
           'js' => array(
@@ -356,7 +369,7 @@ function synonyms_field_widget_form(&$form, &$form_state, $field, $instance, $la
       );
       break;
 
-    case 'synonyms_select':
+    case 'synonyms_select_taxonomy_term':
       $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
 
       $options = array();
@@ -367,10 +380,10 @@ function synonyms_field_widget_form(&$form, &$form_state, $field, $instance, $la
               if ($terms = taxonomy_get_tree($vocabulary->vid, $tree['parent'], NULL, TRUE)) {
                 $behavior_implementations = synonyms_behavior_get('select', 'taxonomy_term', field_extract_bundle('taxonomy_term', $vocabulary), TRUE);
                 foreach ($terms as $term) {
-                  $options[] = synonyms_select_option($term);
+                  $options[] = synonyms_select_option_entity($term, 'taxonomy_term', NULL, NULL, array('depth'));
                   foreach ($behavior_implementations as $implementation) {
                     foreach (synonyms_extract_synonyms($term, $implementation) as $synonym) {
-                      $options[] = synonyms_select_option($term, $synonym, $implementation);
+                      $options[] = synonyms_select_option_entity($term, 'taxonomy_term', $synonym, $implementation, array('depth'));
                     }
                   }
                 }
@@ -379,22 +392,62 @@ function synonyms_field_widget_form(&$form, &$form_state, $field, $instance, $la
 
             case 'name':
               // TODO: is there any way to leverage DB for the sorting routine?
-              $options = synonyms_select_sort_name_options_recursive($vocabulary, $tree['parent']);
+              $options = synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $tree['parent']);
               break;
           }
         }
       }
 
-      if (!$multiple && !$element['#required']) {
-        $options = array('' => t('- None -')) + $options;
+      $element += array(
+        '#type' => 'select',
+        '#multiple' => $multiple,
+        '#options' => $options,
+        '#default_value' => $default_value,
+        '#element_validate' => array('synonyms_select_form_to_storage'),
+        '#empty_option' => t('- None -'),
+      );
+      break;
+
+    case 'synonyms_select_entity':
+      $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
+
+      $options = entityreference_get_selection_handler($field, $instance, $instance['entity_type'], $element['#entity'])->getReferencableEntities();
+      $synonyms_options = array();
+
+      $target_entity_info = entity_get_info($field['settings']['target_type']);
+      $entity_ids = array();
+      foreach ($options as $bundle_entity_ids) {
+        $entity_ids = array_merge($entity_ids, array_keys($bundle_entity_ids));
+      }
+      $entities = entity_load($field['settings']['target_type'], $entity_ids);
+      foreach ($options as $bundle => $bundle_entity_ids) {
+        $synonyms_options[$target_entity_info['bundles'][$bundle]['label']] = array();
+
+        $behavior_implementations = synonyms_behavior_get('select', $field['settings']['target_type'], $bundle, TRUE);
+
+        foreach ($bundle_entity_ids as $entity_id => $v) {
+          $entity = $entities[$entity_id];
+          $synonyms_options[$target_entity_info['bundles'][$bundle]['label']][] = synonyms_select_option_entity($entity, $field['settings']['target_type']);
+          foreach ($behavior_implementations as $behavior_implementation) {
+            foreach (synonyms_extract_synonyms($entity, $behavior_implementation) as $synonym) {
+              $synonyms_options[$target_entity_info['bundles'][$bundle]['label']][] = synonyms_select_option_entity($entity, $field['settings']['target_type'], $synonym, $behavior_implementation);
+            }
+          }
+        }
+        usort($synonyms_options[$target_entity_info['bundles'][$bundle]['label']], 'synonyms_select_sort_name');
+      }
+
+      if (count($synonyms_options) == 1) {
+        $synonyms_options = reset($synonyms_options);
       }
 
       $element += array(
         '#type' => 'select',
         '#multiple' => $multiple,
-        '#options' => $options,
+        '#options' => $synonyms_options,
         '#default_value' => $default_value,
         '#element_validate' => array('synonyms_select_form_to_storage'),
+        '#empty_option' => t('- None -'),
       );
       break;
   }
@@ -414,13 +467,15 @@ function synonyms_field_widget_error($element, $error, $form, &$form_state) {
  *
  * Handle validation for taxonomy term synonym-friendly autocomplete element.
  */
-function synonyms_autocomplete_validate($element, &$form_state) {
+function synonyms_autocomplete_taxonomy_term_validate($element, &$form_state) {
   // After taxonomy_autocomplete_validate() has finished its job any terms it
   // didn't find have been set for autocreation. We need to:
   // (a) Double-check that those terms are not synonyms.
   // (b) Check that synonyms' configurable auto-creation option is enabled.
   $value = drupal_array_get_nested_value($form_state['values'], $element['#parents']);
 
+  $tids = array();
+
   $field = field_widget_field($element, $form_state);
   foreach ($value as $delta => $term) {
     if ($term['tid'] == 'autocreate') {
@@ -428,7 +483,7 @@ function synonyms_autocomplete_validate($element, &$form_state) {
       foreach ($field['settings']['allowed_values'] as $tree) {
         $behavior_implementations = synonyms_behavior_get('autocomplete', 'taxonomy_term', $tree['vocabulary'], TRUE);
         foreach ($behavior_implementations as $behavior_implementation) {
-          $synonyms = synonyms_synonyms_find_behavior(db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $term['name']), $behavior_implementation);
+          $synonyms = synonyms_synonyms_find_behavior(db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $term['name']), $behavior_implementation);
           foreach ($synonyms as $synonym) {
             $synonym_tid = $synonym->entity_id;
             break(2);
@@ -436,21 +491,112 @@ function synonyms_autocomplete_validate($element, &$form_state) {
         }
       }
 
-      if ($synonym_tid != 0) {
+      if ($synonym_tid != 0 && !in_array($synonym_tid, $tids)) {
         $value[$delta]['tid'] = $synonym_tid;
+        $tids[] = $synonym_tid;
       }
       elseif (!$element['#auto_creation']) {
         unset($value[$delta]);
       }
     }
+    else {
+      $tids[] = $term['tid'];
+    }
   }
   $value = array_values($value);
   form_set_value($element, $value, $form_state);
 }
 
 /**
+ * Form element validate handler.
+ *
+ * Validate entity reference synonyms friendly autocomplete element.
+ */
+function synonyms_autocomplete_entity_validate($element, &$form_state) {
+  $input = drupal_map_assoc(drupal_explode_tags(drupal_strtolower($element['#value'])));
+
+  $value = array();
+  if (!empty($input)) {
+    $field = field_info_field($element['#field_name']);
+    $instance = field_info_instance($element['#entity_type'], $field['field_name'], $element['#bundle']);
+    $handler = entityreference_get_selection_handler($field, $instance);
+    $matches = $handler->getReferencableEntities($input, 'IN');
+
+    foreach ($matches as $bundle => $entity_ids) {
+      foreach ($entity_ids as $entity_id => $label) {
+        $value[] = $entity_id;
+        unset($input[drupal_strtolower($label)]);
+      }
+    }
+
+    if (!empty($input)) {
+      $behavior_implementations = synonyms_behavior_get('autocomplete', $field['settings']['target_type'], synonyms_field_target_bundles($field), TRUE);
+      foreach ($behavior_implementations as $implementation) {
+        $condition = db_and();
+        $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $input, 'IN');
+        foreach (synonyms_synonyms_find_behavior($condition, $implementation) as $synonym) {
+          unset($input[drupal_strtolower($synonym->synonym)]);
+          $value[] = $synonym->entity_id;
+        }
+      }
+    }
+  }
+
+  $tmp = array_unique($value);
+  $value = array();
+  foreach ($tmp as $target_id) {
+    $value[] = array('target_id' => $target_id);
+  }
+
+  form_set_value($element, $value, $form_state);
+}
+
+/**
+ * Try finding an entity by its name or synonym.
+ *
+ * @param string $entity_type
+ *   What entity type is being searched
+ * @param string $name
+ *   The look up keyword (the supposed name or synonym)
+ * @param string $bundle
+ *   Optionally limit the search within a specific bundle name of the provided
+ *   entity type
+ *
+ * @return int
+ *   ID of the looked up entity. If such entity was not found, then 0 is
+ *   returned
+ */
+function synonyms_get_entity_by_synonym($entity_type, $name, $bundle = NULL) {
+  $name = trim($name);
+  $entity_info = entity_get_info($entity_type);
+  if (isset($entity_info['entity keys']['label'])) {
+    $efq = new EntityFieldQuery();
+    $efq->entityCondition('entity_type', $entity_type);
+    if ($bundle) {
+      $efq->entityCondition('bundle', $bundle);
+    }
+    $efq->propertyCondition($entity_info['entity keys']['label'], $name);
+    $result = $efq->execute();
+    if (isset($result[$entity_type])) {
+      $result = array_keys($result[$entity_type]);
+      return reset($result);
+    }
+  }
+
+  $synonyms = synonyms_synonyms_find(db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $name), $entity_type, $bundle);
+  if (!empty($synonyms)) {
+    return reset($synonyms)->entity_id;
+  }
+  return 0;
+}
+
+/**
  * Try to find a term by its name or synonym.
  *
+ * You are adviced to use the more general function
+ * synonyms_get_entity_by_synonym() unless you really need $parent input
+ * argument from this function for additional filtering by Taxonomy hierarchy.
+ *
  * @param string $name
  *   The string to be searched for its {taxonomy_term_data}.tid
  * @param object $vocabulary
@@ -465,6 +611,9 @@ function synonyms_autocomplete_validate($element, &$form_state) {
  *   found term, otherwise returns 0
  */
 function synonyms_get_term_by_synonym($name, $vocabulary, $parent = 0) {
+  if (!module_exists('taxonomy')) {
+    return 0;
+  }
   $name = trim($name);
 
   $terms = taxonomy_get_term_by_name($name, $vocabulary->machine_name);
@@ -481,7 +630,7 @@ function synonyms_get_term_by_synonym($name, $vocabulary, $parent = 0) {
   // We have failed to find a term with the provided $name. So let's search now
   // among the term synonyms.
   $bundle = field_extract_bundle('taxonomy_term', $vocabulary);
-  $synonyms = synonyms_synonyms_find(db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $name), 'taxonomy_term', $bundle);
+  $synonyms = synonyms_synonyms_find(db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $name), 'taxonomy_term', $bundle);
   foreach ($synonyms as $synonym) {
     if (!$parent || synonyms_taxonomy_term_is_child_of($synonym->entity_id, $parent)) {
       // TODO: similarly here, as above, we could have more than 1 match, but
@@ -515,6 +664,9 @@ function synonyms_get_term_by_synonym($name, $vocabulary, $parent = 0) {
  *   otherwise it creates a new term and returns its {taxonomy_term_data}.tid
  */
 function synonyms_add_term_by_synonym($name, $vocabulary, $parent = 0) {
+  if (!module_exists('taxonomy')) {
+    return 0;
+  }
   $tid = synonyms_get_term_by_synonym($name, $vocabulary, $parent);
   if ($tid) {
     // We found some term, returning its tid.
@@ -540,35 +692,35 @@ function synonyms_add_term_by_synonym($name, $vocabulary, $parent = 0) {
 }
 
 /**
- * Retrieve a list of sanitized synonyms of a taxonomy term.
+ * Retrieve list of sanitized synonyms of an entity.
  *
- * @param $item object
- *   Fully loaded taxonomy term
+ * @param $entity object
+ *   Fully loaded entity
  *
  * @return array
- *   List of sanitized synonyms of a taxonomy term
+ *   List of sanitized synonyms of an entity
  */
-function synonyms_get_sanitized($item) {
-  $synonyms = array();
-  foreach (synonyms_get_term_synonyms($item) as $synonym) {
-    $synonyms[] = $synonym['safe_value'];
-  }
-  return $synonyms;
+function synonyms_get_sanitized($entity, array $options, $name, $entity_type, &$context) {
+  return array_map('check_plain', synonyms_get_raw($entity, $options, $name, $entity_type, $context));
 }
 
 /**
- * Retrieve a list of raw synonyms of a taxonomy term.
+ * Retrieve list of raw synonyms of an entity.
  *
- * @param $item object
- *   Fully loaded taxonomy term
+ * @param $entity object
+ *   Fully loaded entity
  *
  * @return array
- *   List of raw synonyms of a taxonomy term
+ *   List of raw synonyms of an entity
  */
-function synonyms_get_raw($item) {
+function synonyms_get_raw($entity, array $options, $name, $entity_type, &$context) {
   $synonyms = array();
-  foreach (synonyms_get_term_synonyms($item) as $synonym) {
-    $synonyms[] = $synonym['value'];
+  $bundle = entity_extract_ids($entity_type, $entity);
+  $bundle = $bundle[2] ? $bundle[2] : $entity_type;
+
+  $behavior_implementations = synonyms_behavior_get_all_enabled($entity_type, $bundle);
+  foreach ($behavior_implementations as $implementation) {
+    $synonyms = array_merge($synonyms, synonyms_extract_synonyms($entity, $implementation));
   }
   return $synonyms;
 }
@@ -592,19 +744,22 @@ function synonyms_get_raw($item) {
  * @deprecated
  */
 function synonyms_get_term_synonyms($term) {
+  if (!module_exists('taxonomy')) {
+    return array();
+  }
   $synonyms = array();
   $vocabulary = taxonomy_vocabulary_load($term->vid);
   $bundle = field_extract_bundle('taxonomy_term', $vocabulary);
 
-  $behavior_implementations = synonyms_behavior_get('synonyms', 'taxonomy_term', $bundle, TRUE);
+  $behavior_implementations = synonyms_behavior_get_all_enabled('taxonomy_term', $bundle);
   foreach ($behavior_implementations as $implementation) {
     foreach  (synonyms_extract_synonyms($term, $implementation) as $synonym) {
-        $synonyms[] = array(
-          'value' => $synonym,
-          'safe_value' => check_plain($synonym),
-        );
-      }
+      $synonyms[] = array(
+        'value' => $synonym,
+        'safe_value' => check_plain($synonym),
+      );
     }
+  }
 
   return $synonyms;
 }
@@ -650,19 +805,20 @@ function synonyms_extract_synonyms($entity, $behavior_implementation) {
  * @param QueryConditionInterface $condition
  *   Object of QueryConditionInterface that specifies conditions by which you
  *   want to find synonyms. When building this condition object, use
- *   AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER as a placeholder for
- *   real column name that contains synonym as text. For example, if you were to
- *   find all entities with synonyms that begin with "synonym-come-here"
- *   substring, case insensitive and replacing all spaces in original synonym
- *   string by a dash sign, then you would have to create the following
- *   condition object:
+ *   AbstractSynonymsBehavior::COLUMN_PLACEHOLDER as a placeholder for real
+ *   column name that contains synonym as text. For example, if you were to find
+ *   all entities with synonyms that begin with "synonym-come-here" substring,
+ *   case insensitive and replacing all spaces in original synonym string by a
+ *   dash sign, then you would have to create the following condition object:
  *   db_and()
- *     ->where("LOWER(REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-')) LIKE 'synonym-come-here%'")
+ *     ->where("LOWER(REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-')) LIKE 'synonym-come-here%'")
  *   And then just supply this object as an input parameter to this function
  * @param string $entity_type
  *   Among synonyms of what entity type to search
- * @param string $bundle
- *   Among synonyms of what bundle to search
+ * @param string|array $bundle
+ *   Optionally specifcy among synonyms of what bundle(-s) to search. You can
+ *   specify here a string - bundle name to search within or an array of bundles
+ *   within which to search
  *
  * @return array
  *   Array of found synonyms and entity IDs to which those belong. Each element
@@ -671,10 +827,10 @@ function synonyms_extract_synonyms($entity, $behavior_implementation) {
  *     $condition you specified
  *   - entity_id: (int) ID of the entity to which the found synonym belongs
  */
-function synonyms_synonyms_find(QueryConditionInterface $condition, $entity_type, $bundle) {
+function synonyms_synonyms_find(QueryConditionInterface $condition, $entity_type, $bundle = NULL) {
   $rows = array();
 
-  $behavior_implementations = synonyms_behavior_get('synonyms', $entity_type, $bundle, TRUE);
+  $behavior_implementations = synonyms_behavior_get_all_enabled($entity_type, $bundle);
   foreach ($behavior_implementations as $behavior_implementation) {
     foreach (synonyms_synonyms_find_behavior($condition, $behavior_implementation) as $row) {
       $rows[] = $row;
@@ -702,14 +858,13 @@ function synonyms_synonyms_find(QueryConditionInterface $condition, $entity_type
  * @param QueryConditionInterface $condition
  *   Object of QueryConditionInterface that specifies conditions by which you
  *   want to find synonyms. When building this condition object, use
- *   AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER as a placeholder for
- *   real column name that contains synonym as text. For example, if you were to
- *   find all entities with synonyms that begin with "synonym-come-here"
- *   substring, case insensitive and replacing all spaces in original synonym
- *   string by a dash sign, then you would have to create the following
- *   condition object:
+ *   AbstractSynonymsBehavior::COLUMN_PLACEHOLDER as a placeholder for real
+ *   column name that contains synonym as text. For example, if you were to find
+ *   all entities with synonyms that begin with "synonym-come-here" substring,
+ *   case insensitive and replacing all spaces in original synonym string by a
+ *   dash sign, then you would have to create the following condition object:
  *   db_and()
- *     ->where("LOWER(REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-')) LIKE 'synonym-come-here%'")
+ *     ->where("LOWER(REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-')) LIKE 'synonym-come-here%'")
  *   And then just supply this object as an input parameter to this function
  * @param array $behavior_implementation
  *   Fully loaded behavior implementation. Supply here one of the values from
@@ -759,27 +914,23 @@ function synonyms_synonyms_find_behavior(QueryConditionInterface $condition, $be
  *   Whether synonym has been successfully added
  */
 function synonyms_add_entity_as_synonym($trunk_entity, $trunk_entity_type, $field, $synonym_entity, $synonym_entity_type) {
-  if ($trunk_entity_type != 'taxonomy_term') {
-    // Currently synonyms module only operates on taxonomy terms.
-    return FALSE;
-  }
-
   $bundle = entity_extract_ids($trunk_entity_type, $trunk_entity);
-  $bundle = $bundle[2];
-  $behavior_implementations = synonyms_behavior_get('synonyms', $trunk_entity_type, $bundle, TRUE);
+  $bundle = $bundle[2] ? $bundle[2] : $trunk_entity_type;
+  $behavior_implementations = synonyms_behavior_get_all_enabled($trunk_entity_type, $bundle, $field);
 
   $field = field_info_field($field);
   $instance = field_info_instance($trunk_entity_type, $field['field_name'], $bundle);
-  if (!isset($behavior_implementations[$instance['id']])) {
-    // $field either doesn't exist in the $trunk_entity or it does not have
-    // enabled the behavior of synonyms.
+  if (empty($behavior_implementations)) {
+    // $field either doesn't exist in the $trunk_entity or it does not have any
+    // enabled behavior.
     return FALSE;
   }
 
   $items = field_get_items($trunk_entity_type, $trunk_entity, $field['field_name']);
   $items = is_array($items) ? $items : array();
 
-  $object = synonyms_behavior_implementation_class('synonyms', $field);
+  $behavior_implementation = reset($behavior_implementations);
+  $object = synonyms_behavior_implementation_class($behavior_implementation['behavior'], $field);
   $object = new $object();
   $extra_items = $object->mergeEntityAsSynonym($items, $field, $instance, $synonym_entity, $synonym_entity_type);
 
@@ -805,9 +956,8 @@ function synonyms_add_entity_as_synonym($trunk_entity, $trunk_entity_type, $fiel
   $items = array_values($unique_items);
 
   $trunk_entity->{$field['field_name']}[LANGUAGE_NONE] = $items;
-  // In future if this module eventually becomes a gateway for synonyms for any
-  // entity types, we'll substitute it with entity_save().
-  taxonomy_term_save($trunk_entity);
+
+  entity_save($trunk_entity_type, $trunk_entity);
   return TRUE;
 }
 
@@ -829,9 +979,12 @@ function synonyms_add_entity_as_synonym($trunk_entity, $trunk_entity_type, $fiel
  * @deprecated
  */
 function synonyms_synonyms_fields($vocabulary) {
+  if (!module_exists('taxonomy')) {
+    return array();
+  }
   $fields = array();
   $bundle = field_extract_bundle('taxonomy_term', $vocabulary);
-  $behavior_implementations = synonyms_behavior_get('synonyms', 'taxonomy_term', $bundle, TRUE);
+  $behavior_implementations = synonyms_behavior_get_all_enabled('taxonomy_term', $bundle);
   foreach ($behavior_implementations as $v) {
     $fields[] = $v['field_name'];
   }
@@ -857,10 +1010,11 @@ function synonyms_views_api() {
  * @param string $entity_type
  *   Optional filter to limit the search for existing implementations only to
  *   those that apply to the provided entity type
- * @param string $bundle
+ * @param string|array $bundle
  *   Optional filter to limit the search for existing implementations only to
  *   those that apply to the provided bundle and entity type (the $entity_type
- *   argument)
+ *   argument). You may supply array of bundle names if you want to limit your
+ *   search within a few bundles
  * @param bool $only_enabled
  *   Optional filter to limit the search for existing implementations only to
  *   those that are currently enabled
@@ -920,6 +1074,59 @@ function synonyms_behavior_get($behavior, $entity_type = NULL, $bundle = NULL, $
 }
 
 /**
+ * Load all enabled behaviors on an entity_type and a bundle.
+ *
+ * This is useful when you want to do some operation on all enabled synonyms
+ * behaviors for a specific entity_type and a bundle.
+ *
+ * @param string $entity_type
+ *   Entity type whose enabled behaviors should be loaded
+ * @param string|array $bundle
+ *   Optionally filter by bundle whose enabled behaviors should be loaded. You
+ *   can supply here string - single bundle name or an array of bundle names
+ * @param string $field_name
+ *   Optional filter to only return enabled synonyms behaviors of a specific
+ *   field
+ *
+ * @return array
+ *   Array of enabled behaviors for a provided entity type and a bundle. Each
+ *   sub array will have the following structure:
+ *   - behavior: (string) Name of the synonyms behavior
+ *   - settings: (mixed) Behavior settings, its internal structure depends on
+ *     the type of behavior.
+ *   - entity_type: (string) Entity type to which this behavior implementation
+ *     applies
+ *   - bundle: (string) Bundle name to which this behavior implementation
+ *     applies
+ *   - field_name: (string) Name of the field on which this synonyms behavior is
+ *     enabled
+ *   - instance_id: (int) ID of the field instance to which this behavior
+ *     implementation applies
+ */
+function synonyms_behavior_get_all_enabled($entity_type, $bundle = NULL, $field_name = NULL) {
+  $query = db_select('synonyms_settings', 's');
+  $instance_alias = $query->innerJoin('field_config_instance', 'i', 'i.id = s.instance_id');
+  $query->fields($instance_alias, array('field_name', 'entity_type', 'bundle'));
+  $query->fields('s', array('behavior', 'settings_serialized'));
+  $query->addField($instance_alias, 'id', 'instance_id');
+
+  $query->condition($instance_alias . '.entity_type', $entity_type);
+  if ($bundle) {
+    $query->condition($instance_alias . '.bundle', $bundle);
+  }
+  if ($field_name) {
+    $query->condition($instance_alias . '.field_name', $field_name);
+  }
+
+  $result = $query->execute();
+  $rows = array();
+  foreach ($result as $row) {
+    $rows[] = (array) $row;
+  }
+  return synonyms_behavior_settings_unpack($rows);
+}
+
+/**
  * Retrieve information about all ctools plugins of type 'synonyms behavior'.
  *
  * @return array
@@ -1043,9 +1250,11 @@ function synonyms_behavior_settings_delete($instance_id, $behavior) {
   $disabled_callback = ctools_plugin_get_function($behavior_definition, 'disabled callback');
   if ($disabled_callback) {
     $instance = synonyms_instance_id_load($instance_id);
-    $behavior_implementation = synonyms_behavior_get($behavior, $instance['entity_type'], $instance['bundle'], FALSE, TRUE);
-    $behavior_implementation = $behavior_implementation[$instance_id];
-    $disabled_callback($behavior_definition, $behavior_implementation, $instance);
+    $behavior_implementation = synonyms_behavior_get($behavior, $instance['entity_type'], $instance['bundle'], TRUE, TRUE);
+    if (isset($behavior_implementation[$instance_id])) {
+      $behavior_implementation = $behavior_implementation[$instance_id];
+      $disabled_callback($behavior_definition, $behavior_implementation, $instance);
+    }
   }
   db_delete('synonyms_settings')
     ->condition('instance_id', $instance_id)
@@ -1058,17 +1267,23 @@ function synonyms_behavior_settings_delete($instance_id, $behavior) {
  *
  * @param int $instance_id
  *   ID of the instance that should be loaded
+ * @param bool $reset
+ *   Whether to reset static cache of this function
  *
  * @return array
  *   Instance definition array
  */
-function synonyms_instance_id_load($instance_id) {
-  $result = db_select('field_config_instance', 'i')
-    ->fields('i', array('entity_type', 'bundle', 'field_name'))
-    ->condition('id', $instance_id)
-    ->execute()
-    ->fetchAssoc();
-  return field_info_instance($result['entity_type'], $result['field_name'], $result['bundle']);
+function synonyms_instance_id_load($instance_id, $reset = FALSE) {
+  $cache = &drupal_static(__FUNCTION__, array(), $reset);
+
+  if (!isset($cache[$instance_id])) {
+    $cache[$instance_id] = db_select('field_config_instance', 'i')
+      ->fields('i', array('entity_type', 'bundle', 'field_name'))
+      ->condition('id', $instance_id)
+      ->execute()
+      ->fetchAssoc();
+  }
+  return field_info_instance($cache[$instance_id]['entity_type'], $cache[$instance_id]['field_name'], $cache[$instance_id]['bundle']);
 }
 
 /**
@@ -1088,23 +1303,24 @@ function synonyms_select_form_to_storage($element, &$form_state) {
   }
 
   foreach ($value as $k => $v) {
-    // For the cases when a synonym was selected and not a term option, we
+    // For the cases when a synonym was selected and not an entity option, we
     // process the selected values stripping everything that goes after
     // semicolon.
     if (!is_numeric($v)) {
-      $tid = explode(':', $v);
-      $value[$k] = $tid[0];
+      $id = explode(':', $v);
+      $value[$k] = $id[0];
     }
   }
 
-  // The user also might have selected multiple times the same term, given that
-  // a term can be represented by more than 1 option (a term and its synonym),
-  // then it's possible in theory, so we should be ready for this scenario.
+  // The user also might have selected multiple times the same entity, given
+  // that an entity can be represented by more than 1 option (an entity and its
+  // synonym), then it's possible in theory, so we should be ready for this
+  // scenario.
   $value = array_unique($value);
 
   $form_state_value = array();
-  foreach ($value as $tid) {
-    $form_state_value[] = array('tid' => $tid);
+  foreach ($value as $id) {
+    $form_state_value[] = array($element['#columns'][0] => $id);
   }
 
   form_set_value($element, $form_state_value, $form_state);
@@ -1141,37 +1357,53 @@ function synonyms_taxonomy_term_is_child_of($tid, $parent_tid) {
 }
 
 /**
- * Format an option for select form element.
+ * Format an option for entity reference select form element.
  *
- * @param object $term
- *   Fully loaded taxonomy term which is represented by this option
+ * @param object $entity
+ *   Fully loaded entity which is represented by this option
+ * @param string $entity_type
+ *   Entity type of the $entity object
  * @param string $synonym
- *   If the provided term is represented in this option by a synonym, then
+ *   If the provided entity is represented in this option by a synonym, then
  *   provide it here
  * @param array $behavior_implementation
  *   Behavior implementation array from which the $synonym comes from
+ * @param array $options
+ *   Array of additional settings or options that may influence execution of
+ *   this function. Currently supported options are:
+ *   - depth: Whether to prefix wording of option labels with depth of the
+ *     entity. This will work only for taxonomy term entities, as they are the
+ *     only ones that have notion of depth
  *
  * @return object
- *   An option for select form element
+ *   An option for entity reference select form element
  */
-function synonyms_select_option($term, $synonym = NULL, $behavior_implementation = NULL) {
-  $key = $synonym ? $term->tid . ':' . drupal_html_class($synonym) : $term->tid;
-  $wording = $term->name;
+function synonyms_select_option_entity($entity, $entity_type, $synonym = NULL, $behavior_implementation = NULL, $options = array()) {
+  $entity_id = entity_extract_ids($entity_type, $entity);
+  $entity_id = $entity_id[0];
+  $key = $synonym ? $entity_id . ':' . drupal_html_class($synonym) : $entity_id;
+  $wording = entity_label($entity_type, $entity);
   if ($synonym) {
     $instance = field_info_instance($behavior_implementation['entity_type'], $behavior_implementation['field_name'], $behavior_implementation['bundle']);
     $wording = format_string($behavior_implementation['settings']['wording'], array(
       '@synonym' => $synonym,
-      '@term' => $term->name,
+      '@entity' => entity_label($behavior_implementation['entity_type'], $entity),
       '@field_name' => drupal_strtolower($instance['label']),
     ));
   }
+
+  if (in_array('depth', $options) && $entity_type == 'taxonomy_term') {
+    $depth = count(taxonomy_get_parents_all($entity_id)) - 1;
+    $wording = str_repeat('-', $depth) . $wording;
+  }
+
   return (object) array(
-    'option' => array($key => str_repeat('-', $term->depth) . $wording),
+    'option' => array($key => $wording),
   );
 }
 
 /**
- * Supportive function to build options array with sorting by name logic.
+ * Supportive function to build taxonomy term options array sorted by name.
  *
  * The function starts from the 0-depth level and starts to recursively build
  * the options and to sort the labels on each level, then it merges the bottom
@@ -1194,10 +1426,10 @@ function synonyms_select_option($term, $synonym = NULL, $behavior_implementation
  *   The options will be sorted by name (term or synonym), respecting the
  *   hierarchy restrictions
  */
-function synonyms_select_sort_name_options_recursive($vocabulary, $parent = 0, $depth = 0) {
+function synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $parent = 0, $depth = 0) {
   // We statically cache behavior implementations in order to not DDOS the data
   // base.
-  $behavior_implementations = drupal_static(__FUNCTION__, array());
+  $behavior_implementations = &drupal_static(__FUNCTION__, array());
 
   $bundle = field_extract_bundle('taxonomy_term', $vocabulary);
   if (!isset($behavior_implementations[$bundle])) {
@@ -1209,10 +1441,10 @@ function synonyms_select_sort_name_options_recursive($vocabulary, $parent = 0, $
     $options = array();
     foreach ($terms as $term) {
       $term->depth = $depth;
-      $options[] = synonyms_select_option($term);
+      $options[] = synonyms_select_option_entity($term, 'taxonomy_term', NULL, NULL, array('depth'));
       foreach ($behavior_implementations[$bundle] as $implementation) {
         foreach (synonyms_extract_synonyms($term, $implementation) as $synonym) {
-          $options[] = synonyms_select_option($term, $synonym, $implementation);
+          $options[] = synonyms_select_option_entity($term, 'taxonomy_term', $synonym, $implementation, array('depth'));
         }
       }
     }
@@ -1228,7 +1460,7 @@ function synonyms_select_sort_name_options_recursive($vocabulary, $parent = 0, $
       $tid = array_keys($v->option);
       $tid = $tid[0];
       if (is_numeric($tid)) {
-        $nested_options = synonyms_select_sort_name_options_recursive($vocabulary, $tid, $depth + 1);
+        $nested_options = synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $tid, $depth + 1);
         $options = array_merge(array_slice($options, 0, $i), $nested_options, array_slice($options, $i));
       }
     }
@@ -1244,3 +1476,105 @@ function synonyms_select_sort_name_options_recursive($vocabulary, $parent = 0, $
 function synonyms_select_sort_name($a, $b) {
   return strcasecmp(reset($a->option), reset($b->option));
 }
+
+/**
+ * Test if entity type is applicable for having synonyms.
+ *
+ * Only fieldable entity types can have synonyms for the very reason that
+ * synonyms are stored in fields.
+ *
+ * @param string $entity_type
+ *   Entity type to test
+ *
+ * @return bool|string
+ *   Whether the provided entity type is applicable for having synonyms. If it
+ *   is applicable, the $entity_type input argument will be returned. Otherwise
+ *   FALSE is returned
+ */
+function synonyms_entity_type_load($entity_type) {
+  $entity_info = entity_get_info($entity_type);
+  if ($entity_info && $entity_info['fieldable']) {
+    return $entity_type;
+  }
+  return FALSE;
+}
+
+/**
+ * Test if provided entity type and bundle exist.
+ *
+ * @param string $bundle
+ *   Bundle name to test for existence
+ * @param string $entity_type
+ *   Entity type to test for existence
+ *
+ * @return bool|string
+ *   Whether the provided entity type and bundle exist. If they exist, the
+ *   $bundle input argument is returned. Otherwise FALSE is returned
+ */
+function synonyms_bundle_load($bundle, $entity_type) {
+  $entity_info = entity_get_info($entity_type);
+  if ($entity_info && isset($entity_info['bundles'][$bundle])) {
+    return $bundle;
+  }
+  return FALSE;
+}
+
+/**
+ * Menu title callback function for synonyms settings page.
+ *
+ * @param string $entity_type
+ *   Entity type whose synonyms settings are managed
+ * @param string $bundle
+ *   Bundle whose synonyms settings are managed
+ *
+ * @return string
+ *   Title of the synonyms settings page
+ */
+function synonyms_settings_title($entity_type, $bundle) {
+  $entity_info = entity_get_info($entity_type);
+  $entity_label = isset($entity_info['plural label']) ? $entity_info['plural label'] : $entity_info['label'];
+  if ($entity_type == $bundle) {
+    return t('Synonyms settings of @entity_type', array(
+      '@entity_type' => $entity_label,
+    ));
+  }
+  return t('Synonyms settings of @bundle @entity_type', array(
+    '@bundle' => $entity_info['bundles'][$bundle]['label'],
+    '@entity_type' => $entity_label,
+  ));
+}
+
+/**
+ * Escape string to safely use in autocomplete text field as default value.
+ *
+ * @param string $value
+ *   String to be escaped
+ *
+ * @return string
+ *   Escaped string $value
+ */
+function synonyms_autocomplete_escape($value) {
+  // Commas or quotes must be wrapped in quotes.
+  if (strpos($value, ',') !== FALSE || strpos($value, '"') !== FALSE) {
+    $value = '"' . str_replace('"', '""', $value) . '"';
+  }
+  return $value;
+}
+
+/**
+ * Determine a list of target bundles of an entityreference field.
+ *
+ * @param array $field
+ *   Field definition array. This field must be of type 'entityreference'
+ *
+ * @return array|null
+ *   List of target bundles per the settings of provided field or NULL if the
+ *   provided field does not expose any limitations on target bundles
+ */
+function synonyms_field_target_bundles($field) {
+  $target_bundles = isset($field['settings']['handler_settings']['target_bundles']) ? array_values($field['settings']['handler_settings']['target_bundles']) : array();
+  if (empty($target_bundles)) {
+    $target_bundles = NULL;
+  }
+  return $target_bundles;
+}
diff --git a/synonyms.pages.inc b/synonyms.pages.inc
index 04e6ec2..e37a0c9 100644
--- a/synonyms.pages.inc
+++ b/synonyms.pages.inc
@@ -26,7 +26,7 @@
  *   autocomplete form element. Only the last term is used for autocompletion.
  *   Defaults to '' (an empty string).
  */
-function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed = '') {
+function synonyms_autocomplete_taxonomy_term($field_name, $entity_type, $bundle, $tags_typed = '') {
   // If the request has a '/' in the search text, then the menu system will have
   // split it into multiple arguments, recover the intended $tags_typed.
   $args = func_get_args();
@@ -56,7 +56,7 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
     exit;
   }
 
-  $widget = $instance['widget']['type'] == 'synonyms_autocomplete' ? $instance['widget']['settings'] : field_info_widget_settings('synonyms_autocomplete');
+  $widget = $instance['widget']['type'] == 'synonyms_autocomplete_taxonomy_term' ? $instance['widget']['settings'] : field_info_widget_settings('synonyms_autocomplete_taxonomy_term');
 
   // How many suggestions maximum we are able to output.
   $max_suggestions = $widget['suggestion_size'];
@@ -81,7 +81,14 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
     }
   }
 
-  $term_matches = array();
+  // Array of found suggestions. Each subarray of this array will represent a
+  // single suggestion entry.
+  // - tid: (int) tid of the suggested term
+  // - name: (string) name of the suggested term
+  // - synonym: (string) optional synonym string that matched this entry
+  // - behavior_implementation: (array) optional behavior implementation that
+  //   provided the synonym
+  $tags_return = array();
   if ($tag_last != '') {
     // Part of the criteria for the query come from the field's own settings.
     $vocabularies = array();
@@ -91,14 +98,6 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
     }
     $vocabularies = taxonomy_vocabulary_load_multiple(array_keys($vocabularies));
 
-    // Array of found suggestions. Each subarray of this array will represent
-    // a single suggestion entry. The sub array must contain the following keys:
-    // - tid: (int) tid of the suggested term
-    // - name: (string) name of the suggested term
-    // - wording: (string) human friendly XSS escaped text of the suggestion
-    //   entry
-    $tags_return = array();
-
     // Firstly getting a list of tids that match by $term->name.
     $query = db_select('taxonomy_term_data', 't');
     $query->addTag('translatable');
@@ -116,9 +115,7 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
       ->range(0, $max_suggestions)
       ->execute();
     foreach ($result as $v) {
-      $v = (array) $v;
-      $v['wording'] = check_plain($v['name']);
-      $tags_return[] = $v;
+      $tags_return[] = (array) $v;
     }
 
     // Now we go vocabulary by vocabulary looking through synonym fields.
@@ -129,7 +126,7 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
       $behavior_implementations = synonyms_behavior_get('autocomplete', 'taxonomy_term', $bundle, TRUE);
       foreach ($behavior_implementations as $implementation) {
         $condition = db_and();
-        $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like($tag_last) . '%', 'LIKE');
+        $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like($tag_last) . '%', 'LIKE');
 
         if (!empty($tags_typed_tids)) {
           $condition->condition('entity_id', $tags_typed_tids, 'NOT IN');
@@ -149,7 +146,7 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
               'tid' => $synonym->entity_id,
               'name' => '',
               'synonym' => $synonym->synonym,
-              'implementation' => $implementation,
+              'behavior_implementation' => $implementation,
             );
             $new_tids[] = $synonym->entity_id;
           }
@@ -168,36 +165,202 @@ function synonyms_autocomplete($field_name, $entity_type, $bundle, $tags_typed =
       $synonym_terms = taxonomy_term_load_multiple($synonym_terms);
       foreach ($tags_return as &$v) {
         if (isset($v['synonym'])) {
-          $instance = field_info_instance($v['implementation']['entity_type'], $v['implementation']['field_name'], $v['implementation']['bundle']);
           $v['name'] = $synonym_terms[$v['tid']]->name;
-          $v['wording'] = format_string(filter_xss($v['implementation']['settings']['wording']), array(
-            '@synonym' => $v['synonym'],
-            '@term' => $v['name'],
-            '@field_name' => drupal_strtolower($instance['label']),
-          ));
         }
       }
     }
-    $prefix = empty($tags_typed) ? '' : drupal_implode_tags($tags_typed) . ', ';
-
     if (count($tags_return) > $max_suggestions) {
       $tags_return = array_slice($tags_return, 0, $max_suggestions);
     }
+  }
+  $prefix = empty($tags_typed) ? '' : drupal_implode_tags($tags_typed) . ', ';
+  drupal_json_output(synonyms_autocomplete_format($tags_return, $prefix));
+}
+
+/**
+ * Page callback: Outputs JSON for entity autocomplete suggestions.
+ *
+ * This callback outputs entity name suggestions in response to Ajax requests
+ * made by the synonyms autocomplete widget for entity reference fields. The
+ * output is a JSON object of plain-text entity suggestions, keyed by the
+ * user-entered value with the completed entity name appended. Entity names
+ * containing commas are wrapped in quotes. The search is made with
+ * consideration of synonyms.
+ *
+ * @param string $field_name
+ *   The name of the entity reference field.
+ * @param string $entity_type
+ *   Entity type to which the supplied $field_name is attached to
+ * @param string $bundle
+ *   Bundle name to which the supplied $field_name is attached to
+ * @param string $tags_typed
+ *   (optional) A comma-separated list of entity names entered in the
+ *   autocomplete form element. Only the last term is used for autocompletion.
+ *   Defaults to '' (an empty string).
+ */
+function synonyms_autocomplete_entity($field_name, $entity_type, $bundle, $tags_typed = '') {
+  // If the request has a '/' in the search text, then the menu system will have
+  // split it into multiple arguments, recover the intended $tags_typed.
+  $args = func_get_args();
+  // Shift off the $field_name argument.
+  array_shift($args);
+  // Shift off the $entity_type argument.
+  array_shift($args);
+  // Shift off the $bundle argument.
+  array_shift($args);
+  $tags_typed = implode('/', $args);
 
-    // Now formatting the results.
-    foreach ($tags_return as $info) {
-      $n = $info['name'];
-      // Term names containing commas or quotes must be wrapped in quotes.
-      if (strpos($info['name'], ',') !== FALSE || strpos($info['name'], '"') !== FALSE) {
-        $n = '"' . str_replace('"', '""', $info['name']) . '"';
+  if (!($field = field_info_field($field_name)) || $field['type'] != 'entityreference') {
+    print t('Entity reference field @field_name not found.', array('@field_name' => $field_name));
+    exit;
+  }
+
+  if (!($instance = field_info_instance($entity_type, $field['field_name'], $bundle))) {
+    // Error string. The JavaScript handler will realize this is not JSON and
+    // will display it as debugging information.
+    print t('There was not found an instance of @field_name in @entity_type.', array(
+      '@field_name' => $field_name,
+      '@entity_type' => $entity_type,
+    ));
+    exit;
+  }
+
+  $widget = $instance['widget']['type'] == 'synonyms_autocomplete_entity' ? $instance['widget']['settings'] : field_info_widget_settings('synonyms_autocomplete_entity');
+
+  // How many suggestions maximum we are able to output.
+  $max_suggestions = $widget['suggestion_size'];
+
+  // Whether we are allowed to suggest more than one entry per term, shall that
+  // entry be either term name itself or one of its synonyms.
+  $suggest_only_unique = $widget['suggest_only_unique'];
+
+  $tags_typed = drupal_explode_tags($tags_typed);
+  $tag_last = drupal_strtolower(array_pop($tags_typed));
+  $prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
+
+  $handler = entityreference_get_selection_handler($field, $instance, $entity_type, NULL);
+
+  $tags_typed_entity_ids = array();
+  if (!empty($tags_typed)) {
+    foreach ($handler->getReferencableEntities($tags_typed, 'IN') as $target_entity_ids) {
+      $tags_typed_entity_ids = array_merge($tags_typed_entity_ids, array_keys($target_entity_ids));
+    }
+  }
+
+  $matches = array();
+  if ($tag_last) {
+    foreach ($handler->getReferencableEntities($tag_last) as $target_entity_ids) {
+      foreach (array_diff_key($target_entity_ids, drupal_map_assoc($tags_typed_entity_ids)) as $target_id => $label) {
+        $matches[] = array(
+          'target_id' => $target_id,
+          'name' => $label,
+        );
+        if (count($matches) == $max_suggestions) {
+          break (2);
+        }
       }
-      while (isset($term_matches[$prefix . $n])) {
-        $n .= ' ';
+    }
+
+    if (count($matches) < $max_suggestions) {
+      $behavior_implementations = synonyms_behavior_get('autocomplete', $field['settings']['target_type'], synonyms_field_target_bundles($field), TRUE);
+      foreach ($behavior_implementations as $implementation) {
+        $condition = db_and();
+        $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like($tag_last) . '%', 'LIKE');
+
+        if (!empty($tags_typed_entity_ids)) {
+          $condition->condition('entity_id', $tags_typed_entity_ids, 'NOT IN');
+        }
+        if ($suggest_only_unique && !empty($matches)) {
+          $tmp = array();
+          foreach ($matches as $match) {
+            $tmp[] = $match['target_id'];
+          }
+          $condition->condition('entity_id', $tmp, 'NOT IN');
+        }
+
+        $new_target_ids = array();
+        foreach (synonyms_synonyms_find_behavior($condition, $implementation) as $synonym) {
+          if (!$suggest_only_unique || !in_array($synonym->entity_id, $new_target_ids)) {
+            $matches[] = array(
+              'target_id' => $synonym->entity_id,
+              'synonym' => $synonym->synonym,
+              'behavior_implementation' => $implementation,
+            );
+            $new_target_ids[] = $synonym->entity_id;
+            if (count($matches) == $max_suggestions) {
+              break (2);
+            }
+          }
+        }
       }
-      $term_matches[$prefix . $n] = $info['wording'];
+    }
+
+    $synonym_entities = array();
+    foreach ($matches as $match) {
+      if (!isset($match['wording']) && isset($match['synonym'])) {
+        $synonym_entities[] = $match['target_id'];
+      }
+    }
+    if (!empty($synonym_entities)) {
+      $synonym_entities = entity_load($field['settings']['target_type'], $synonym_entities);
+      foreach ($matches as $k => $match) {
+        if (!isset($match['name']) && isset($match['synonym'])) {
+          if (entity_access('view', $field['settings']['target_type'], $synonym_entities[$match['target_id']])) {
+            $matches[$k]['name'] = entity_label($field['settings']['target_type'], $synonym_entities[$match['target_id']]);
+          }
+          else {
+            unset($matches[$k]);
+          }
+        }
+      }
+      $matches = array_values($matches);
     }
   }
-  drupal_json_output($term_matches);
+
+  drupal_json_output(synonyms_autocomplete_format($matches, $prefix));
+}
+
+/**
+ * Supportive function to format autocomplete suggestions.
+ *
+ * @param array $matches
+ *   Array of matched entries. It should follow this structure:
+ *   - name: (string) String to be inserted into autocomplete textfield if user
+ *     chooses this autocomplete entry
+ *   - synonym: (string) If this entry is matched through a synonym, put that
+ *     synonym here
+ *   - behavior_implementation: (array) If this entry is matched through a
+ *     synonym, put here the behavior implementation array that provided this
+ *     match
+ * @param string $prefix
+ *   Any prefix to be appended to 'name' property of $matches array when
+ *   inserting into the autocomplete textfield. Normally it is the already
+ *   entered entries in the textfield
+ *
+ * @return array
+ *   Array of formatted autocomplete response entries ready to be returned to
+ *   the autocomplete JavaScript
+ */
+function synonyms_autocomplete_format($matches, $prefix) {
+  $output = array();
+
+  foreach ($matches as $match) {
+    $n = synonyms_autocomplete_escape($match['name']);
+    while (isset($output[$prefix . $n])) {
+      $n .= ' ';
+    }
+    $wording = check_plain($match['name']);
+    if (isset($match['synonym'])) {
+      $instance = synonyms_instance_id_load($match['behavior_implementation']['instance_id']);
+      $wording = format_string(filter_xss($match['behavior_implementation']['settings']['wording']), array(
+        '@entity' => $match['name'],
+        '@synonym' => $match['synonym'],
+        '@field_name' => drupal_strtolower($instance['label']),
+      ));
+    }
+    $output[$prefix . $n] = $wording;
+  }
+  return $output;
 }
 
 /**
@@ -238,3 +401,140 @@ function theme_synonyms_behaviors_settings($variables) {
 
   return '<div id="' . $element['#id'] . '">' . theme('table', $table) . drupal_render_children($element) . '</div>';
 }
+
+/**
+ * Page menu callback for managing Synonyms settings of entity types.
+ */
+function synonyms_settings_overview() {
+  $output = array();
+
+  $output['table'] = array(
+    '#theme' => 'table',
+    '#header' => array(t('Entity type'), t('Bundle'), t('Manage')),
+    '#rows' => array(),
+  );
+
+  foreach (entity_get_info() as $entity_type => $entity_info) {
+    if (synonyms_entity_type_load($entity_type)) {
+      foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
+        $output['table']['#rows'][] = array(
+          $entity_info['label'],
+          $bundle == $entity_type ? '' : $bundle_info['label'],
+          l(t('Edit'), 'admin/structure/synonyms/' . $entity_type . '/' . $bundle),
+        );
+      }
+    }
+  }
+
+  return $output;
+}
+
+/**
+ * Synonyms settings form for a specific entity type and bundle name.
+ *
+ * @param string $entity_type
+ *   Entity type for which to generate synonyms settings form
+ * @param string $bundle
+ *   Bundle name for which to generate synonyms settings form
+ */
+function synonyms_settings_form($form, &$form_state, $entity_type, $bundle) {
+  $form['settings'] = array(
+    '#tree' => TRUE,
+    '#theme' => 'synonyms_behaviors_settings',
+    '#id' => 'synonyms-behaviors-settings-wrapper',
+  );
+
+  $behaviors = synonyms_behaviors();
+
+  foreach ($behaviors as $behavior => $behavior_info) {
+    $form['settings'][$behavior] = array(
+      '#title' => $behavior_info['title'],
+    );
+
+    $behavior_implementations = synonyms_behavior_get($behavior, $entity_type, $bundle);
+
+    foreach ($behavior_implementations as $implementation) {
+      $instance = field_info_instance($implementation['entity_type'], $implementation['field_name'], $implementation['bundle']);
+      $form['settings'][$behavior][$implementation['instance_id']]['#title'] = $instance['label'];
+
+      if (isset($form_state['values']['settings'][$behavior][$implementation['instance_id']])) {
+        $behavior_settings = (bool) $form_state['values']['settings'][$behavior][$implementation['instance_id']]['enabled'];
+      }
+      else {
+        $behavior_settings = !is_null($implementation['settings']);
+      }
+
+      if ($behavior_settings) {
+        if (isset($form_state['values']['settings'][$behavior][$implementation['instance_id']]['settings'])) {
+          $behavior_settings = $form_state['values']['settings'][$behavior][$implementation['instance_id']]['settings'];
+        }
+        elseif ($implementation['settings']) {
+          $behavior_settings = $implementation['settings'];
+        }
+        else {
+          $behavior_settings = array();
+        }
+      }
+
+      $form['settings'][$behavior][$implementation['instance_id']]['enabled'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Enable'),
+        '#default_value' => $behavior_settings !== FALSE,
+      );
+
+      $settings_form = ctools_plugin_get_function($behavior_info, 'settings form callback');
+      if ($settings_form) {
+        $form['settings'][$behavior][$implementation['instance_id']]['enabled']['#ajax'] = array(
+          'callback' => 'synonyms_settings_form_ajax',
+          'wrapper' => $form['settings']['#id'],
+        );
+
+        if ($behavior_settings !== FALSE) {
+          $form['settings'][$behavior][$implementation['instance_id']]['settings'] = $settings_form($form, $form_state, $behavior_settings);
+        }
+      }
+    }
+  }
+
+  $form['actions'] = array(
+    '#type' => '#actions',
+  );
+
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for 'synonyms_settings_form' form.
+ *
+ * Store synonyms behavior settings.
+ */
+function synonyms_settings_form_submit($form, &$form_state) {
+  foreach ($form_state['values']['settings'] as $behavior => $settings) {
+    foreach ($settings as $instance_id => $behavior_settings) {
+      if ($behavior_settings['enabled']) {
+        synonyms_behavior_settings_save(array(
+          'instance_id' => $instance_id,
+          'behavior' => $behavior,
+          'settings' => isset($behavior_settings['settings']) ? $behavior_settings['settings'] : NULL,
+        ));
+      }
+      else {
+        synonyms_behavior_settings_delete($instance_id, $behavior);
+      }
+    }
+  }
+  drupal_set_message(t('Synonyms settings have been successfully saved.'));
+  $form_state['redirect'] = array('admin/structure/synonyms');
+}
+
+/**
+ * Ajax callback function for synonyms settings form.
+ */
+function synonyms_settings_form_ajax($form, &$form_state) {
+  return $form['settings'];
+}
diff --git a/synonyms.test b/synonyms.test
index 296929a..5fc1dc5 100644
--- a/synonyms.test
+++ b/synonyms.test
@@ -76,7 +76,7 @@ abstract class SynonymsWebTestCase extends DrupalWebTestCase {
    * SetUp method.
    */
   public function setUp($modules = array()) {
-    $modules[] = 'synonyms';
+    array_unshift($modules, 'synonyms');
     parent::setUp($modules);
 
     $this->admin = $this->drupalCreateUser(array(
@@ -140,15 +140,15 @@ abstract class SynonymsWebTestCase extends DrupalWebTestCase {
  */
 class SynonymsSynonymsWebTestCase extends SynonymsWebTestCase {
 
-  protected $behavior = 'synonyms';
+  protected $behavior = 'autocomplete';
 
   /**
    * GetInfo method.
    */
   public static function getInfo() {
     return array(
-      'name' => 'Taxonomy synonyms',
-      'description' => 'Ensure that the general "synonyms" behavior works correctly.',
+      'name' => 'Synonyms',
+      'description' => 'Ensure that the general synonyms functionality works correctly.',
       'group' => 'Synonyms',
     );
   }
@@ -235,11 +235,11 @@ class SynonymsSynonymsWebTestCase extends SynonymsWebTestCase {
     taxonomy_term_save($term);
 
     // Testing the 'synonyms' property of 'taxonomy_term' entity.
-    $synonyms = synonyms_get_sanitized($no_synonyms_term);
+    $synonyms = entity_metadata_wrapper('taxonomy_term', $no_synonyms_term)->synonyms->value();
     $this->assertTrue(empty($synonyms), 'Successfully retrieved synonyms_get_sanitized() for a term without synonyms.');
-    $synonyms = synonyms_get_sanitized($one_synonym_term);
+    $synonyms = entity_metadata_wrapper('taxonomy_term', $one_synonym_term)->synonyms->value();
     $this->assertTrue(count($synonyms) == 1 && $synonyms[0] == $synonym1, 'Successfully retrieved synonyms_get_sanitized() for a term with a single synonym.');
-    $synonyms = synonyms_get_sanitized($two_synonyms_term);
+    $synonyms = entity_metadata_wrapper('taxonomy_term', $two_synonyms_term)->synonyms->value();
     $this->assertTrue(count($synonyms) == 2 && $synonyms[0] == $synonym1 && $synonyms[1] == $synonym2, 'Successfully retrieved synonyms_get_sanitized() for a term with 2 synonyms.');
 
     // Testing the function synonyms_get_term_by_synonym().
@@ -270,18 +270,43 @@ class SynonymsSynonymsWebTestCase extends SynonymsWebTestCase {
     $tid = synonyms_add_term_by_synonym($term->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->vocabulary);
     $new_term = taxonomy_term_load($tid);
     $this->assertNotEqual($new_term->tid, $term->tid, 'Successfully called synonyms_add_term_by_synonym() on a new title and a new term was created (due to a field not being engaged in "synonyms" behavior).');
+
+    // Testing the function synonyms_get_entity_by_synonym().
+    $another_vocabulary = (object) array(
+      'name' => $this->randomName(),
+      'machine_name' => 'another_bundle',
+    );
+    taxonomy_vocabulary_save($another_vocabulary);
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', $this->randomName());
+    $this->assertEqual($entity_id, 0, 'synonyms_get_entity_by_synonym() function returns 0 when fails to look up any entity.');
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', drupal_strtoupper($term_parent->name));
+    $this->assertEqual($entity_id, $term_parent->tid, 'synonyms_get_entity_by_synonym() function returns entity ID when a name of an existing entity is supplised.');
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', drupal_strtoupper($term_parent->name), $another_vocabulary->machine_name);
+    $this->assertEqual($entity_id, 0, 'synonyms_get_entity_by_synonym() returns 0 if an existing entity name is provided, but the search is conducted within another bundle.');
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', drupal_strtolower($synonym2));
+    $this->assertEqual($entity_id, $two_synonyms_term->tid, 'synonyms_get_entity_by_synonym() returns entity ID when a synonym of that entity is supplied.');
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', drupal_strtolower($parent_synonym), $another_vocabulary->machine_name);
+    $this->assertEqual($entity_id, 0, 'synonyms_get_entity_by_synonym() returns 0 if a synonym of an existing entity is supplied, but the search is conducted within another bundle.');
+
+    $entity_id = synonyms_get_entity_by_synonym('taxonomy_term', $term_parent->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']);
+    $this->assertEqual($entity_id, 0, 'synonyms_get_entity_by_synonym() returns 0 if a non-synonym field value is supplied.');
   }
 }
 
 /**
  * Test "Synonyms friendly autocomplete" widget of Synonyms module.
  */
-class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
+abstract class AbstractAutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
 
   protected $behavior = 'autocomplete';
 
   protected $behavior_settings = array(
-    'wording' => '@synonym @field_name @term',
+    'wording' => '@synonym @field_name @entity',
   );
 
   /**
@@ -311,18 +336,15 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
    *
    * @var array
    */
-  protected $term_reference_field = array();
+  protected $reference_field = array();
 
   /**
-   * GetInfo method.
+   * Field instance definition array of the field that will be attached to
+   * $this->entity_type with synonyms friendly autocomplete widget.
+   *
+   * @var array
    */
-  public static function getInfo() {
-    return array(
-      'name' => 'Taxonomy synonyms autocomplete',
-      'description' => 'Ensure that the "synonym friendly autocomplete" widget works correctly with taxonomy terms.',
-      'group' => 'Synonyms',
-    );
-  }
+  protected $reference_instance = array();
 
   /**
    * SetUp method.
@@ -335,33 +357,6 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
       'name' => 'Synonyms Test Content',
       'type' => $this->bundle,
     ), 'Save content type');
-
-    $this->term_reference_field = array(
-      'type' => 'taxonomy_term_reference',
-      'field_name' => 'synonyms_term_enabled',
-      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->machine_name,
-            'parent' => 0,
-          ),
-        ),
-      ),
-    );
-    $this->term_reference_field = field_create_field($this->term_reference_field);
-
-    $instance = array(
-      'field_name' => $this->term_reference_field['field_name'],
-      'entity_type' => 'node',
-      'bundle' => $this->bundle,
-      'label' => 'Synonym Terms Autcomplete',
-      'widget' => array(
-        'type' => 'synonyms_autocomplete',
-      ),
-    );
-    $instance = field_create_instance($instance);
-
     drupal_static_reset();
 
     // Now creating taxonomy tree.
@@ -510,48 +505,6 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
   }
 
   /**
-   * Test auto-creation functionality.
-   *
-   * Test the auto-creation functionality of the synonym friendly autocomplete
-   * widget type. Along the way it tests whether synonyms, submitted into the
-   * widget's textfield are converted into the terms, synonyms of which they
-   * are.
-   */
-  public function testAutoCreation() {
-    // Trying enabled auto creation.
-    $this->drupalPost('admin/structure/types/manage/synonyms-test-content/fields/synonyms_term_enabled', array(
-      'instance[widget][settings][auto_creation]' => TRUE,
-    ), 'Save settings');
-
-    $new_term_name = $this->terms['no_synonyms']->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
-    $this->drupalPost('node/add/synonyms-test-content', array(
-      'title' => $this->randomName(),
-      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => $this->terms['no_synonyms']->name . ', ' . $new_term_name . ', ' . $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-    ), 'Save');
-    $this->assertText($this->terms['no_synonyms']->name, 'Existing term was assigned to the new node');
-    $this->assertText($new_term_name, 'Auto created term was assigned to the new node when Auto creation is on.');
-    $this->assertText($this->terms['one_synonym']->name, 'Submitting a synonym into autocomplete widget results in the term, to which the synonym belongs, being assigned to the just created entity (when Auto creation is on).');
-    $term = $this->getLastTerm($this->vocabulary);
-    $this->assertEqual($term->name, $new_term_name, 'The auto created term has been created when Auto creation is on.');
-
-    // Trying disabled auto creation.
-    $this->drupalPost('admin/structure/types/manage/synonyms-test-content/fields/synonyms_term_enabled', array(
-      'instance[widget][settings][auto_creation]' => FALSE,
-    ), 'Save settings');
-
-    $new_term_name = $this->terms['term1']->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
-    $this->drupalPost('node/add/synonyms-test-content', array(
-      'title' => $this->randomName(),
-      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => $this->terms['no_synonyms']->name . ', ' . $new_term_name . ', ' . $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-    ), 'Save');
-    $this->assertText($this->terms['no_synonyms']->name, 'Existing term was assigned to the new node');
-    $this->assertNoText($new_term_name, 'Auto created term was not assigned to the new node when Auto creation is off.');
-    $this->assertText($this->terms['one_synonym']->name, 'Submitting a synonym into autocomplete widget results in the term, to which the synonym belongs, being assigned to the just created entity (when Auto creation is off).');
-    $term = $this->getLastTerm($this->vocabulary);
-    $this->assertNotEqual($term->name, $new_term_name, 'The auto created term has not been created when Auto creation is off.');
-  }
-
-  /**
    * Test autocomplete menu path.
    *
    * Feed all known "buggy" input to synonym friendly autocomplete menu path,
@@ -612,6 +565,115 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
       $this->terms['one_synonym']->name => $this->synonymAutocompleteResult($this->terms['one_synonym'], $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->fields['enabled']['instance']),
       $this->terms['one_synonym']->name . ' ' => $this->synonymAutocompleteResult($this->terms['one_synonym'], $this->terms['one_synonym']->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->fields['disabled']['instance']),
     ), 'Autocomplete works correctly when more than 1 field participates in the autocomplete behavior.');
+    synonyms_behavior_settings_delete($this->fields['disabled']['instance']['id'], $this->behavior);
+
+    // Submit a name that is similar to one of our terms and is similar to a
+    // a term from another vocabulary, which should not participate in the
+    // autocomplete. We do this trick in different flavors, all with the idea
+    // to make sure the bundles that should not participate in the field values
+    // are not suggested by the autocomplete menu path. The different flavors
+    // are:
+    // - non valid term similar to valid term
+    // - non valid term similar to valid synonym
+    // - non valid synonym similar to valid term
+    // - non valid synonym similar to valid synonym
+    $another_vocabulary = (object) array(
+      'name' => $this->randomName(),
+      'machine_name' => 'another_vocabulary',
+    );
+    taxonomy_vocabulary_save($another_vocabulary);
+    $instance = field_create_instance(array(
+      'field_name' => $this->fields['enabled']['field']['field_name'],
+      'entity_type' => 'taxonomy_term',
+      'bundle' => $another_vocabulary->machine_name,
+    ));
+    $instance = field_info_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
+    synonyms_behavior_settings_save(array(
+      'instance_id' => $instance['id'],
+      'behavior' => $this->behavior,
+      'settings' => $this->behavior_settings,
+    ));
+
+    $term_similar_term = (object) array(
+      'name' => $this->terms['no_synonyms']->name,
+      'vid' => $another_vocabulary->vid,
+    );
+    taxonomy_term_save($term_similar_term);
+    $this->assertAutocompleteMenuPath($this->terms['no_synonyms']->name, array(
+      $this->terms['no_synonyms']->name => $this->terms['no_synonyms']->name,
+    ), 'Submitting term name similar to term from another bundle does not include the term from another bundle.');
+
+    $term_similar_synonym = (object) array(
+      'name' => $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'vid' => $another_vocabulary->vid,
+    );
+    taxonomy_term_save($term_similar_synonym);
+    $this->assertAutocompleteMenuPath($term_similar_synonym->name, array(
+      $this->terms['one_synonym']->name => $this->synonymAutocompleteResult($this->terms['one_synonym'], $term_similar_synonym->name, $this->fields['enabled']['instance']),
+    ), 'Submitting synonym similar to term from another bundle does not include the term from another bundle.');
+
+    $synonym_similar_term = (object) array(
+      'name' => $this->randomName(),
+      'vid' => $another_vocabulary->vid,
+      $this->fields['enabled']['field']['field_name'] => array(LANGUAGE_NONE => array(
+        $this->terms['no_synonyms']->name,
+      )),
+    );
+    taxonomy_term_save($synonym_similar_term);
+    $this->assertAutocompleteMenuPath($this->terms['no_synonyms']->name, array(
+      $this->terms['no_synonyms']->name => $this->terms['no_synonyms']->name,
+    ), 'Submitting term name similar to a synonym of a term from another bundle does not include the term from another bundle.');
+
+    $synonym_similar_synonym = (object) array(
+      'name' => $this->randomName(),
+      'vid' => $another_vocabulary->vid,
+      $this->fields['enabled']['field']['field_name'] => array(LANGUAGE_NONE => array(
+        $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      )),
+    );
+    taxonomy_term_save($synonym_similar_synonym);
+    $this->assertAutocompleteMenuPath($this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], array(
+      $this->terms['one_synonym']->name => $this->synonymAutocompleteResult($this->terms['one_synonym'], $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->fields['enabled']['instance'])
+    ), 'Submitting synonym similar to a synonym of a term from another bundle does not includde the term from another bundle.');
+  }
+
+  /**
+   * Test autocomplete text field validation.
+   *
+   * In particular, this test does the following:
+   * - test submitting a synonym into the text field (that should be converted
+   *   into its entity)
+   * - test submitting the same entity name twice (only one reference should be
+   *   saved)
+   * - test submitting entity name and one of its synonyms (only one reference
+   *   should be saved)
+   * - test submitting 2 different synonyms of the same entity (only one
+   *   reference should be saved)
+   */
+  public function testAutocompleteTextField() {
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    ), 'Save');
+    $this->assertText($this->terms['one_synonym']->name, 'Submitting a synonym into autocomplete text field results into term being saved.');
+
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => drupal_implode_tags(array($this->terms['one_synonym']->name, $this->terms['one_synonym']->name)),
+    ), 'Save');
+    $this->assertUniqueText($this->terms['one_synonym']->name, 'Submitting the same term name twice into autocomplete text field results in saving the term only once in the field.');
+
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => drupal_implode_tags(array($this->terms['one_synonym']->name, $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'])),
+    ), 'Save');
+    $this->assertUniqueText($this->terms['one_synonym']->name, 'Submitting term name and one of its synonyms results in saving the term only once in the field.');
+
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => drupal_implode_tags(array($this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'])),
+    ), 'Save');
+    $this->assertUniqueText($this->terms['two_synonyms']->name, 'Submitting 2 different synonyms of the same term results in saving the term only once in the field.');
   }
 
   /**
@@ -619,19 +681,18 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
    */
   public function testWidgetSettingsSuggestionSize() {
     $suggestion_size = 1;
-    $this->drupalPost('admin/structure/types/manage/synonyms-test-content/fields/synonyms_term_enabled', array(
-      'instance[widget][settings][suggestion_size]' => $suggestion_size,
-    ), 'Save settings');
+    $this->reference_instance['widget']['settings']['suggestion_size'] = $suggestion_size;
+    field_update_instance($this->reference_instance);
 
     // If size was bigger than 1, we'd get suggested 2 terms: 'term1' and
     // 'term1_longer_name'.
     $this->assertAutocompleteMenuPath($this->terms['term1']->name, array(
       $this->terms['term1']->name => $this->terms['term1']->name,
-    ), 'Suggestions Size option is respected in autocomplete widget for term suggestion entries.');
+    ), 'Suggestions Size option is respected in autocomplete widget for entity suggestion entries.');
 
     $this->assertAutocompleteMenuPath($this->terms['name_similar_synonym']->name, array(
       $this->terms['name_similar_synonym']->name => $this->terms['name_similar_synonym']->name,
-    ), 'Suggestions Size option is respected in autocomplete widget for term and synonym suggestion entries.');
+    ), 'Suggestions Size option is respected in autocomplete widget for entity and synonym suggestion entries.');
 
     $this->assertAutocompleteMenuPath(drupal_substr($this->terms['similar_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], 0, 8), array(
       $this->terms['similar_synonyms']->name => $this->synonymAutocompleteResult($this->terms['similar_synonyms'], $this->terms['similar_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'], $this->fields['enabled']['instance']),
@@ -639,7 +700,7 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
 
     $this->assertAutocompleteMenuPath('one_term_name_another_synonym_', array(
       $this->terms['name_another_synonym']->name => $this->terms['name_another_synonym']->name,
-    ), 'Suggestions Size option is respected in autocomplete widget for the case when there is match by term name and by synonyms; and preference is given to the match by term name.');
+    ), 'Suggestions Size option is respected in autocomplete widget for the case when there is match by entity name and by synonyms; and preference is given to the match by entity name.');
   }
 
   /**
@@ -683,7 +744,7 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
    *   Drupal assertion message to be displayed on the rest results page
    */
   protected function assertAutocompleteMenuPath($input, $standard, $message) {
-    $response = $this->drupalGet('synonyms/autocomplete/' . $this->term_reference_field['field_name']  . '/' . $this->entity_type . '/' . $this->bundle . '/' . $input);
+    $response = $this->drupalGet($this->reference_instance['widget']['settings']['synonyms_autocomplete_path'] . '/' . $this->reference_field['field_name']  . '/' . $this->entity_type . '/' . $this->bundle . '/' . $input);
     if (!$response) {
       $this->fail($message, 'Autocomplete Menu Path');
       return;
@@ -698,36 +759,169 @@ class AutocompleteSynonymsWebTestCase extends SynonymsWebTestCase {
   /**
    * Return expected autocomplete menu path result.
    *
-   * The result is prepared as if the term was found by the supplied synonym.
+   * The result is prepared as if the entity was found by the supplied synonym.
    *
-   * @param object $term
-   *   Fully loaded taxonomy term object for which the result is generated.
+   * @param object $entity
+   *   Fully loaded entity for which the result is generated.
    * @param string $synonym
-   *   Synonym by which the term was hit in the search
+   *   Synonym by which the entity was hit in the search
    * @param array $instance
    *   Instance definition array which the $synonym originates from
    *
    * @return string
    *   Formatted autocomplete result
    */
-  protected function synonymAutocompleteResult($term, $synonym, $instance) {
+  protected function synonymAutocompleteResult($entity, $synonym, $instance) {
     return format_string($this->behavior_settings['wording'], array(
       '@synonym' => $synonym,
-      '@term' => $term->name,
+      '@entity' => entity_label($this->fields['enabled']['instance']['entity_type'], $entity),
       '@field_name' => drupal_strtolower($instance['label']),
     ));
   }
 }
 
 /**
+ * Test synonyms friendly autocomplete widget for taxonomy term reference field.
+ */
+class TaxonomyTermReferenceAutocompleteSynonymsWebTestCase extends AbstractAutocompleteSynonymsWebTestCase {
+
+  /**
+   * GetInfo method.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Taxonomy synonyms autocomplete',
+      'description' => 'Ensure that the "synonym friendly autocomplete" widget works correctly with taxonomy term reference field type.',
+      'group' => 'Synonyms',
+    );
+  }
+
+  public function setUp($modules = array()) {
+    parent::setUp($modules);
+
+    $this->reference_field = array(
+      'type' => 'taxonomy_term_reference',
+      'field_name' => 'synonyms_term_enabled',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'allowed_values' => array(
+          array(
+            'vocabulary' => $this->vocabulary->machine_name,
+            'parent' => 0,
+          ),
+        ),
+      ),
+    );
+    $this->reference_field = field_create_field($this->reference_field);
+
+    $this->reference_instance = array(
+      'field_name' => $this->reference_field['field_name'],
+      'entity_type' => 'node',
+      'bundle' => $this->bundle,
+      'label' => 'Synonym Terms Autcomplete',
+      'widget' => array(
+        'type' => 'synonyms_autocomplete_taxonomy_term',
+      ),
+    );
+    $this->reference_instance['widget']['settings'] = field_info_widget_settings($this->reference_instance['widget']['type']);
+    $this->reference_instance = field_create_instance($this->reference_instance);
+  }
+
+  /**
+   * Test auto-creation functionality.
+   *
+   * Test the auto-creation functionality of the synonym friendly autocomplete
+   * widget type for taxonomy term reference field type.
+   */
+  public function testAutoCreation() {
+    // Trying enabled auto creation.
+    $this->reference_instance['widget']['settings']['auto_creation'] = TRUE;
+    field_update_instance($this->reference_instance);
+
+    $new_term_name = $this->terms['no_synonyms']->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => $this->terms['no_synonyms']->name . ', ' . $new_term_name . ', ' . $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    ), 'Save');
+    $this->assertText($this->terms['no_synonyms']->name, 'Existing term was assigned to the new node');
+    $this->assertText($new_term_name, 'Auto created term was assigned to the new node when Auto creation is on.');
+    $this->assertText($this->terms['one_synonym']->name, 'Submitting a synonym into autocomplete widget results in the term, to which the synonym belongs, being assigned to the just created entity (when Auto creation is on).');
+    $term = $this->getLastTerm($this->vocabulary);
+    $this->assertEqual($term->name, $new_term_name, 'The auto created term has been created when Auto creation is on.');
+
+    // Trying disabled auto creation.
+    $this->reference_instance['widget']['settings']['auto_creation'] = FALSE;
+    field_update_instance($this->reference_instance);
+
+    $new_term_name = $this->terms['term1']->{$this->fields['disabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $this->randomName(),
+      'synonyms_term_enabled[' . LANGUAGE_NONE . ']' => $this->terms['no_synonyms']->name . ', ' . $new_term_name . ', ' . $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    ), 'Save');
+    $this->assertText($this->terms['no_synonyms']->name, 'Existing term was assigned to the new node');
+    $this->assertNoText($new_term_name, 'Auto created term was not assigned to the new node when Auto creation is off.');
+    $this->assertText($this->terms['one_synonym']->name, 'Submitting a synonym into autocomplete widget results in the term, to which the synonym belongs, being assigned to the just created entity (when Auto creation is off).');
+    $term = $this->getLastTerm($this->vocabulary);
+    $this->assertNotEqual($term->name, $new_term_name, 'The auto created term has not been created when Auto creation is off.');
+  }
+}
+
+/**
+ * Test synonyms friendly autocomplete widget for entity reference field type.
+ */
+class EntityReferenceAutocompleteSynonymsWebTestCase extends AbstractAutocompleteSynonymsWebTestCase {
+
+  /**
+   * GetInfo method.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity reference synonyms autocomplete',
+      'description' => 'Ensure that the "synonym friendly autocomplete" widget works correctly with entityreference field type.',
+      'group' => 'Synonyms',
+    );
+  }
+
+  public function setUp($modules = array()) {
+    $modules[] = 'entityreference';
+    parent::setUp($modules);
+
+    $this->reference_field = array(
+      'type' => 'entityreference',
+      'field_name' => 'synonyms_term_enabled',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'target_type' => 'taxonomy_term',
+        'handler_settings' => array(
+          'target_bundles' => drupal_map_assoc(array($this->fields['enabled']['instance']['bundle'])),
+        ),
+      ),
+    );
+    $this->reference_field = field_create_field($this->reference_field);
+
+    $this->reference_instance = array(
+      'field_name' => $this->reference_field['field_name'],
+      'entity_type' => 'node',
+      'bundle' => $this->bundle,
+      'label' => 'Synonym Entity Autcomplete',
+      'widget' => array(
+        'type' => 'synonyms_autocomplete_entity',
+      ),
+    );
+    $this->reference_instance['widget']['settings'] = field_info_widget_settings($this->reference_instance['widget']['type']);
+    $this->reference_instance = field_create_instance($this->reference_instance);
+  }
+}
+
+/**
  * Test "Synonyms friendly select" widget of Synonyms module.
  */
-class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
+abstract class AbstractSelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
   protected $behavior = 'select';
 
   protected $behavior_settings = array(
-    'wording' => '@synonym @term @field_name',
+    'wording' => '@synonym @entity @field_name',
   );
 
   /**
@@ -738,14 +932,14 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
   protected $terms = array();
 
   /**
-   * Entity type to which a term reference field with tested widget is attached.
+   * Entity type to which a field with tested widget is attached.
    *
    * @var string
    */
   protected $entity_type = 'node';
 
   /**
-   * Bundle to which a term reference field with tested widget is attached.
+   * Bundle to which a field with tested widget is attached.
    *
    * @var string
    */
@@ -757,92 +951,577 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
    *
    * @var array
    */
-  protected $term_reference_field = array();
+  protected $reference_field = array();
+
+  /**
+   * Field instance definition array of the field that will be attached to
+   * $this->entity_type with synonyms friendly select widget.
+   *
+   * @var array
+   */
+  protected $reference_instance = array();
+
+  public function setUp($modules = array()) {
+    parent::setUp($modules);
+
+    // Creating a test content type.
+    $this->drupalPost('admin/structure/types/add', array(
+      'name' => 'Synonyms Test Content',
+      'type' => $this->bundle,
+    ), 'Save content type');
+
+    $this->terms['parent_term'] = (object) array(
+      'vid' => $this->vocabulary->vid,
+      'name' => 'Parent Term',
+      $this->fields['enabled']['field']['field_name'] => array(
+        LANGUAGE_NONE => array(
+          array('value' => 'Parent TermA' . $this->randomName()),
+          array('value' => 'Parent TermZ' . $this->randomName()),
+        ),
+      ),
+    );
+    taxonomy_term_save($this->terms['parent_term']);
+
+    $this->terms['child_term'] = (object) array(
+      'vid' => $this->vocabulary->vid,
+      'name' => 'Child Term',
+      'parent' => $this->terms['parent_term']->tid,
+      $this->fields['enabled']['field']['field_name'] => array(
+        LANGUAGE_NONE => array(
+          array('value' => 'Child TermZ' . $this->randomName()),
+          array('value' => 'Child TermA' . $this->randomName()),
+        ),
+      ),
+    );
+    taxonomy_term_save($this->terms['child_term']);
+
+    $this->terms['normal_term'] = (object) array(
+      'vid' => $this->vocabulary->vid,
+      'name' => 'Normal Term',
+      $this->fields['enabled']['field']['field_name'] => array(
+        LANGUAGE_NONE => array(
+          array('value' => 'Normal TermA' . $this->randomName()),
+          array('value' => 'Normal TermZ' . $this->randomName()),
+        ),
+      ),
+    );
+    taxonomy_term_save($this->terms['normal_term']);
+  }
+
+  /**
+   * Test sorting options of the widget.
+   */
+  abstract public function testWidgetSorting();
+
+  /**
+   * Test main functionality of the widget.
+   */
+  abstract public function testWidget();
+
+  /**
+   * Assert correctness of the synonyms-friendly select widget.
+   *
+   * @param array $options
+   *   Array of what options must be present in the select form element. It
+   *   should consist of arrays that follow such structure:
+   *   - entity: (object) Entity this option represents
+   *   - synonym: (string) If the option comes from a synonym, then include it
+   *     here
+   *   - selected: (bool) Place here TRUE if this option should be selected by
+   *     default
+   * @param string $message
+   *   Assert message that will be passed on to SimpleTest internals
+   */
+  protected function assertSynonymsSelect($options, $message = '') {
+    $multiple = $this->reference_field['cardinality'] > 1 || $this->reference_field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
+
+    $element = array(
+      '#options' => array(),
+      '#value' => $multiple ? array() : 'nothing',
+    );
+
+    if (!$multiple) {
+      $element['#options'][''] = t('- None -');
+    }
+
+    foreach ($options as $v) {
+      if (!isset($v['synonym'])) {
+        $v['synonym'] = NULL;
+      }
+      $key = $this->synonymSelectKey($v['entity'], $v['synonym']);
+      $label = entity_label($this->fields['enabled']['instance']['entity_type'], $v['entity']);
+      if ($v['synonym']) {
+        $label = format_string($this->behavior_settings['wording'], array(
+          '@synonym' => $v['synonym'],
+          '@entity'=> $label,
+          '@field_name' => $this->fields['enabled']['instance']['label'],
+        ));
+      }
+
+      if (isset($v['selected']) && $v['selected']) {
+        if ($multiple) {
+          $element['#value'][] = $key;
+        }
+        else {
+          $element['#value'] = $key;
+        }
+      }
+
+      $element['#options'][$key] = $this->synonymsSelectOptionPrefix($v['entity'], $v['synonym']) . $label;
+    }
+    $this->assertRaw('>' . form_select_options($element) . '</select>', $message, 'Synonyms friendly select');
+  }
+
+  /**
+   * Generate necessary prefix before the main wording of the label in select.
+   *
+   * It may be useful to insert some kind of hiderarchy indention, for example.
+   *
+   * @param object $entity
+   *   Fully loaded entity object whose prefix is requested in the option label
+   *   of the synonyms friendly select widget
+   * @param string $synonym
+   *   If this option comes from a synonym, that synonym will be supplied here
+   *
+   * @return string
+   *   Any suitable prefix before the main wording of the option for this
+   *   particular option
+   */
+  protected function synonymsSelectOptionPrefix($entity, $synonym = NULL) {
+    return '';
+  }
+
+  /**
+   * Form a key for the option of a synonyms friendly select.
+   *
+   * @param object $entity
+   *   Fully loaded entity for which to generate the key
+   * @param string $synonym
+   *   If the option, whose key is being generated, comes from a synonym, then
+   *   supply it here
+   *
+   * @return string
+   *   Key for the option of a synonym friendly select
+   */
+  protected function synonymSelectKey($entity, $synonym = NULL) {
+    $entity_id = entity_extract_ids($this->fields['enabled']['instance']['entity_type'], $entity);
+    $key = $entity_id[0];
+    if ($synonym) {
+      $key .= ':' . drupal_html_class($synonym);
+    }
+    return $key;
+  }
+}
+
+/**
+ * Test synonyms friendly select widget for taxonomy term reference field.
+ */
+class TaxonomyTermReferenceSelectSynonymsWebTestCase extends AbstractSelectSynonymsWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Taxonomy synonyms select',
+      'description' => 'Ensure that the "synonym friendly select" widget works correctly with taxonomy term reference field.',
+      'group' => 'Synonyms',
+    );
+  }
+
+  public function setUp($modules = array()) {
+    parent::setUp($modules);
+
+    $this->reference_field = array(
+      'type' => 'taxonomy_term_reference',
+      'field_name' => 'synonyms_term',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'allowed_values' => array(
+          array(
+            'vocabulary' => $this->vocabulary->machine_name,
+            'parent' => 0,
+          ),
+        ),
+      ),
+    );
+    $this->reference_field = field_create_field($this->reference_field);
+
+    $this->reference_instance = array(
+      'field_name' => $this->reference_field['field_name'],
+      'entity_type' => 'node',
+      'bundle' => $this->bundle,
+      'label' => 'Synonym Terms Select',
+      'widget' => array(
+        'type' => 'synonyms_select_taxonomy_term',
+      ),
+    );
+    $this->reference_instance = field_create_instance($this->reference_instance);
+  }
+
+  public function testWidgetSorting() {
+    $cardinality = array(
+      1 => 1,
+      FIELD_CARDINALITY_UNLIMITED => 'unlimited',
+    );
+    $required = array(
+      TRUE => 'required',
+      FALSE => 'not required',
+    );
+
+    foreach ($cardinality as $cardinality_k => $cardinality_v) {
+      foreach ($required as $required_k => $required_v) {
+        $this->reference_field['cardinality'] = $cardinality_k;
+        field_update_field($this->reference_field);
+
+        $this->reference_instance['required'] = $required_k;
+        $this->reference_instance['widget']['settings']['sort'] = 'weight';
+        field_update_instance($this->reference_instance);
+
+        $this->terms['parent_term']->weight = 0;
+        taxonomy_term_save($this->terms['parent_term']);
+
+        $options = array();
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $this->drupalGet('node/add/synonyms-test-content');
+        $this->assertSynonymsSelect($options, 'Synonyms select sorting by weight works for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
+
+        $this->terms['parent_term']->weight = -1000;
+        taxonomy_term_save($this->terms['parent_term']);
+        $options = array();
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $this->drupalGet('node/add/synonyms-test-content');
+        $this->assertSynonymsSelect($options, 'Synonyms select sorting by weight works after changing weights of terms for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
+
+        $this->reference_instance['widget']['settings']['sort'] = 'name';
+        field_update_instance($this->reference_instance);
+
+        $options = array();
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['normal_term'],
+          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['child_term'],
+          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+        );
+        $options[] = array(
+          'entity' => $this->terms['parent_term'],
+          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+        );
+        $this->drupalGet('node/add/synonyms-test-content');
+        $this->assertSynonymsSelect($options, 'Synonyms select sorting by name works for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
+      }
+    }
+  }
+
+  public function testWidget() {
+    $name = $this->randomName();
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $name,
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+        $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+        $this->terms['child_term']->tid,
+        $this->terms['normal_term']->tid,
+        $this->synonymSelectKey($this->terms['normal_term'], $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+      ),
+    ), 'Save');
+
+    $node = $this->drupalGetNodeByTitle($name);
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertText($this->terms['parent_term']->name, 'Term is saved when its synonym is submitted through synonyms friendly select for the unlimited cardinality.');
+    $this->assertText($this->terms['child_term']->name, 'Term is saved when it is submitted through synonyms friendly select for the unlimited cardinality.');
+    $this->assertUniqueText($this->terms['normal_term']->name, 'Term is saved only once when the term and its synonym are submitted through synonyms friendly select for the unlimited cardinality.');
+
+    $options = array();
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'selected' => TRUE,
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'selected' => TRUE,
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'selected' => TRUE,
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $this->drupalGet('node/' . $node->nid . '/edit');
+    $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with field cardinality more than 1.');
+
+    $this->reference_field['cardinality'] = 2;
+    field_update_field($this->reference_field);
+    $name = $this->randomName();
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $name,
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+        $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+        $this->terms['child_term']->tid,
+        $this->terms['normal_term']->tid,
+      ),
+    ), 'Save');
+    $this->assertText('this field cannot hold more than 2 values.', 'Submitting 3 entries into a field with cardinality of 2, that refer to 3 terms, results in a form error.');
+
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $name,
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+        $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+        $this->terms['normal_term']->tid,
+        $this->synonymSelectKey($this->terms['normal_term'], $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+      ),
+    ), 'Save');
+    $node = $this->drupalGetNodeByTitle($name);
+    $this->drupalGet('node/' .  $node->nid);
+    $this->assertUniqueText($this->terms['parent_term']->name, 'Submitting 3 entries into a field with cardinality of 2, that refer to only 2 terms, results in form getting submitted. Term #1 is saved.');
+    $this->assertUniqueText($this->terms['normal_term']->name, 'Term #2 is saved.');
+
+    $this->reference_field['cardinality'] = 1;
+    field_update_field($this->reference_field);
+    $name = $this->randomName();
+    $this->drupalPost('node/add/synonyms-test-content', array(
+      'title' => $name,
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+    ), 'Save');
+    $node = $this->drupalGetNodeByTitle($name);
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertText($this->terms['parent_term']->name, 'Term is saved when its synonym is submitted through synonyms friendly select for the cardinality of 1.');
+
+    $options = array();
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'selected' => TRUE,
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $this->drupalGet('node/' .  $node->nid . '/edit');
+    $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
+
+    $this->drupalPost('node/' . $node->nid . '/edit', array(
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->terms['child_term']->tid,
+    ), 'Save');
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertNoText($this->terms['parent_term']->name, 'After updating entity the old term is removed.');
+    $this->assertText($this->terms['child_term']->name, 'Term is saved when it is submitted through synonyms friendly select for the cardinality of 1.');
+
+    $options = array();
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'selected' => TRUE,
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+    );
+    $options[] = array(
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+    );
+    $this->drupalGet('node/' .  $node->nid . '/edit');
+    $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
+  }
+
+  protected function synonymsSelectOptionPrefix($entity, $synonym = NULL) {
+    $depth = count(taxonomy_get_parents_all($entity->tid)) - 1;
+    return str_repeat('-', $depth) . parent::synonymsSelectOptionPrefix($entity, $synonym);
+  }
+}
+
+/**
+ * Test synonyms friendly select widget for entity reference field type.
+ */
+class EntityReferenceSelectSynonymsWebTestCase extends AbstractSelectSynonymsWebTestCase {
 
   public static function getInfo() {
     return array(
-      'name' => 'Synonyms friendly select',
-      'description' => 'Ensure that the "synonym friendly select" widget works correctly with taxonomy terms.',
+      'name' => 'Entity reference synonyms select',
+      'description' => 'Ensure that the "synonym friendly select" widget works correctly with entity reference field.',
       'group' => 'Synonyms',
     );
   }
 
   public function setUp($modules = array()) {
+    $modules[] = 'entityreference';
     parent::setUp($modules);
 
-    // Creating a test content type.
-    $this->drupalPost('admin/structure/types/add', array(
-      'name' => 'Synonyms Test Content',
-      'type' => $this->bundle,
-    ), 'Save content type');
-
-    $this->term_reference_field = array(
-      'type' => 'taxonomy_term_reference',
+    $this->reference_field = array(
+      'type' => 'entityreference',
       'field_name' => 'synonyms_term',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
       'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->machine_name,
-            'parent' => 0,
-          ),
-        ),
+        'target_type' => 'taxonomy_term',
+        'handler_settings' => array(),
       ),
     );
-    $this->term_reference_field = field_create_field($this->term_reference_field);
+    $this->reference_field = field_create_field($this->reference_field);
 
-    $instance = array(
-      'field_name' => $this->term_reference_field['field_name'],
+    $this->reference_instance = array(
+      'field_name' => $this->reference_field['field_name'],
       'entity_type' => 'node',
       'bundle' => $this->bundle,
       'label' => 'Synonym Terms Select',
       'widget' => array(
-        'type' => 'synonyms_select',
-      ),
-    );
-    $instance = field_create_instance($instance);
-
-    $this->terms['parent_term'] = (object) array(
-      'vid' => $this->vocabulary->vid,
-      'name' => 'Parent Term',
-      $this->fields['enabled']['field']['field_name'] => array(
-        LANGUAGE_NONE => array(
-          array('value' => 'Parent TermA' . $this->randomName()),
-          array('value' => 'Parent TermZ' . $this->randomName()),
-        ),
-      ),
-    );
-    taxonomy_term_save($this->terms['parent_term']);
-
-    $this->terms['child_term'] = (object) array(
-      'vid' => $this->vocabulary->vid,
-      'name' => 'Child Term',
-      'parent' => $this->terms['parent_term']->tid,
-      $this->fields['enabled']['field']['field_name'] => array(
-        LANGUAGE_NONE => array(
-          array('value' => 'Child TermZ' . $this->randomName()),
-          array('value' => 'Child TermA' . $this->randomName()),
-        ),
-      ),
-    );
-    taxonomy_term_save($this->terms['child_term']);
-
-    $this->terms['normal_term'] = (object) array(
-      'vid' => $this->vocabulary->vid,
-      'name' => 'Normal Term',
-      $this->fields['enabled']['field']['field_name'] => array(
-        LANGUAGE_NONE => array(
-          array('value' => 'Normal TermA' . $this->randomName()),
-          array('value' => 'Normal TermZ' . $this->randomName()),
-        ),
+        'type' => 'synonyms_select_entity',
       ),
     );
-    taxonomy_term_save($this->terms['normal_term']);
+    $this->reference_instance = field_create_instance($this->reference_instance);
   }
 
-  /**
-   * Test sorting options of the widget.
-   */
   public function testWidgetSorting() {
     $cardinality = array(
       1 => 1,
@@ -855,129 +1534,44 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
     foreach ($cardinality as $cardinality_k => $cardinality_v) {
       foreach ($required as $required_k => $required_v) {
-        $this->term_reference_field['cardinality'] = $cardinality_k;
-        field_update_field($this->term_reference_field);
-
-        $instance = field_info_instance($this->entity_type, $this->term_reference_field['field_name'], $this->bundle);
-        $instance['required'] = $required_k;
-        $instance['widget']['settings']['sort'] = 'weight';
-        field_update_instance($instance);
+        $this->reference_field['cardinality'] = $cardinality_k;
+        field_update_field($this->reference_field);
 
-        $this->terms['parent_term']->weight = 0;
-        taxonomy_term_save($this->terms['parent_term']);
+        $this->reference_instance['required'] = $required_k;
+        field_update_instance($this->reference_instance);
 
         $options = array();
         $options[] = array(
-          'term' => $this->terms['normal_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
-          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
-          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
-          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+          'entity' => $this->terms['child_term'],
         );
         $options[] = array(
-          'term' => $this->terms['child_term'],
+          'entity' => $this->terms['child_term'],
           'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
         );
-        $this->drupalGet('node/add/synonyms-test-content');
-        $this->assertSynonymsSelect($options, 'Synonyms select sorting by weight works for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
-
-        $this->terms['parent_term']->weight = -1000;
-        taxonomy_term_save($this->terms['parent_term']);
-        $options = array();
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-        );
         $options[] = array(
-          'term' => $this->terms['parent_term'],
-          'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
+          'entity' => $this->terms['child_term'],
           'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
         );
         $options[] = array(
-          'term' => $this->terms['child_term'],
-          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
+          'entity' => $this->terms['normal_term'],
         );
         $options[] = array(
-          'term' => $this->terms['normal_term'],
+          'entity' => $this->terms['normal_term'],
           'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
         );
         $options[] = array(
-          'term' => $this->terms['normal_term'],
+          'entity' => $this->terms['normal_term'],
           'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
         );
-        $this->drupalGet('node/add/synonyms-test-content');
-        $this->assertSynonymsSelect($options, 'Synonyms select sorting by weight works after changing weights of terms for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
-
-        $instance = field_info_instance($this->entity_type, $this->term_reference_field['field_name'], $this->bundle);
-        $instance['widget']['settings']['sort'] = 'name';
-        field_update_instance($instance);
-
-        $options = array();
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
-          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['normal_term'],
-          'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
-        $options[] = array(
-          'term' => $this->terms['parent_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
-        );
-        $options[] = array(
-          'term' => $this->terms['child_term'],
-          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
-        );
         $options[] = array(
-          'term' => $this->terms['child_term'],
-          'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+          'entity' => $this->terms['parent_term'],
         );
         $options[] = array(
-          'term' => $this->terms['parent_term'],
+          'entity' => $this->terms['parent_term'],
           'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
         );
         $options[] = array(
-          'term' => $this->terms['parent_term'],
+          'entity' => $this->terms['parent_term'],
           'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
         );
         $this->drupalGet('node/add/synonyms-test-content');
@@ -986,14 +1580,11 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
     }
   }
 
-  /**
-   * Test main functionality of the widget.
-   */
   public function testWidget() {
     $name = $this->randomName();
     $this->drupalPost('node/add/synonyms-test-content', array(
       'title' => $name,
-      $this->term_reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
         $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
         $this->terms['child_term']->tid,
         $this->terms['normal_term']->tid,
@@ -1009,50 +1600,50 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
     $options = array();
     $options[] = array(
-      'term' => $this->terms['normal_term'],
+      'entity' => $this->terms['child_term'],
       'selected' => TRUE,
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
+      'entity' => $this->terms['normal_term'],
       'selected' => TRUE,
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
+      'entity' => $this->terms['parent_term'],
       'selected' => TRUE,
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $this->drupalGet('node/' . $node->nid . '/edit');
     $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with field cardinality more than 1.');
 
-    $this->term_reference_field['cardinality'] = 2;
-    field_update_field($this->term_reference_field);
+    $this->reference_field['cardinality'] = 2;
+    field_update_field($this->reference_field);
     $name = $this->randomName();
     $this->drupalPost('node/add/synonyms-test-content', array(
       'title' => $name,
-      $this->term_reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
         $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
         $this->terms['child_term']->tid,
         $this->terms['normal_term']->tid,
@@ -1062,7 +1653,7 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
     $this->drupalPost('node/add/synonyms-test-content', array(
       'title' => $name,
-      $this->term_reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
         $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
         $this->terms['normal_term']->tid,
         $this->synonymSelectKey($this->terms['normal_term'], $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
@@ -1073,12 +1664,12 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
     $this->assertUniqueText($this->terms['parent_term']->name, 'Submitting 3 entries into a field with cardinality of 2, that refer to only 2 terms, results in form getting submitted. Term #1 is saved.');
     $this->assertUniqueText($this->terms['normal_term']->name, 'Term #2 is saved.');
 
-    $this->term_reference_field['cardinality'] = 1;
-    field_update_field($this->term_reference_field);
+    $this->reference_field['cardinality'] = 1;
+    field_update_field($this->reference_field);
     $name = $this->randomName();
     $this->drupalPost('node/add/synonyms-test-content', array(
       'title' => $name,
-      $this->term_reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->synonymSelectKey($this->terms['parent_term'], $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
     ), 'Save');
     $node = $this->drupalGetNodeByTitle($name);
     $this->drupalGet('node/' . $node->nid);
@@ -1086,44 +1677,44 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
     $options = array();
     $options[] = array(
-      'term' => $this->terms['normal_term'],
+      'entity' => $this->terms['child_term'],
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'selected' => TRUE,
+      'entity' => $this->terms['normal_term'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
+      'entity' => $this->terms['parent_term'],
+      'selected' => TRUE,
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $this->drupalGet('node/' .  $node->nid . '/edit');
     $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
 
     $this->drupalPost('node/' . $node->nid . '/edit', array(
-      $this->term_reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->terms['child_term']->tid,
+      $this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->terms['child_term']->tid,
     ), 'Save');
     $this->drupalGet('node/' . $node->nid);
     $this->assertNoText($this->terms['parent_term']->name, 'After updating entity the old term is removed.');
@@ -1131,115 +1722,42 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
 
     $options = array();
     $options[] = array(
-      'term' => $this->terms['normal_term'],
+      'entity' => $this->terms['child_term'],
+      'selected' => TRUE,
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['normal_term'],
-      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['child_term'],
+      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
+      'entity' => $this->terms['normal_term'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['parent_term'],
-      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['normal_term'],
+      'synonym' => $this->terms['normal_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'selected' => TRUE,
+      'entity' => $this->terms['parent_term'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
     );
     $options[] = array(
-      'term' => $this->terms['child_term'],
-      'synonym' => $this->terms['child_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
+      'entity' => $this->terms['parent_term'],
+      'synonym' => $this->terms['parent_term']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
     );
     $this->drupalGet('node/' .  $node->nid . '/edit');
     $this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
   }
-
-  /**
-   * Assert correctness of the synonyms-friendly select widget.
-   *
-   * @param array $options
-   *   Array of what options must be present in the select form element. It
-   *   should consist of arrays that follow such structure:
-   *   - term: (object) Term object this option represents
-   *   - synonym: (string) If the option comes from a term, then include it here
-   *   - selected: (bool) Place here TRUE if this option should be selected by
-   *     default
-   * @param string $message
-   *   Assert message that will be passed on to SimpleTest internals
-   */
-  protected function assertSynonymsSelect($options, $message = '') {
-    $instance = field_info_instance($this->entity_type, $this->term_reference_field['field_name'], $this->bundle);
-    $multiple = $this->term_reference_field['cardinality'] > 1 || $this->term_reference_field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
-    $required = $instance['required'];
-
-    $element = array(
-      '#options' => array(),
-      '#value' => $multiple ? array() : 'nothing',
-    );
-
-    if (!$multiple && !$required) {
-      $element['#options'][''] = t('- None -');
-    }
-
-    foreach ($options as $v) {
-      $key = $this->synonymSelectKey($v['term'], isset($v['synonym']) ? $v['synonym'] : NULL);
-      $label = $v['term']->name;
-      if (isset($v['synonym'])) {
-        $label = format_string($this->behavior_settings['wording'], array(
-          '@synonym' => $v['synonym'],
-          '@term'=> $v['term']->name,
-          '@field_name' => $this->fields['enabled']['instance']['label'],
-        ));
-      }
-
-      if (isset($v['selected']) && $v['selected']) {
-        if ($multiple) {
-          $element['#value'][] = $key;
-        }
-        else {
-          $element['#value'] = $key;
-        }
-      }
-
-      $depth = count(taxonomy_get_parents_all($v['term']->tid)) - 1;
-      $element['#options'][$key] = str_repeat('-', $depth) . $label;
-    }
-    $this->assertRaw('>' . form_select_options($element) . '</select>', $message, 'Synonyms friendly select');
-  }
-
-  /**
-   * Form a key for the option of a synonyms friendly select.
-   *
-   * @param object $term
-   *   Fully loaded taxonomy term for which to generate the key
-   * @param string $synonym
-   *   If the option, whose key is being generated, comes from a synonym, then
-   *   supply it here
-   *
-   * @return string
-   *   Key for the option of a synonym friendly select
-   */
-  protected function synonymSelectKey($term, $synonym = NULL) {
-    $key = $term->tid;
-    if ($synonym) {
-      $key .= ':' . drupal_html_class($synonym);
-    }
-    return $key;
-  }
 }
 
 /**
@@ -1247,7 +1765,7 @@ class SelectSynonymsWebTestCase extends SynonymsWebTestCase {
  */
 abstract class AbstractSynonymsBehaviorWebTestCase extends SynonymsWebTestCase {
 
-  protected $behavior = 'synonyms';
+  protected $behavior = 'autocomplete';
 
   /**
    * Test synonymsExtract() method.
@@ -1261,7 +1779,7 @@ abstract class AbstractSynonymsBehaviorWebTestCase extends SynonymsWebTestCase {
    *   SimpleTest assertion method
    */
   protected function assertSynonymsExtract($items, $standard, $message = '') {
-    $behavior_implementation = synonyms_behavior_implementation_class('synonyms', $this->fields['enabled']['field']);
+    $behavior_implementation = synonyms_behavior_implementation_class($this->behavior, $this->fields['enabled']['field']);
     $behavior_implementation = new $behavior_implementation();
 
     $term = (object) array(
@@ -1294,7 +1812,7 @@ abstract class AbstractSynonymsBehaviorWebTestCase extends SynonymsWebTestCase {
    *   SimpleTest assertion method
    */
   protected function assertMergeEntityAsSynonym($items, $synonym_entity, $synonym_entity_type, $standard, $message = '') {
-    $behavior_implementation = synonyms_behavior_implementation_class('synonyms', $this->fields['enabled']['field']);
+    $behavior_implementation = synonyms_behavior_implementation_class($this->behavior, $this->fields['enabled']['field']);
     $behavior_implementation = new $behavior_implementation();
 
     $message = get_class($behavior_implementation) . '::mergeEntityAsSynonym() passed: ' . $message;
@@ -1332,7 +1850,7 @@ abstract class AbstractSynonymsBehaviorWebTestCase extends SynonymsWebTestCase {
    *   SimpleTest assertion method
    */
   protected function assertSynonymsFind($meta_data, QueryConditionInterface $condition, $message = '') {
-    $behavior_implementation = synonyms_behavior_implementation_class('synonyms', $this->fields['enabled']['field']);
+    $behavior_implementation = synonyms_behavior_implementation_class($this->behavior, $this->fields['enabled']['field']);
     $behavior_implementation = new $behavior_implementation();
 
     $message = get_class($behavior_implementation) . '::synonymsFind() pass: ' . $message;
@@ -1424,14 +1942,14 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
     $this->assertMergeEntityAsSynonym(array(), $node, 'node', array(array('value' => $node->title)), 'on a node entity.');
 
     // Testing synonymFind() method.
-    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field.');
+    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field.');
 
     $meta_data = array();
     $meta_data[] = array(
       'items' => array(),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values.');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values.');
 
     $meta_data = array();
     $meta_data[] = array(
@@ -1442,7 +1960,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value, but when searching for another string.');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value, but when searching for another string.');
 
     $meta_data = array();
     $synonym = $this->randomName();
@@ -1454,7 +1972,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on a field with a single value searching for that string');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on a field with a single value searching for that string');
 
     $meta_data = array();
     $synonym = $this->randomName();
@@ -1467,7 +1985,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on a field with 2 values searching for one of those 2 values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on a field with 2 values searching for one of those 2 values');
 
     $meta_data = array();
     $synonym = $this->randomName();
@@ -1489,7 +2007,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on 2 fields with 2 values each searching for one of those values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym), 'on 2 fields with 2 values each searching for one of those values');
 
     $meta_data = array();
     $synonym = $this->randomName();
@@ -1501,7 +2019,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym, 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym, 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
 
     $meta_data = array();
     $tag = $this->randomName();
@@ -1516,7 +2034,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym1, $synonym2),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
 
     $meta_data = array();
     $synonym1 = $this->randomName();
@@ -1530,7 +2048,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym1, $synonym2),
     );
-    $this->assertSynonymsFind($meta_data, db_or()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym1)->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym2), 'on a field with 2 values searching for value1 or value2');
+    $this->assertSynonymsFind($meta_data, db_or()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym1)->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym2), 'on a field with 2 values searching for value1 or value2');
 
     $meta_data = array();
     $synonym = $this->randomName();
@@ -1543,7 +2061,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       ),
       'found_synonyms' => array($synonym),
     );
-    $this->assertSynonymsFind($meta_data, db_and(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym)->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, db_like(drupal_substr($synonym, 0, -1)) . '%', 'LIKE'), 'on a field with 2 values searching for value1 and LIKE value1%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym)->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, db_like(drupal_substr($synonym, 0, -1)) . '%', 'LIKE'), 'on a field with 2 values searching for value1 and LIKE value1%');
 
     $meta_data = array();
     $synonym1 = $this->randomName();
@@ -1558,8 +2076,8 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       'found_synonyms' => array($synonym1, $synonym2),
     );
     $condition = db_or();
-    $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym1);
-    $condition->condition(db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym2)->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, db_like(drupal_substr($synonym2, 0, -1)) . '%', 'LIKE'));
+    $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym1);
+    $condition->condition(db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym2)->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, db_like(drupal_substr($synonym2, 0, -1)) . '%', 'LIKE'));
     $this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for (value1 or (value2 AND value2%))');
 
     $meta_data = array();
@@ -1575,7 +2093,7 @@ class TextSynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTestCas
       'found_synonyms' => array($synonym1, $synonym2),
     );
     $condition = db_and()
-      ->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
+      ->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
         ':synonym' => $synonym2,
       ));
     $this->assertSynonymsFind($meta_data, $condition, "on a field with 2 values, where 2nd value replaces spaces with dashes in the 1st value, searching for REPLACE(column, ' ', '-') = value2");
@@ -1654,14 +2172,14 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
     $this->assertMergeEntityAsSynonym(array(), $synonym_term, 'taxonomy_term', array(array('tid' => $synonym_term->tid)), 'on a term from referenced vocabulary.');
 
     // Testing synonymFind() method.
-    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field');
+    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field');
 
     $meta_data = array();
     $meta_data[] = array(
       'items' => array(),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values');
 
     $meta_data = array();
     $meta_data[] = array(
@@ -1672,7 +2190,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value but searching for another string');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value but searching for another string');
 
     $meta_data = array();
     $synonym_term = $this->createSynonymTerm();
@@ -1684,7 +2202,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term->name),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on a field with a single value searching for that string');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on a field with a single value searching for that string');
 
     $meta_data = array();
     $synonym_term = $this->createSynonymTerm();
@@ -1697,7 +2215,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term->name),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on a field with 2 values searching for one of those 2 values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on a field with 2 values searching for one of those 2 values');
 
     $meta_data = array();
     $synonym_term = $this->createSynonymTerm();
@@ -1719,7 +2237,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on 2 fields with 2 values each searching for one of those values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name), 'on 2 fields with 2 values each searching for one of those values');
 
     $meta_data = array();
     $synonym_term = $this->createSynonymTerm();
@@ -1731,7 +2249,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term->name),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term->name, 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term->name, 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
 
     $meta_data = array();
     $tag = $this->randomName();
@@ -1746,7 +2264,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term1->name, $synonym_term2->name),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
 
     $meta_data = array();
     $synonym_term1 = $this->createSynonymTerm();
@@ -1760,7 +2278,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term1->name, $synonym_term2->name),
     );
-    $this->assertSynonymsFind($meta_data, db_or()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term1->name)->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term2->name), 'on a field with 2 values searching for value1 or value2');
+    $this->assertSynonymsFind($meta_data, db_or()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term1->name)->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term2->name), 'on a field with 2 values searching for value1 or value2');
 
     $meta_data = array();
     $synonym_term = $this->createSynonymTerm();
@@ -1773,7 +2291,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       ),
       'found_synonyms' => array($synonym_term->name),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name)->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term->name, 1, -1)) . '%', 'LIKE'), 'on a field with 2 values searching for value1 and LIKE value1%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term->name)->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term->name, 1, -1)) . '%', 'LIKE'), 'on a field with 2 values searching for value1 and LIKE value1%');
 
     $meta_data = array();
     $synonym_term1 = $this->createSynonymTerm();
@@ -1788,10 +2306,10 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       'found_synonyms' => array($synonym_term1->name, $synonym_term2->name),
     );
     $condition = db_or();
-    $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term1->name);
+    $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term1->name);
     $condition->condition(db_and()
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term2->name)
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term2->name, 1 -1)) . '%', 'LIKE'));
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $synonym_term2->name)
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr($synonym_term2->name, 1 -1)) . '%', 'LIKE'));
     $this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for (value1 or (value2 AND value2%))');
 
     $meta_data =  array();
@@ -1807,7 +2325,7 @@ class TaxonomySynonymsBehaviorWebTestCase extends AbstractSynonymsBehaviorWebTes
       'found_synonyms' => array($synonym_term1->name, $synonym_term2->name),
     );
     $condition = db_and()
-      ->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
+      ->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
         ':synonym' => $synonym_term2->name,
       ));
     $this->assertSynonymsFind($meta_data, $condition, "on a field with 2 values, where 2nd value replaces spaces with dashes in the 1st value, searching for REPLACE(column, ' ', '-') = value2");
@@ -1901,14 +2419,14 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
     $this->assertMergeEntityAsSynonym(array(), $node, 'node', array(array('target_id' => $node->nid)), 'on a node.');
 
     // Testing synonymFind() method.
-    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field');
+    $this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on empty field');
 
     $meta_data = array();
     $meta_data[] = array(
       'items' => array(),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field without values');
 
     $meta_data = array();
     $meta_data[] = array(
@@ -1919,7 +2437,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value but searching for another string');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $this->randomName()), 'on a field with a value but searching for another string');
 
     $meta_data = array();
     $synonym_entity = $this->createNode();
@@ -1931,7 +2449,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
       'found_synonyms' => array(entity_label('node', $synonym_entity)),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on a field with a single value searching for that string');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on a field with a single value searching for that string');
 
     $meta_data = array();
     $synonym_entity = $this->createNode();
@@ -1944,7 +2462,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
       'found_synonyms' => array(entity_label('node', $synonym_entity)),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on a field with 2 values searching for one of those 2 values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on a field with 2 values searching for one of those 2 values');
 
     $meta_data = array();
     $synonym_entity = $this->createNode();
@@ -1966,7 +2484,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
       'found_synonyms' => array(),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on 2 fields with 2 values each searching for one of those values');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity)), 'on 2 fields with 2 values each searching for one of those values');
 
     $meta_data = array();
     $synonym_entity = $this->createNode();
@@ -1978,7 +2496,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
       'found_synonyms' => array(entity_label('node', $synonym_entity)),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity), 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity), 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
 
     $meta_data = array();
     $tag = $this->randomName();
@@ -1996,7 +2514,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
         entity_label('node', $synonym_entity2),
       ),
     );
-    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
+    $this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
 
     $meta_data = array();
     $synonym_entity1 = $this->createNode();
@@ -2014,8 +2532,8 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
     );
     $condition = db_or()
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity1))
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity2));
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity1))
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity2));
     $this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for value1 or value2');
 
     $meta_data = array();
@@ -2030,8 +2548,8 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       'found_synonyms' => array(entity_label('node', $synonym_entity)),
     );
     $condition = db_and()
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity))
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity), 1, -1)) . '%', 'LIKE');
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity))
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity), 1, -1)) . '%', 'LIKE');
     $this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for value1 and LIKE value1%');
 
     $meta_data = array();
@@ -2050,8 +2568,8 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
     );
     $condition = db_or()
-      ->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity1))
-      ->condition(db_and()->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity2))->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity2), 1, -1)) . '%', 'LIKE'));
+      ->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity1))
+      ->condition(db_and()->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, entity_label('node', $synonym_entity2))->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('node', $synonym_entity2), 1, -1)) . '%', 'LIKE'));
     $this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for (value1 or (value2 AND value2%))');
 
     $meta_data = array();
@@ -2070,7 +2588,7 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
       ),
     );
     $condition = db_and()
-      ->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
+      ->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :synonym", array(
         ':synonym' => entity_label('node', $synonym_entity2),
       ));
     $this->assertSynonymsFind($meta_data, $condition, "on a field with 2 values, where 2nd value replaces spaces with dashes in the 1st value, searching for REPLACE(column, ' ', '-') = value2");
@@ -2101,3 +2619,80 @@ class EntityReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsBehavio
     return $entity;
   }
 }
+
+/**
+ * Test 'term_synonyms' cTools pargument plugin implementation.
+ */
+class TaxonomyTermArgumentSynonymsWebTestCase extends SynonymsWebTestCase {
+
+  protected $behavior = 'autocomplete';
+
+  protected $behavior_settings = array(
+    'wording' => '@synonym',
+  );
+
+  /**
+   * GetInfo method.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Term synonyms cTools argument plugin',
+      'description' => 'Ensure that synonyms friendly taxonomy terms cTools argument plugin works correctly.',
+      'group' => 'Synonyms',
+    );
+  }
+
+  /**
+   * Test the term synonym argument.
+   */
+  public function testTermSynonymArgument() {
+    $term = (object) array(
+      'name' => 'Term name',
+      'vid' => $this->vocabulary->vid,
+      $this->fields['enabled']['field']['field_name'] => array(LANGUAGE_NONE => array(
+        array('value' => 'Synonym of term'),
+      )),
+    );
+    taxonomy_term_save($term);
+
+    ctools_include('context');
+
+    $argument = array(
+      'name' => 'term_synonyms',
+      'vids' => array(),
+      'transform' => FALSE,
+      'identifier' => 'Just Testing',
+      'keyword' => 'term',
+      'id' => 0,
+    );
+
+    $result = ctools_context_get_context_from_argument($argument, $this->randomName());
+    $this->assertNull($result, 'Term synonym does not look up anything when random string is supplied.');
+
+    $result = ctools_context_get_context_from_argument($argument, drupal_strtolower($term->name));
+    $this->assertEqual($result->data->tid, $term->tid, 'Term synonym argument correctly looks up the term by its name.');
+
+    $result = ctools_context_get_context_from_argument($argument, drupal_strtolower($term->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']));
+    $this->assertEqual($result->data->tid, $term->tid, 'Term synonym argument correctly looks up the term by its synonym.');
+
+    $argument['transform'] = TRUE;
+    $result = ctools_context_get_context_from_argument($argument, str_replace(' ', '-', $term->name));
+    $this->assertEqual($result->data->tid, $term->tid, 'Term synonym argument correctly looks up the term by its name, if the spaces are repaced with dashes.');
+
+    $result = ctools_context_get_context_from_argument($argument, str_replace(' ', '-', $term->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']));
+    $this->assertEqual($result->data->tid, $term->tid, 'Term synonym argument correctly looks up the term by its synonym, if the spaces are repaced with dashes.');
+
+    $argument['transform'] = FALSE;
+    $another_vocabulary = (object) array(
+      'name' => $this->randomName(),
+      'machine_name' => 'another_vocabulary',
+    );
+    taxonomy_vocabulary_save($another_vocabulary);
+    $argument['vids'][$another_vocabulary->vid] = $another_vocabulary->vid;
+    $result = ctools_context_get_context_from_argument($argument, drupal_strtolower($term->name));
+    $this->assertNull($result, 'Term synonym argument does not look up anything when term name is supplied, but the search is limited to another vocabulary.');
+
+    $result = ctools_context_get_context_from_argument($argument, drupal_strtolower($term->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']));
+    $this->assertNull($result, 'Term synonym argument does not look up anything when term synonym is supplied, but the search is limited to another vocabulary.');
+  }
+}
diff --git a/synonyms_search/includes/SearchSynonymsBehavior.interface.inc b/synonyms_search/includes/SearchSynonymsBehavior.interface.inc
index 63935dd..a30ff60 100644
--- a/synonyms_search/includes/SearchSynonymsBehavior.interface.inc
+++ b/synonyms_search/includes/SearchSynonymsBehavior.interface.inc
@@ -9,6 +9,6 @@
 /**
  * Interface of search integration synonyms behavior.
  */
-interface SearchSynonymsBehavior extends SynonymsSynonymsBehavior {
+interface SearchSynonymsBehavior extends SynonymsBehavior {
 }
 
diff --git a/synonyms_search/plugins/behavior/search.inc b/synonyms_search/plugins/behavior/search.inc
index 83b2e66..e53864f 100644
--- a/synonyms_search/plugins/behavior/search.inc
+++ b/synonyms_search/plugins/behavior/search.inc
@@ -20,8 +20,10 @@ $plugin = array(
  * where the change has taken place.
  */
 function synonyms_search_behavior_search_enabled($behavior_definition, $settings, $instance) {
-  module_load_include('inc', 'synonyms_search', 'synonyms_search.pages');
-  synonyms_search_reindex_nodes_by_vocabulary(taxonomy_vocabulary_machine_name_load($instance['bundle']));
+  if ($instance['entity_type'] == 'taxonomy_term') {
+    module_load_include('inc', 'synonyms_search', 'synonyms_search.pages');
+    synonyms_search_reindex_nodes_by_vocabulary(taxonomy_vocabulary_machine_name_load($instance['bundle']));
+  }
 }
 
 /**
@@ -31,6 +33,8 @@ function synonyms_search_behavior_search_enabled($behavior_definition, $settings
  * where the change has taken place.
  */
 function synonyms_search_behavior_search_disabled($behavior_definition, $behavior_implementation, $instance) {
-  module_load_include('inc', 'synonyms_search', 'synonyms_search.pages');
-  synonyms_search_reindex_nodes_by_vocabulary(taxonomy_vocabulary_machine_name_load($instance['bundle']));
+  if ($instance['entity_type'] == 'taxonomy_term') {
+    module_load_include('inc', 'synonyms_search', 'synonyms_search.pages');
+    synonyms_search_reindex_nodes_by_vocabulary(taxonomy_vocabulary_machine_name_load($instance['bundle']));
+  }
 }
diff --git a/synonyms_search/synonyms_search.info b/synonyms_search/synonyms_search.info
index 7e009e2..3520aef 100644
--- a/synonyms_search/synonyms_search.info
+++ b/synonyms_search/synonyms_search.info
@@ -1,9 +1,13 @@
 name = Synonyms Search
 description = "Provides synonyms integration with searching."
-package = Taxonomy
+package = Synonyms
 core = 7.x
 dependencies[] = synonyms
 dependencies[] = search
+dependencies[] = taxonomy
+
+test_dependencies[] = entityreference:entityreference
+test_dependencies[] = term_search:term_search
 
 files[] = synonyms_search.test
 
diff --git a/synonyms_search/synonyms_search.module b/synonyms_search/synonyms_search.module
index 835f276..0e7f262 100644
--- a/synonyms_search/synonyms_search.module
+++ b/synonyms_search/synonyms_search.module
@@ -51,11 +51,13 @@ function synonyms_search_taxonomy_term_update($term) {
 function synonyms_search_node_update_index($node) {
   $output = array();
   foreach (field_info_instances('node', $node->type) as $instance) {
-    // We go a field by field looking for taxonomy term reference and if that
-    // vocabulary has enabled search synonyms, we add them to the search index.
+    // We go a field by field looking for taxonomy term reference or entity
+    // reference of taxonomy term type and if that vocabulary has enabled search
+    // synonyms, we add them to the search index.
+    // TODO: implement this through foreign keys information. See
+    // term_merge_fields_with_foreign_key() function.
     $field_info = field_info_field($instance['field_name']);
     if ($field_info['type'] == 'taxonomy_term_reference') {
-      // For each term referenced in this node we have to add synonyms.
       $terms = field_get_items('node', $node, $instance['field_name']);
       if (is_array($terms) && !empty($terms)) {
         foreach ($terms as $v) {
@@ -63,6 +65,14 @@ function synonyms_search_node_update_index($node) {
         }
       }
     }
+    if ($field_info['type'] == 'entityreference' && $field_info['settings']['target_type'] == 'taxonomy_term') {
+      $terms = field_get_items('node', $node, $instance['field_name']);
+      if (is_array($terms) && !empty($terms)) {
+        foreach ($terms as $v) {
+          $output[] = $v['target_id'];
+        }
+      }
+    }
   }
 
   if (!empty($output)) {
diff --git a/synonyms_search/synonyms_search.pages.inc b/synonyms_search/synonyms_search.pages.inc
index b6876f3..3747888 100644
--- a/synonyms_search/synonyms_search.pages.inc
+++ b/synonyms_search/synonyms_search.pages.inc
@@ -21,8 +21,6 @@ function synonyms_search_reindex_nodes_by_terms($tids) {
   $found_nids = array();
   foreach (field_info_field_map() as $field_name => $v) {
     if ($v['type'] == 'taxonomy_term_reference' && isset($v['bundles']['node'])) {
-      // This field is taxonomy term reference and it is attached to nodes, so
-      // we will run EntityFieldQuery on it.
       $query = new EntityFieldQuery();
       $result = $query->entityCondition('entity_type', 'node')
         ->fieldCondition($field_name, 'tid', $tids, 'IN')
@@ -31,6 +29,18 @@ function synonyms_search_reindex_nodes_by_terms($tids) {
         $found_nids = array_merge($found_nids, array_keys($result['node']));
       }
     }
+    if ($v['type'] == 'entityreference' && isset($v['bundles']['node'])) {
+      $field = field_info_field($field_name);
+      if ($field['settings']['target_type'] == 'taxonomy_term') {
+        $query = new EntityFieldQuery();
+        $result = $query->entityCondition('entity_type', 'node')
+          ->fieldCondition($field_name, 'target_id', $tids, 'IN')
+          ->execute();
+        if (isset($result['node'])) {
+          $found_nids = array_merge($found_nids, array_keys($result['node']));
+        }
+      }
+    }
   }
   if (!empty($found_nids)) {
     db_update('search_dataset')
diff --git a/synonyms_search/synonyms_search.test b/synonyms_search/synonyms_search.test
index 5477d9a..3dae565 100644
--- a/synonyms_search/synonyms_search.test
+++ b/synonyms_search/synonyms_search.test
@@ -30,7 +30,7 @@ abstract class AbstractSearchSynonymsWebTestCase extends SynonymsWebTestCase {
    * SetUp method.
    */
   public function setUp($modules = array()) {
-    $modules[] = 'synonyms_search';
+    array_unshift($modules, 'synonyms_search');
     parent::setUp($modules);
 
     // Create a few terms and synonyms.
@@ -121,6 +121,7 @@ class NodeSearchSynonymsWebTestCase extends AbstractSearchSynonymsWebTestCase {
    * SetUp method.
    */
   public function setUp($modules = array()) {
+    $modules[] = 'entityreference';
     parent::setUp($modules);
 
     // Creating a test content type.
@@ -128,7 +129,18 @@ class NodeSearchSynonymsWebTestCase extends AbstractSearchSynonymsWebTestCase {
       'name' => 'Synonyms Test Content',
       'type' => 'synonyms_test_content',
     ), 'Save content type');
+  }
 
+  /**
+   * Test searching nodes by a term synonym.
+   *
+   * Since logically term and its synonyms represent the same entity, the idea
+   * is that searching by a term synonym should trigger all content referencing
+   * that term to be included in search results. Additionally we test that when
+   * a synonym is deleted/edited in a term, corresponding content is no longer
+   * encountered when searched by ex-synonym.
+   */
+  public function testSearchTermSynonym() {
     // Attaching term reference field to the new content type.
     $field = array(
       'type' => 'taxonomy_term_reference',
@@ -156,26 +168,110 @@ class NodeSearchSynonymsWebTestCase extends AbstractSearchSynonymsWebTestCase {
     );
 
     field_create_instance($instance);
+
+    // Creating a node, which references all the terms we have.
+    $node = (object) array(
+      'type' => 'synonyms_test_content',
+      'title' => $this->randomName(),
+      'synonyms_term_enabled' => array(LANGUAGE_NONE => array(
+        array('tid' => $this->terms['no_synonyms']->tid),
+        array('tid' => $this->terms['one_synonym']->tid),
+        array('tid' => $this->terms['two_synonyms']->tid),
+      )),
+    );
+    node_save($node);
+
+    // Rebuilding Search index.
+    $this->cronRun();
+
+    foreach ($this->terms as $k => $term) {
+      $this->assertSearchResults($term->name, array($node), 'Searching by name of the term ' . $k);
+      $items = field_get_items('taxonomy_term', $term, $this->fields['disabled']['field']['field_name']);
+      if (is_array($items)) {
+        foreach ($items as $delta => $item) {
+          $this->assertSearchResults($item['value'], array(), 'Searching by not enabled search integration field value #' . $delta . ' of term ' . $k);
+        }
+      }
+
+      $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
+      if (is_array($items)) {
+        foreach ($items as $delta => $item) {
+          $this->assertSearchResults($item['value'], array($node), 'Searching by synonym #' . $delta . ' of the term ' . $k);
+        }
+      }
+    }
+
+    // Removing a synonym from the term. Then asserting node got re-indexed with
+    // new values of synonyms.
+    $deleted_synonym = array_pop($this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE]);
+    taxonomy_term_save($this->terms['one_synonym']);
+    $this->cronRun();
+    $this->assertSearchResults($deleted_synonym['value'], array(), 'Searching by recently deleted synonym of a taxonomy term yields no results.');
+
+    // Editing a synonym in a term. Then asserting node got re-indexed with new
+    // values of synonyms.
+    $ex_synonym = $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
+    $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'] = $this->randomName();
+    taxonomy_term_save($this->terms['two_synonyms']);
+    $this->cronRun();
+    $this->assertSearchResults($ex_synonym, array(), 'Searching by recently changed synonym of a taxonomy term yields no results.');
+
+    // We disable entire field from search integration and make sure for all
+    // synonyms search results are empty.
+    synonyms_behavior_settings_delete($this->fields['enabled']['instance']['id'], $this->behavior);
+    $this->cronRun();
+    foreach ($this->terms as $k => $term) {
+      $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
+      if (is_array($items)) {
+        foreach ($items as $synonym) {
+          $this->assertSearchResults($synonym['value'], array(), 'Searching by ' . $k . ' term synonym, which field was recently disabled from search behavior yields no results.');
+        }
+      }
+    }
   }
 
   /**
-   * Test searching nodes by a term synonym.
+   * Test searching nodes by a term synonym when referenced by entity reference.
    *
-   * Since logically term and its synonyms represent the same entity, the idea
-   * is that searching by a term synonym should trigger all content referencing
-   * that term to be included in search results. Additionally we test that when
-   * a synonym is deleted/edited in a term, corresponding content is no longer
-   * encountered when searched by ex-synonym.
+   * This test pretty much does the same thing as the testSearchTermSynonym()
+   * with the only different that the terms are referenced through entity
+   * reference field type.
    */
-  public function testSearchTermSynonym() {
+  public function testSearchTermSynonymEntityReference() {
+    // Attaching entity reference field to the new content type.
+    $field = array(
+      'type' => 'entityreference',
+      'field_name' => 'synonyms_term_enabled',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'target_type' => 'taxonomy_term',
+        'handler_settings' => array(
+          'target_bundles' => array($this->vocabulary->machine_name),
+        ),
+      ),
+    );
+    $field = field_create_field($field);
+
+    $instance = array(
+      'field_name' => $field['field_name'],
+      'entity_type' => 'node',
+      'bundle' => 'synonyms_test_content',
+      'label' => 'Synonym Terms',
+      'widget' => array(
+        'type' => 'synonyms_autocomplete',
+      ),
+    );
+
+    field_create_instance($instance);
+
     // Creating a node, which references all the terms we have.
     $node = (object) array(
       'type' => 'synonyms_test_content',
       'title' => $this->randomName(),
       'synonyms_term_enabled' => array(LANGUAGE_NONE => array(
-        array('tid' => $this->terms['no_synonyms']->tid),
-        array('tid' => $this->terms['one_synonym']->tid),
-        array('tid' => $this->terms['two_synonyms']->tid),
+        array('target_id' => $this->terms['no_synonyms']->tid),
+        array('target_id' => $this->terms['one_synonym']->tid),
+        array('target_id' => $this->terms['two_synonyms']->tid),
       )),
     );
     node_save($node);
diff --git a/views/synonyms.views.inc b/views/synonyms.views.inc
index eaf8016..e72f74c 100644
--- a/views/synonyms.views.inc
+++ b/views/synonyms.views.inc
@@ -9,9 +9,11 @@
  * Implements hook_views_plugins_alter().
  */
 function synonyms_views_plugins_alter(&$plugins) {
-  // Replace default taxonomy term argument validator with our extended version,
-  // which can also handle a term synonym as an argument.
-  $plugins['argument validator']['taxonomy_term']['handler'] = 'synonyms_views_plugin_argument_validate_taxonomy_term';
+  if (module_exists('taxonomy')) {
+    // Replace default taxonomy term argument validator with our extended
+    // version, which can also handle a term synonym as an argument.
+    $plugins['argument validator']['taxonomy_term']['handler'] = 'synonyms_views_plugin_argument_validate_taxonomy_term';
+  }
 }
 
 /**
diff --git a/views/synonyms_views_handler_filter_term_tid.inc b/views/synonyms_views_handler_filter_term_tid.inc
index 4fafd5d..5d6c20c 100644
--- a/views/synonyms_views_handler_filter_term_tid.inc
+++ b/views/synonyms_views_handler_filter_term_tid.inc
@@ -53,11 +53,11 @@ class synonyms_views_handler_filter_term_tid extends views_handler_filter_term_n
       $bundle = $field['bundles'][$field_entity_type][0];
 
       $instance = field_info_instance($field_entity_type, $field['field_name'], $bundle);
-      if ($instance['widget']['type'] == 'synonyms_autocomplete') {
+      if ($instance['widget']['type'] == 'synonyms_autocomplete_taxonomy_term') {
         $widget = $instance['widget']['settings'];
       }
       else {
-        $widget = field_info_widget_settings('synonyms_autocomplete');
+        $widget = field_info_widget_settings('synonyms_autocomplete_taxonomy_term');
       }
       $autocomplete_path = $widget['synonyms_autocomplete_path'];
       $size = $widget['size'];
@@ -154,7 +154,7 @@ class synonyms_views_handler_filter_term_tid extends views_handler_filter_term_n
       if (!empty($missing)) {
         $condition = db_or();
         foreach ($missing as $tag => $v) {
-          $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $tag);
+          $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $tag);
         }
         $synonyms = synonyms_synonyms_find_behavior($condition, $behavior_implementation);
         foreach ($synonyms as $synonym) {
diff --git a/views/synonyms_views_plugin_argument_validate_taxonomy_term.inc b/views/synonyms_views_plugin_argument_validate_taxonomy_term.inc
index 18fcb79..5f4f900 100644
--- a/views/synonyms_views_plugin_argument_validate_taxonomy_term.inc
+++ b/views/synonyms_views_plugin_argument_validate_taxonomy_term.inc
@@ -63,12 +63,12 @@ class synonyms_views_plugin_argument_validate_taxonomy_term extends views_plugin
         foreach ($bundles as $bundle) {
           $condition = db_and();
           if ($transform) {
-            $condition->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :argument", array(
+            $condition->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :argument", array(
               ':argument' => $argument,
             ));
           }
           else {
-            $condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $argument);
+            $condition->condition(AbstractSynonymsBehavior::COLUMN_PLACEHOLDER, $argument);
           }
           $synonyms = synonyms_synonyms_find($condition, 'taxonomy_term', $bundle);
           if (!empty($synonyms)) {
