diff --git a/entityreference.devel_generate.inc b/entityreference.devel_generate.inc
index eee767c..8334019 100644
--- a/entityreference.devel_generate.inc
+++ b/entityreference.devel_generate.inc
@@ -17,7 +17,7 @@ function entityreference_devel_generate($object, $field, $instance, $bundle) {
 function _entityreference_devel_generate($object, $field, $instance, $bundle) {
   $object_field = array();
   // Get all the entity that are referencable here.
-  $referencable_entity = entityreference_get_selection_handler($field, $instance)->getReferencableEntities();
+  $referencable_entity = entityreference_get_selection_handler($field)->getReferencableEntities();
   if (is_array($referencable_entity) && !empty($referencable_entity)) {
     // Get a random key.
     $object_field['target_id'] = array_rand($referencable_entity);
diff --git a/entityreference.info b/entityreference.info
index bcb1c1c..8db2655 100644
--- a/entityreference.info
+++ b/entityreference.info
@@ -10,9 +10,8 @@ files[] = entityreference.migrate.inc
 
 ; Our plugins.
 files[] = plugins/selection/abstract.inc
-files[] = plugins/selection/base.class.php
+files[] = plugins/selection/base.inc
 files[] = plugins/behavior/abstract.inc
-files[] = plugins/behavior/base.inc
 
 ; Tests.
 files[] = tests/entityreference.handlers.test
diff --git a/entityreference.module b/entityreference.module
index 77decb9..d1c1177 100644
--- a/entityreference.module
+++ b/entityreference.module
@@ -14,23 +14,11 @@ function entityreference_ctools_plugin_directory($module, $plugin) {
  */
 function entityreference_ctools_plugin_type() {
   $plugins['selection'] = array();
-  $plugins['behavior'] = array('process' => 'entityreference_behavior_plugin_process');
+  $plugins['behavior'] = array();
   return $plugins;
 }
 
 /**
- * CTools callback; Process the behavoir plugins.
- */
-function entityreference_behavior_plugin_process(&$plugin, $info) {
-  $plugin += array(
-    'description' => '',
-    'behavior type' => 'field',
-    'access callback' => FALSE,
-    'force enabled' => FALSE,
-  );
-}
-
-/**
  * Implementation of hook_field_info().
  */
 function entityreference_field_info() {
@@ -38,7 +26,7 @@ function entityreference_field_info() {
     'label' => t('Entity Reference'),
     'description' => t('This field reference another entity.'),
     'settings' => array(
-      // Default to the core target entity type node.
+      // Default to the core target entity type node. 
       'target_type' => 'node',
       // The handler for this field.
       'handler' => 'base',
@@ -84,59 +72,34 @@ function entityreference_field_is_empty($item, $field) {
   return !isset($item['target_id']) || !is_numeric($item['target_id']);
 }
 
-
 /**
  * Get the behavior handlers for a given entityreference field.
  */
-function entityreference_get_behavior_handlers($field, $instance = NULL) {
+function entityreference_get_behavior_handlers($field) {
   $object_cache = drupal_static(__FUNCTION__);
-  $identifier = $field['field_name'];
-  if (!empty($instance)) {
-    $identifier .= ':' . $instance['entity_type'] . ':' . $instance['bundle'];
-  }
 
-  if (!isset($object_cache[$identifier])) {
-    $object_cache[$identifier] = array();
+  if (!isset($object_cache[$field['field_name']])) {
+    ctools_include('plugins');
 
     // Merge in defaults.
     $field['settings'] += array('behaviors' => array());
 
     $object_cache[$field['field_name']] = array();
-    $behaviors = !empty($field['settings']['handler_settings']['behaviors']) ? $field['settings']['handler_settings']['behaviors'] : array();
-    if (!empty($instance['settings']['behaviors'])) {
-      $behaviors = array_merge($behaviors, $instance['settings']['behaviors']);
-    }
-    foreach ($behaviors as $behavior => $settings) {
-      if (empty($settings['status'])) {
-        // Behavior is not enabled.
-        continue;
-      }
+    foreach ($field['settings']['behaviors'] as $behavior) {
+      // Merge in defaults.
+      $behavior += array(
+        'plugin' => '',
+        'settings' => array(),
+      );
 
-      $object_cache[$identifier][] = entityreference_get_behavior_handler($behavior, $field, $instance);
+      $class = ctools_plugin_load_class('entityreference', 'behavior', $behavior['plugin'], 'class');
+      if (class_exists($class)) {
+        $object_cache[$field['field_name']][$plugin_name] = new $class($behavior['settings'], $field);
+      }
     }
   }
 
-  return $object_cache[$identifier];
-}
-
-/**
- * Get the behavior handler for a given entityreference field and instance.
- *
- * @param $handler
- *   The behavior handler name.
- */
-function entityreference_get_behavior_handler($behavior, $field, $instance = NULL) {
-  $object_cache = drupal_static(__FUNCTION__);
-
-  if (!isset($object_cache[$behavior])) {
-    ctools_include('plugins');
-    $class = ctools_plugin_load_class('entityreference', 'behavior', $behavior, 'class');
-
-    $class = class_exists($class) ? $class : 'EntityReference_BehaviorHandler_Broken';
-    $object_cache[$behavior] = new $class($behavior, $field, $instance);
-  }
-
-  return $object_cache[$behavior];
+  return $object_cache[$field['field_name']];
 }
 
 /**
@@ -144,7 +107,7 @@ function entityreference_get_behavior_handler($behavior, $field, $instance = NUL
  *
  * The handler contains most of the business logic of the field.
  */
-function entityreference_get_selection_handler($field, $instance = NULL) {
+function entityreference_get_selection_handler($field) {
   $object_cache = drupal_static(__FUNCTION__);
 
   if (!isset($object_cache[$field['field_name']])) {
@@ -153,10 +116,10 @@ function entityreference_get_selection_handler($field, $instance = NULL) {
     $class = ctools_plugin_load_class('entityreference', 'selection', $handler, 'class');
 
     if (class_exists($class)) {
-      $object_cache[$field['field_name']] = call_user_func(array($class, 'getInstance'), $field, $instance);
+      $object_cache[$field['field_name']] = call_user_func(array($class, 'getInstance'), $field);
     }
     else {
-      $object_cache[$field['field_name']] = EntityReference_SelectionHandler_Broken::getInstance($field, $instance);
+      $object_cache[$field['field_name']] = EntityReference_SelectionHandler_Broken::getInstance($field);
     }
   }
 
@@ -184,7 +147,7 @@ function entityreference_field_validate($entity_type, $entity, $field, $instance
     }
   }
 
-  $valid_ids = entityreference_get_selection_handler($field, $instance)->validateReferencableEntities(array_keys($ids));
+  $valid_ids = entityreference_get_selection_handler($field)->validateReferencableEntities(array_keys($ids));
 
   $invalid_entities = array_diff_key($ids, array_flip($valid_ids));
   if ($invalid_entities) {
@@ -197,7 +160,7 @@ function entityreference_field_validate($entity_type, $entity, $field, $instance
   }
 
   // Invoke the behaviors.
-  foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) {
+  foreach (entityreference_get_behavior_handlers($field) as $handler) {
     $handler->validate($entity_type, $entity, $field, $instance, $langcode, $items, $errors);
   }
 }
@@ -213,7 +176,7 @@ function entityreference_field_presave($entity_type, $entity, $field, $instance,
   }
 
   // Invoke the behaviors.
-  foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) {
+  foreach (entityreference_get_behavior_handlers($field) as $handler) {
     $handler->presave($entity_type, $entity, $field, $instance, $langcode, $items);
   }
 }
@@ -223,7 +186,7 @@ function entityreference_field_presave($entity_type, $entity, $field, $instance,
  */
 function entityreference_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
   // Invoke the behaviors.
-  foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) {
+  foreach (entityreference_get_behavior_handlers($field) as $handler) {
     $handler->insert($entity_type, $entity, $field, $instance, $langcode, $items);
   }
 }
@@ -233,7 +196,7 @@ function entityreference_field_insert($entity_type, $entity, $field, $instance,
  */
 function entityreference_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
   // Invoke the behaviors.
-  foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) {
+  foreach (entityreference_get_behavior_handlers($field) as $handler) {
     $handler->update($entity_type, $entity, $field, $instance, $langcode, $items);
   }
 }
@@ -243,7 +206,7 @@ function entityreference_field_update($entity_type, $entity, $field, $instance,
  */
 function entityreference_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
   // Invoke the behaviors.
-  foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) {
+  foreach (entityreference_get_behavior_handlers($field) as $handler) {
     $handler->delete($entity_type, $entity, $field, $instance, $langcode, $items);
   }
 }
@@ -253,7 +216,6 @@ function entityreference_field_delete($entity_type, $entity, $field, $instance,
  */
 function entityreference_field_settings_form($field, $instance, $has_data) {
   $settings = $field['settings'];
-  $settings += array('handler' => 'base');
 
   // Select the target entity type.
   $entity_type_options = array();
@@ -320,22 +282,6 @@ function entityreference_field_settings_form($field, $instance, $has_data) {
 }
 
 /**
- * Implements hook_field_instance_settings_form().
- */
-function entityreference_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
-  ctools_include('plugins');
-  $class = ctools_plugin_load_class('entityreference', 'selection', $field['settings']['handler'], 'class');
-  if (!class_exists($class)) {
-    $class = 'EntityReference_SelectionHandler_Broken';
-  }
-
-  entityreference_get_behavior_elements($form, $class, $field, $instance, 'instance');
-
-  return $form;
-}
-
-/**
  * #process callback: generates the handler settings form.
  *
  * @see entityreference_field_settings_form()
@@ -349,7 +295,7 @@ function entityreference_render_settings($element, $form_state) {
   ctools_include('plugins');
   $class = ctools_plugin_load_class('entityreference', 'selection', $handler, 'class');
   if (!class_exists($class)) {
-    $class = 'EntityReference_SelectionHandler_Broken';
+    $class = 'EntityReferenceHandler_broken';
   }
 
   // Rebuild the field configuration based on the submitted structure.
@@ -359,80 +305,11 @@ function entityreference_render_settings($element, $form_state) {
     $field['settings'] = $form_state['values']['field']['settings'] + $field['settings'];
   }
 
-  entityreference_get_behavior_elements($element, $class, $field, $instance, 'field');
-
   $element += call_user_func(array($class, 'settingsForm'), $field, $instance);
   return $element;
 }
 
 /**
- * Get the field or instance elements for the field configuration.
- */
-function entityreference_get_behavior_elements(&$element, $class, $field, $instance, $level) {
-   // Add the accessible behavior handlers.
-  $behavior_plugins = entityreference_get_accessible_behavior_plugins($class, $field, $instance);
-
-  if ($behavior_plugins[$level]) {
-    $element['behaviors'] = array();
-
-    foreach ($behavior_plugins[$level] as $name => $plugin) {
-      if ($level == 'field') {
-        $settings = !empty($field['settings']['handler_settings']['behaviors'][$name]) ? $field['settings']['handler_settings']['behaviors'][$name] : array();
-      }
-      else {
-        $settings = !empty($instance['settings']['behaviors'][$name]) ? $instance['settings']['behaviors'][$name] : array();
-      }
-      $settings += array('status' => $plugin['force enabled']);
-      $element['behaviors'][$name] = array(
-        '#type' => 'fieldset',
-        '#title' => $plugin['title'],
-        '#default_value' => $settings['status'],
-      );
-      $element['behaviors'][$name]['status'] = array(
-        '#type' => 'checkbox',
-        '#title' => t('Enable %title', array('%title' => $plugin['title'])),
-        '#default_value' => $settings['status'],
-        '#disabled' => $plugin['force enabled'],
-      );
-
-      $behavior_class = ctools_plugin_load_class('entityreference', 'behavior', $name, 'class');
-      if ($behavior_elements = call_user_func(array($behavior_class, 'settingsForm'))) {
-        $enable_element = $level == 'field' ? 'field[settings][handler_settings][behaviors]' : 'instance[settings][behaviors]';
-        foreach ($behavior_elements as $key => &$behavior_element) {
-          $behavior_element += array(
-            '#default_value' => !empty($settings[$key]) ? $settings[$key] : NULL,
-            '#states' => array(
-              'visible' => array(
-                ':input[name="' . $enable_element . '[' . $name . '][status]"]' => array('checked' => TRUE),
-              ),
-            ),
-          );
-        }
-
-        // Get the behavior settings.
-        $element['behaviors'][$name] += $behavior_elements;
-      }
-    }
-  }
-}
-
-/**
- * Get all accessible behavior plugins.
- */
-function entityreference_get_accessible_behavior_plugins($select_class, $field, $instance) {
-  ctools_include('plugins');
-  $plugins = array('field' => array(), 'instance' => array());
-  foreach (ctools_get_plugins('entityreference', 'behavior') as $name => $plugin) {
-    $handler = entityreference_get_behavior_handler($name, $field, $instance);
-    $level = $plugin['behavior type'];
-    if ($handler->access($select_class)) {
-      $plugins[$level][$name] = $plugin;
-    }
-  }
-  return $plugins;
-}
-
-/**
  * Ajax callback for the handler settings form.
  *
  * @see entityreference_field_settings_form()
@@ -553,24 +430,22 @@ function entityreference_field_widget_settings_form($field, $instance) {
 /**
  * Implements hook_options_list().
  */
-function entityreference_options_list($field, $instance = NULL) {
-  return entityreference_get_selection_handler($field, $instance)->getReferencableEntities();
+function entityreference_options_list($field) {
+  return entityreference_get_selection_handler($field)->getReferencableEntities();
 }
 
 /**
  * Implements hook_query_TAG_alter().
  */
 function entityreference_query_entityreference_alter(QueryAlterableInterface $query) {
-  $field = $query->getMetadata('field');
-  $instance = $query->getMetadata('instance');
-  entityreference_get_selection_handler($field, $instance)->entityFieldQueryAlter($query);
+  entityreference_get_selection_handler($query->getMetadata('field'))->entityFieldQueryAlter($query);
 }
 
 /**
  * Implements hook_field_widget_form().
  */
 function entityreference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $handler = entityreference_get_selection_handler($field, $instance);
+  $handler = entityreference_get_selection_handler($field);
 
   if ($instance['widget']['type'] == 'entityreference_autocomplete' || $instance['widget']['type'] == 'entityreference_autocomplete_tags') {
 
@@ -686,7 +561,7 @@ function entityreference_autocomplete_callback($type, $field_name, $entity_type,
     return MENU_ACCESS_DENIED;
   }
 
-  $handler = entityreference_get_selection_handler($field, $instance);
+  $handler = entityreference_get_selection_handler($field);
 
   if ($type == 'tags') {
     // The user enters a comma-separated list of tags. We only autocomplete the last tag.
@@ -851,7 +726,7 @@ function entityreference_field_formatter_view($entity_type, $entity, $field, $in
 
   switch ($display['type']) {
     case 'entityreference_label':
-      $handler = entityreference_get_selection_handler($field, $instance);
+      $handler = entityreference_get_selection_handler($field);
 
       foreach ($items as $delta => $item) {
         $label = $handler->getLabel($item['entity']);
diff --git a/examples/entityreference_behavior_example/entityreference_behavior_example.info b/examples/entityreference_behavior_example/entityreference_behavior_example.info
index 1ba5149..ba2ec17 100644
--- a/examples/entityreference_behavior_example/entityreference_behavior_example.info
+++ b/examples/entityreference_behavior_example/entityreference_behavior_example.info
@@ -3,7 +3,3 @@ description = Provides some example code for implementing Entity Reference behav
 core = 7.x
 package = Fields
 dependencies[] = entityreference
-
-; Behavior handlers
-files[] = plugins/behavior/test_field_behavior.class.php
-files[] = plugins/behavior/test_instance_behavior.class.php
\ No newline at end of file
diff --git a/examples/entityreference_behavior_example/entityreference_behavior_example.module b/examples/entityreference_behavior_example/entityreference_behavior_example.module
index 9d6c6f8..f2c143c 100644
--- a/examples/entityreference_behavior_example/entityreference_behavior_example.module
+++ b/examples/entityreference_behavior_example/entityreference_behavior_example.module
@@ -1,11 +1,6 @@
 <?php
 
 /**
- * @file
- * Example module to demonstrate Entity reference behavior handlers.
- */
-
-/**
  * Implements hook_ctools_plugin_directory().
  */
 function entityreference_behavior_example_ctools_plugin_directory($module, $plugin) {
diff --git a/examples/entityreference_behavior_example/plugins/behavior/test_behavior.inc b/examples/entityreference_behavior_example/plugins/behavior/test_behavior.inc
new file mode 100644
index 0000000..52d44a7
--- /dev/null
+++ b/examples/entityreference_behavior_example/plugins/behavior/test_behavior.inc
@@ -0,0 +1,38 @@
+<?php
+
+$plugin = array(
+  'title' => t('Test behavior'),
+  'class' => 'EntityReferenceBehaviorExample',
+  'weight' => 10,
+);
+
+class EntityReferenceBehaviorExample implements EntityReference_BehaviorHandler {
+  public function __construct(array $settings, array $field) {
+    $this->settings = $settings;
+    $this->field = $field;
+  }
+
+  public function load($entity_type, $entities, $field, $instances, $langcode, &$items) {
+    drupal_set_message('Do something on load!');
+  }
+
+  public function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+    
+  }
+
+  public function presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
+    
+  }
+
+  public function insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
+    drupal_set_message('Do something on insert!');
+  }
+
+  public function update($entity_type, $entity, $field, $instance, $langcode, &$items) {
+    drupal_set_message('Do something on update!');
+  }
+
+  public function delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
+    drupal_set_message('Do something on delete!');
+  }
+}
diff --git a/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.class.php b/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.class.php
deleted file mode 100644
index 1f9652b..0000000
--- a/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.class.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-class EntityReferenceFieldBehaviorExample extends EntityReference_BehaviorHandler_Generic {
-
-  public function load($entity_type, $entities, $field, $instances, $langcode, &$items) {
-    drupal_set_message('Do something on load!');
-  }
-
-  public function insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on insert!');
-  }
-
-  public function update($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on update!');
-  }
-
-  public function delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on delete!');
-  }
-
-  /**
-   * Generate a settings form for this handler.
-   */
-  public function settingsForm() {
-    $form['test_field'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Field behavoir setting'),
-    );
-    return $form;
-  }
-}
diff --git a/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.inc b/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.inc
deleted file mode 100644
index 590087b..0000000
--- a/examples/entityreference_behavior_example/plugins/behavior/test_field_behavior.inc
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-$plugin = array(
-  'title' => t('Test behavior'),
-  'class' => 'EntityReferenceFieldBehaviorExample',
-  'weight' => 10,
-  'behavior type' => 'field',
-);
diff --git a/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.class.php b/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.class.php
deleted file mode 100644
index 5c6be25..0000000
--- a/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.class.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-class EntityReferenceInstanceBehaviorExample extends EntityReference_BehaviorHandler_Generic {
-
-  public function load($entity_type, $entities, $field, $instances, $langcode, &$items) {
-    drupal_set_message('Do something on load, on the instance level!');
-  }
-
-  public function insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on insert, on the instance level!');
-  }
-
-  public function update($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on update, on the instance level!');
-  }
-
-  public function delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
-    drupal_set_message('Do something on delete, on the instance level!');
-  }
-
-  /**
-   * Generate a settings form for this handler.
-   */
-  public function settingsForm() {
-    $form['test_instance'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Instance behavoir setting'),
-    );
-    return $form;
-  }
-}
\ No newline at end of file
diff --git a/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.inc b/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.inc
deleted file mode 100644
index 41173fe..0000000
--- a/examples/entityreference_behavior_example/plugins/behavior/test_instance_behavior.inc
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-$plugin = array(
-  'title' => t('Test instance behavior'),
-  'class' => 'EntityReferenceInstanceBehaviorExample',
-  'weight' => 10,
-  'behavior type' => 'instance',
-);
diff --git a/plugins/behavior/abstract.inc b/plugins/behavior/abstract.inc
index 86aaad8..77f0f7d 100644
--- a/plugins/behavior/abstract.inc
+++ b/plugins/behavior/abstract.inc
@@ -7,96 +7,38 @@
  * register it using CTools' plugin system.
  */
 interface EntityReference_BehaviorHandler {
+  /**
+   * @TODO: document.
+   */
+  public function __construct(array $settings, array $field);
 
   /**
-   * Act on loading entity reference fields of entities.
-   *
-   * @see hook_field_load()
+   * @TODO: document.
    */
   public function load($entity_type, $entities, $field, $instances, $langcode, &$items);
 
   /**
-   * Act on validating an entity reference field.
-   *
-   * @see hook_field_validate()
+   * @TODO: document.
    */
   public function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors);
 
   /**
-   * Act on presaving an entity reference field.
-   *
-   * @see hook_field_presave()
+   * @TODO: document.
    */
   public function presave($entity_type, $entity, $field, $instance, $langcode, &$items);
 
   /**
-   * Act after inserting an entity reference field.
-   *
-   * @see hook_field_insert()
+   * @TODO: document.
    */
   public function insert($entity_type, $entity, $field, $instance, $langcode, &$items);
 
   /**
-   * Act after updating an entity reference field.
-   *
-   * @see hook_field_update()
+   * @TODO: document.
    */
   public function update($entity_type, $entity, $field, $instance, $langcode, &$items);
 
   /**
-   * Act after deleting entity reference field.
-   *
-   * @see hook_field_delete()
+   * @TODO: document.
    */
   public function delete($entity_type, $entity, $field, $instance, $langcode, &$items);
-
-  /**
-   * Generate a settings form for this handler.
-   */
-  public function settingsForm();
-
-  /**
-   * Determine if handler should appear.
-   */
-  public function access($selection_class);
 }
-
-/**
- * A null implementation of EntityReference_BehaviorHandler.
- */
-class EntityReference_BehaviorHandler_Broken implements EntityReference_BehaviorHandler {
-
-  public function load($entity_type, $entities, $field, $instances, $langcode, &$items) {
-
-  }
-
-  public function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
-
-  }
-
-  public function presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
-
-  }
-
-  public function insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
-
-  }
-
-  public function update($entity_type, $entity, $field, $instance, $langcode, &$items) {
-
-  }
-
-  public function delete($entity_type, $entity, $field, $instance, $langcode, &$items);
-
-  public function settingsForm() {
-    $form['behavior_handler'] = array(
-      '#markup' => t('The selected behavior handler is broken.'),
-    );
-    return $form;
-
-  }
-
-  public function access($selection_class) {
-    return FALSE;
-  }
-}
\ No newline at end of file
diff --git a/plugins/behavior/base.inc b/plugins/behavior/base.inc
deleted file mode 100644
index 67e5dd7..0000000
--- a/plugins/behavior/base.inc
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-class EntityReference_BehaviorHandler_Generic implements EntityReference_BehaviorHandler {
-
-  public function __construct($behavior, array $field, array $instance = NULL) {
-    ctools_include('plugins');
-    $plugin = ctools_get_plugins('entityreference', 'behavior', $behavior);
-    $this->plugin = $plugin;
-
-    if ($plugin['behavior type'] == 'field') {
-      $this->settings = !empty($field['settings']['handler_settings']['behavior']) ? $field['settings']['handler_settings']['behavior'] : array();
-    }
-    else {
-      $this->settings = !empty($instance['settings']['behavior']) ? $instance['settings']['behavior'] : array();
-    }
-
-    $this->status = !empty($settings['status']) ? $settings['status'] : FALSE;
-    unset($this->settings['status']);
-
-    $this->field = $field;
-    $this->instance = $instance;
-  }
-
-  public function load($entity_type, $entities, $field, $instances, $langcode, &$items) {}
-
-  public function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {}
-
-  public function presave($entity_type, $entity, $field, $instance, $langcode, &$items) {}
-
-  public function insert($entity_type, $entity, $field, $instance, $langcode, &$items) {}
-
-  public function update($entity_type, $entity, $field, $instance, $langcode, &$items) {}
-
-  public function delete($entity_type, $entity, $field, $instance, $langcode, &$items) {}
-
-  public function settingsForm() {}
-
-  public function access($selection_class) {
-    return TRUE;
-  }
-}
diff --git a/plugins/selection/abstract.inc b/plugins/selection/abstract.inc
index 75743e4..071af17 100644
--- a/plugins/selection/abstract.inc
+++ b/plugins/selection/abstract.inc
@@ -14,7 +14,7 @@ interface EntityReference_SelectionHandler {
    *   A field datastructure.
    * @return EntityReferenceHandler
    */
-  public static function getInstance($field, $instance);
+  public static function getInstance($field);
 
   /**
    * Return a list of referencable entities.
@@ -54,18 +54,17 @@ interface EntityReference_SelectionHandler {
  * A null implementation of EntityReference_SelectionHandler.
  */
 class EntityReference_SelectionHandler_Broken implements EntityReference_SelectionHandler {
-  public static function getInstance($field, $instance) {
-    return new EntityReference_SelectionHandler_Broken($field, $instance);
+  public static function getInstance($field) {
+    return new EntityReference_SelectionHandler_Broken($field);
   }
 
-  protected function __construct($field, $instance) {
+  protected function __construct($field) {
     $this->field = $field;
-    $this->instance = $instance;
   }
 
   public static function settingsForm($field, $instance) {
-    $form['selection_handler'] = array(
-      '#markup' => t('The selected selection handler is broken.'),
+    $form['handler'] = array(
+      '#markup' => t('The selected handler is broken.'),
     );
     return $form;
   }
diff --git a/plugins/selection/base.class.php b/plugins/selection/base.class.php
deleted file mode 100644
index de5ab2b..0000000
--- a/plugins/selection/base.class.php
+++ /dev/null
@@ -1,414 +0,0 @@
-<?php
-
-/**
- * A generic Entity handler.
- *
- * The generic base implementation has a variety of overrides to workaround
- * core's largely deficient entity handling.
- */
-class EntityReference_SelectionHandler_Generic implements EntityReference_SelectionHandler {
-
-  /**
-   * Implements EntityReferenceHandler::getInstance().
-   */
-  public static function getInstance($field, $instance) {
-    $entity_type = $field['settings']['target_type'];
-    if (class_exists($class_name = 'EntityReference_SelectionHandler_Generic_' . $entity_type)) {
-      return new $class_name($field, $instance);
-    }
-    else {
-      return new EntityReference_SelectionHandler_Generic($field, $instance);
-    }
-  }
-
-  protected function __construct($field, $instance) {
-    $this->field = $field;
-    $this->instance = $instance;
-  }
-
-  /**
-   * Implements EntityReferenceHandler::settingsForm().
-   */
-  public static function settingsForm($field, $instance) {
-    $entity_info = entity_get_info($field['settings']['target_type']);
-    $bundles = array();
-    foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
-      $bundles[$bundle_name] = $bundle_info['label'];
-    }
-
-    $form['target_bundles'] = array(
-      '#type' => 'select',
-      '#title' => t('Target bundles'),
-      '#options' => $bundles,
-      '#default_value' => isset($field['settings']['handler_settings']['target_bundles']) ? $field['settings']['handler_settings']['target_bundles'] : array(),
-      '#size' => 6,
-      '#multiple' => TRUE,
-      '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.')
-    );
-
-    $form['sort']['type'] = array(
-      '#type' => 'radios',
-      '#title' => t('Sort by'),
-      '#options' => array(
-        'none' => t("Don't sort"),
-        'property' => t('A property of the base table of the entity'),
-        'field' => t('A field attached to this entity'),
-      ),
-      '#default_value' => isset($field['settings']['handler_settings']['sort']['type']) ? $field['settings']['handler_settings']['sort']['type'] : 'none',
-    );
-
-    $form['sort']['property'] = array(
-      '#type' => 'select',
-      '#title' => t('Sort property'),
-      '#options' => drupal_map_assoc($entity_info['schema_fields_sql']['base table']),
-      '#default_value' => isset($field['settings']['handler_settings']['sort']['property']) ? $field['settings']['handler_settings']['sort']['property'] : '',
-      '#states' => array(
-        'visible' => array(
-          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'property'),
-        ),
-      ),
-    );
-
-    $fields = array();
-    foreach (field_info_instances($field['settings']['target_type']) as $bundle_name => $bundle_instances) {
-      foreach ($bundle_instances as $instance_name => $instance_info) {
-        $field_info = field_info_field($instance_name);
-        foreach ($field_info['columns'] as $column_name => $column_info) {
-          $fields[$instance_name . ':' . $column_name] = t('@label (column @column)', array('@label' => $instance_info['label'], '@column' => $column_name));
-        }
-      }
-    }
-
-    $form['sort']['field'] = array(
-      '#type' => 'select',
-      '#title' => t('Sort field'),
-      '#options' => $fields,
-      '#default_value' => isset($field['settings']['handler_settings']['sort']['type']) ? $field['settings']['handler_settings']['sort']['type'] : '',
-      '#states' => array(
-        'visible' => array(
-          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'field'),
-        ),
-      ),
-    );
-
-    $form['sort']['direction'] = array(
-      '#type' => 'select',
-      '#title' => t('Sort direction'),
-      '#options' => array(
-        'ASC' => t('Ascending'),
-        'DESC' => t('Descending'),
-      ),
-      '#default_value' => isset($field['settings']['handler_settings']['sort']['direction']) ? $field['settings']['handler_settings']['sort']['direction'] : 'ASC',
-      '#states' => array(
-        'invisible' => array(
-          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'none'),
-        ),
-      ),
-    );
-
-    return $form;
-  }
-
-  /**
-   * Implements EntityReferenceHandler::getReferencableEntities().
-   */
-  public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
-    $options = array();
-    $entity_type = $this->field['settings']['target_type'];
-
-    $query = $this->buildEntityFieldQuery($match, $match_operator);
-    if ($limit > 0) {
-      $query->range(0, $limit);
-    }
-
-    $results = $query->execute();
-
-    if (!empty($results[$entity_type])) {
-      $entities = entity_load($entity_type, array_keys($results[$entity_type]));
-      foreach ($entities as $entity_id => $entity) {
-        $options[$entity_id] = $this->getLabel($entity);
-      }
-    }
-
-    return $options;
-  }
-
-  /**
-   * Implements EntityReferenceHandler::countReferencableEntities().
-   */
-  public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') {
-    $query = $this->buildEntityFieldQuery($match, $match_operator);
-    return $query
-      ->count()
-      ->execute();
-  }
-
-  /**
-   * Implements EntityReferenceHandler::validateReferencableEntities().
-   */
-  public function validateReferencableEntities(array $ids) {
-    if ($ids) {
-      $entity_type = $this->field['settings']['target_type'];
-      $query = $this->buildEntityFieldQuery();
-      $query->entityCondition('entity_id', $ids, 'IN');
-      $result = $query->execute();
-      if (!empty($result[$entity_type])) {
-        return array_keys($result[$entity_type]);
-      }
-    }
-
-    return array();
-  }
-
-  /**
-   * Build an EntityFieldQuery to get referencable entities.
-   */
-  protected function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
-    $query = new EntityFieldQuery();
-    $query->entityCondition('entity_type', $this->field['settings']['target_type']);
-    if ($this->field['settings']['handler_settings']['target_bundles']) {
-      $query->entityCondition('bundle', $this->field['settings']['handler_settings']['target_bundles'], 'IN');
-    }
-    if (isset($match)) {
-      $entity_info = entity_get_info($this->field['settings']['target_type']);
-      if (isset($entity_info['entity keys']['label'])) {
-        $query->propertyCondition($entity_info['entity keys']['label'], $match, $match_operator);
-      }
-    }
-
-    // Add a generic entity access tag to the query.
-    $query->addTag('entity_field_access');
-    $query->addTag('entityreference');
-    $query->addMetaData('field', $this->field);
-
-    // Add the sort option.
-    if (!empty($this->field['settings']['handler_settings']['sort'])) {
-      $sort_settings = $this->field['settings']['handler_settings']['sort'];
-      if ($sort_settings['type'] == 'property') {
-        $query->propertyOrderBy($sort_settings['property'], $sort_settings['direction']);
-      }
-      elseif ($sort_settings['type'] == 'field') {
-        list($field, $column) = explode(':', $sort_settings['field'], 2);
-        $query->fieldOrderBy($field, $column, $sort_settings['direction']);
-      }
-    }
-
-    return $query;
-  }
-
-  /**
-   * Implements EntityReferenceHandler::entityFieldQueryAlter().
-   */
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-
-  }
-
-  /**
-   * Helper method: pass a query to the alteration system again.
-   *
-   * This allow Entity Reference to add a tag to an existing query, to ask
-   * access control mechanisms to alter it again.
-   */
-  protected function reAlterQuery(SelectQueryInterface $query, $tag, $base_table) {
-    // Save the old tags and metadata.
-    // For some reason, those are public.
-    $old_tags = $query->alterTags;
-    $old_metadata = $query->alterMetaData;
-
-    $query->alterTags = array($tag => TRUE);
-    $query->alterMetaData['base_table'] = $base_table;
-    drupal_alter(array('query', 'query_' . $tag), $query);
-
-    // Restore the tags and metadata.
-    $query->alterTags = $old_tags;
-    $query->alterMetaData = $old_metadata;
-  }
-
-  /**
-   * Implements EntityReferenceHandler::getLabel().
-   */
-  public function getLabel($entity) {
-    return entity_label($this->field['settings']['target_type'], $entity);
-  }
-}
-
-/**
- * Override for the Node type.
- *
- * This only exists to workaround core bugs.
- */
-class EntityReference_SelectionHandler_Generic_node extends EntityReference_SelectionHandler_Generic {
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-    // Adding the 'node_access' tag is sadly insufficient for nodes: core
-    // requires us to also know about the concept of 'published' and
-    // 'unpublished'. We need to do that as long as there are no access control
-    // modules in use on the site. As long as one access control module is there,
-    // it is supposed to handle this check.
-    if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
-      $tables = $query->getTables();
-      $query->condition(key($tables) . '.status', NODE_PUBLISHED);
-    }
-  }
-}
-
-/**
- * Override for the User type.
- *
- * This only exists to workaround core bugs.
- */
-class EntityReference_SelectionHandler_Generic_user extends EntityReference_SelectionHandler_Generic {
-  public function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
-    $query = parent::buildEntityFieldQuery($match, $match_operator);
-
-    // The user entity doesn't have a label column.
-    if (isset($match)) {
-      $query->propertyCondition('name', $match, $match_operator);
-    }
-
-    // Adding the 'user_access' tag is sadly insufficient for users: core
-    // requires us to also know about the concept of 'blocked' and
-    // 'active'.
-    if (!user_access('administer users')) {
-      $query->propertyCondition('status', 1);
-    }
-    return $query;
-  }
-
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-    if (user_access('administer users')) {
-      // In addition, if the user is administrator, we need to make sure to
-      // match the anonymous user, that doesn't actually have a name in the
-      // database.
-      $conditions = &$query->conditions();
-      foreach ($conditions as $key => $condition) {
-        if ($condition['field'] == 'users.name') {
-          // Remove the condition.
-          unset($conditions[$key]);
-
-          // Re-add the condition and a condition on uid = 0 so that we end up
-          // with a query in the form:
-          //    WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
-          $or = db_or();
-          $or->condition($condition['field'], $condition['value'], $condition['operator']);
-          // Sadly, the Database layer doesn't allow us to build a condition
-          // in the form ':placeholder = :placeholder2', because the 'field'
-          // part of a condition is always escaped.
-          // As a (cheap) workaround, we separately build a condition with no
-          // field, and concatenate the field and the condition separately.
-          $value_part = db_and();
-          $value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
-          $value_part->compile(Database::getConnection(), $query);
-          $or->condition(db_and()
-            ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => format_username(user_load(0))))
-            ->condition('users.uid', 0)
-          );
-          $query->condition($or);
-        }
-      }
-    }
-  }
-}
-
-/**
- * Override for the Comment type.
- *
- * This only exists to workaround core bugs.
- */
-class EntityReference_SelectionHandler_Generic_comment extends EntityReference_SelectionHandler_Generic {
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-    // Adding the 'comment_access' tag is sadly insufficient for comments: core
-    // requires us to also know about the concept of 'published' and
-    // 'unpublished'.
-    if (!user_access('administer comments')) {
-      $tables = $query->getTables();
-      $query->condition(key($tables) . '.status', COMMENT_PUBLISHED);
-    }
-
-    // The Comment module doesn't implement any proper comment access,
-    // and as a consequence doesn't make sure that comments cannot be viewed
-    // when the user doesn't have access to the node.
-    $tables = $query->getTables();
-    $base_table = key($tables);
-    $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid');
-    // Pass the query to the node access control.
-    $this->reAlterQuery($query, 'node_access', $node_alias);
-
-    // Alas, the comment entity exposes a bundle, but doesn't have a bundle column
-    // in the database. We have to alter the query ourself to go fetch the
-    // bundle.
-    $conditions = &$query->conditions();
-    foreach ($conditions as $id => &$condition) {
-      if (is_array($condition) && $condition['field'] == 'node_type') {
-        $condition['field'] = $node_alias . '.type';
-        foreach ($condition['value'] as &$value) {
-          if (substr($value, 0, 13) == 'comment_node_') {
-            $value = substr($value, 13);
-          }
-        }
-        break;
-      }
-    }
-
-    // Passing the query to node_query_node_access_alter() is sadly
-    // insufficient for nodes.
-    // @see EntityReferenceHandler_node::entityFieldQueryAlter()
-    if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
-      $query->condition($node_alias . '.status', 1);
-    }
-  }
-}
-
-/**
- * Override for the File type.
- *
- * This only exists to workaround core bugs.
- */
-class EntityReference_SelectionHandler_Generic_file extends EntityReference_SelectionHandler_Generic {
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-    // Core forces us to know about 'permanent' vs. 'temporary' files.
-    $tables = $query->getTables();
-    $base_table = key($tables);
-    $query->condition('status', FILE_STATUS_PERMANENT);
-
-    // Access control to files is a very difficult business. For now, we are not
-    // going to give it a shot.
-    // @todo: fix this when core access control is less insane.
-    return $query;
-  }
-
-  public function getLabel($entity) {
-    // The file entity doesn't have a label. More over, the filename is
-    // sometimes empty, so use the basename in that case.
-    return $entity->filename !== '' ? $entity->filename : basename($entity->uri);
-  }
-}
-
-/**
- * Override for the Taxonomy term type.
- *
- * This only exists to workaround core bugs.
- */
-class EntityReference_SelectionHandler_Generic_taxonomy_term extends EntityReference_SelectionHandler_Generic {
-  public function entityFieldQueryAlter(SelectQueryInterface $query) {
-    // The Taxonomy module doesn't implement any proper taxonomy term access,
-    // and as a consequence doesn't make sure that taxonomy terms cannot be viewed
-    // when the user doesn't have access to the vocabulary.
-    $tables = $query->getTables();
-    $base_table = key($tables);
-    $vocabulary_alias = $query->innerJoin('taxonomy_vocabulary', 'n', '%alias.vid = ' . $base_table . '.vid');
-    $query->addMetadata('base_table', $vocabulary_alias);
-    // Pass the query to the taxonomy access control.
-    $this->reAlterQuery($query, 'taxonomy_vocabulary_access', $vocabulary_alias);
-
-    // Also, the taxonomy term entity exposes a bundle, but doesn't have a bundle
-    // column in the database. We have to alter the query ourself to go fetch
-    // the bundle.
-    $conditions = &$query->conditions();
-    foreach ($conditions as $id => &$condition) {
-      if (is_array($condition) && $condition['field'] == 'vocabulary_machine_name') {
-        $condition['field'] = $vocabulary_alias . '.machine_name';
-        break;
-      }
-    }
-  }
-}
diff --git a/plugins/selection/base.inc b/plugins/selection/base.inc
index 32471c9..d8ae568 100644
--- a/plugins/selection/base.inc
+++ b/plugins/selection/base.inc
@@ -5,3 +5,415 @@ $plugin = array(
   'class' => 'EntityReference_SelectionHandler_Generic',
   'weight' => -100,
 );
+
+/**
+ * A generic Entity handler.
+ *
+ * The generic base implementation has a variety of overrides to workaround
+ * core's largely deficient entity handling.
+ */
+class EntityReference_SelectionHandler_Generic implements EntityReference_SelectionHandler {
+
+  /**
+   * Implements EntityReferenceHandler::getInstance().
+   */
+  public static function getInstance($field) {
+    $entity_type = $field['settings']['target_type'];
+    if (class_exists($class_name = 'EntityReference_SelectionHandler_Generic_' . $entity_type)) {
+      return new $class_name($field);
+    }
+    else {
+      return new EntityReference_SelectionHandler_Generic($field);
+    }
+  }
+
+  protected function __construct($field) {
+    $this->field = $field;
+  }
+
+  /**
+   * Implements EntityReferenceHandler::settingsForm().
+   */
+  public static function settingsForm($field, $instance) {
+    $entity_info = entity_get_info($field['settings']['target_type']);
+    $bundles = array();
+    foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
+      $bundles[$bundle_name] = $bundle_info['label'];
+    }
+
+    $form['target_bundles'] = array(
+      '#type' => 'select',
+      '#title' => t('Target bundles'),
+      '#options' => $bundles,
+      '#default_value' => isset($field['settings']['handler_settings']['target_bundles']) ? $field['settings']['handler_settings']['target_bundles'] : array(),
+      '#size' => 6,
+      '#multiple' => TRUE,
+      '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.')
+    );
+
+    $form['sort']['type'] = array(
+      '#type' => 'radios',
+      '#title' => t('Sort by'),
+      '#options' => array(
+        'none' => t("Don't sort"),
+        'property' => t('A property of the base table of the entity'),
+        'field' => t('A field attached to this entity'),
+      ),
+      '#default_value' => isset($field['settings']['handler_settings']['sort']['type']) ? $field['settings']['handler_settings']['sort']['type'] : 'none',
+    );
+
+    $form['sort']['property'] = array(
+      '#type' => 'select',
+      '#title' => t('Sort property'),
+      '#options' => drupal_map_assoc($entity_info['schema_fields_sql']['base table']),
+      '#default_value' => isset($field['settings']['handler_settings']['sort']['property']) ? $field['settings']['handler_settings']['sort']['property'] : '',
+      '#states' => array(
+        'visible' => array(
+          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'property'),
+        ),
+      ),
+    );
+
+    $fields = array();
+    foreach (field_info_instances($field['settings']['target_type']) as $bundle_name => $bundle_instances) {
+      foreach ($bundle_instances as $instance_name => $instance_info) {
+        $field_info = field_info_field($instance_name);
+        foreach ($field_info['columns'] as $column_name => $column_info) {
+          $fields[$instance_name . ':' . $column_name] = t('@label (column @column)', array('@label' => $instance_info['label'], '@column' => $column_name));
+        }
+      }
+    }
+
+    $form['sort']['field'] = array(
+      '#type' => 'select',
+      '#title' => t('Sort field'),
+      '#options' => $fields,
+      '#default_value' => isset($field['settings']['handler_settings']['sort']['type']) ? $field['settings']['handler_settings']['sort']['type'] : '',
+      '#states' => array(
+        'visible' => array(
+          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'field'),
+        ),
+      ),
+    );
+
+    $form['sort']['direction'] = array(
+      '#type' => 'select',
+      '#title' => t('Sort direction'),
+      '#options' => array(
+        'ASC' => t('Ascending'),
+        'DESC' => t('Descending'),
+      ),
+      '#default_value' => isset($field['settings']['handler_settings']['sort']['direction']) ? $field['settings']['handler_settings']['sort']['direction'] : 'ASC',
+      '#states' => array(
+        'invisible' => array(
+          ':input[name="field[settings][handler_settings][sort][type]"]' => array('value' => 'none'),
+        ),
+      ),
+    );
+
+    return $form;
+  }
+
+  /**
+   * Implements EntityReferenceHandler::getReferencableEntities().
+   */
+  public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
+    $options = array();
+    $entity_type = $this->field['settings']['target_type'];
+
+    $query = $this->buildEntityFieldQuery($match, $match_operator);
+    if ($limit > 0) {
+      $query->range(0, $limit);
+    }
+
+    $results = $query->execute();
+
+    if (!empty($results[$entity_type])) {
+      $entities = entity_load($entity_type, array_keys($results[$entity_type]));
+      foreach ($entities as $entity_id => $entity) {
+        $options[$entity_id] = $this->getLabel($entity);
+      }
+    }
+
+    return $options;
+  }
+
+  /**
+   * Implements EntityReferenceHandler::countReferencableEntities().
+   */
+  public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') {
+    $query = $this->buildEntityFieldQuery($match, $match_operator);
+    return $query
+      ->count()
+      ->execute();
+  }
+
+  /**
+   * Implements EntityReferenceHandler::validateReferencableEntities().
+   */
+  public function validateReferencableEntities(array $ids) {
+    if ($ids) {
+      $entity_type = $this->field['settings']['target_type'];
+      $query = $this->buildEntityFieldQuery();
+      $query->entityCondition('entity_id', $ids, 'IN');
+      $result = $query->execute();
+      if (!empty($result[$entity_type])) {
+        return array_keys($result[$entity_type]);
+      }
+    }
+
+    return array();
+  }
+
+  /**
+   * Build an EntityFieldQuery to get referencable entities.
+   */
+  protected function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', $this->field['settings']['target_type']);
+    if ($this->field['settings']['handler_settings']['target_bundles']) {
+      $query->entityCondition('bundle', $this->field['settings']['handler_settings']['target_bundles'], 'IN');
+    }
+    if (isset($match)) {
+      $entity_info = entity_get_info($this->field['settings']['target_type']);
+      if (isset($entity_info['entity keys']['label'])) {
+        $query->propertyCondition($entity_info['entity keys']['label'], $match, $match_operator);
+      }
+    }
+
+    // Add a generic entity access tag to the query.
+    $query->addTag($this->field['settings']['target_type'] . '_access');
+    $query->addTag('entityreference');
+    $query->addMetaData('field', $this->field);
+
+    // Add the sort option.
+    if (!empty($this->field['settings']['handler_settings']['sort'])) {
+      $sort_settings = $this->field['settings']['handler_settings']['sort'];
+      if ($sort_settings['type'] == 'property') {
+        $query->propertyOrderBy($sort_settings['property'], $sort_settings['direction']);
+      }
+      elseif ($sort_settings['type'] == 'field') {
+        list($field, $column) = explode(':', $sort_settings['field'], 2);
+        $query->fieldOrderBy($field, $column, $sort_settings['direction']);
+      }
+    }
+
+    return $query;
+  }
+
+  /**
+   * Implements EntityReferenceHandler::entityFieldQueryAlter().
+   */
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+
+  }
+
+  /**
+   * Helper method: pass a query to the alteration system again.
+   *
+   * This allow Entity Reference to add a tag to an existing query, to ask
+   * access control mechanisms to alter it again.
+   */
+  protected function reAlterQuery(SelectQueryInterface $query, $tag, $base_table) {
+    // Save the old tags and metadata.
+    // For some reason, those are public.
+    $old_tags = $query->alterTags;
+    $old_metadata = $query->alterMetaData;
+
+    $query->alterTags = array($tag => TRUE);
+    $query->alterMetaData['base_table'] = $base_table;
+    drupal_alter(array('query', 'query_' . $tag), $query);
+
+    // Restore the tags and metadata.
+    $query->alterTags = $old_tags;
+    $query->alterMetaData = $old_metadata;
+  }
+
+  /**
+   * Implements EntityReferenceHandler::getLabel().
+   */
+  public function getLabel($entity) {
+    return entity_label($this->field['settings']['target_type'], $entity);
+  }
+}
+
+/**
+ * Override for the Node type.
+ *
+ * This only exists to workaround core bugs.
+ */
+class EntityReference_SelectionHandler_Generic_node extends EntityReference_SelectionHandler_Generic {
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+    // Adding the 'node_access' tag is sadly insufficient for nodes: core
+    // requires us to also know about the concept of 'published' and
+    // 'unpublished'. We need to do that as long as there are no access control
+    // modules in use on the site. As long as one access control module is there,
+    // it is supposed to handle this check.
+    if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
+      $tables = $query->getTables();
+      $query->condition(key($tables) . '.status', NODE_PUBLISHED);
+    }
+  }
+}
+
+/**
+ * Override for the User type.
+ *
+ * This only exists to workaround core bugs.
+ */
+class EntityReference_SelectionHandler_Generic_user extends EntityReference_SelectionHandler_Generic {
+  public function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
+    $query = parent::buildEntityFieldQuery($match, $match_operator);
+
+    // The user entity doesn't have a label column.
+    if (isset($match)) {
+      $query->propertyCondition('name', $match, $match_operator);
+    }
+
+    // Adding the 'user_access' tag is sadly insufficient for users: core
+    // requires us to also know about the concept of 'blocked' and
+    // 'active'.
+    if (!user_access('administer users')) {
+      $query->propertyCondition('status', 1);
+    }
+    return $query;
+  }
+
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+    if (user_access('administer users')) {
+      // In addition, if the user is administrator, we need to make sure to
+      // match the anonymous user, that doesn't actually have a name in the
+      // database.
+      $conditions = &$query->conditions();
+      foreach ($conditions as $key => $condition) {
+        if ($condition['field'] == 'users.name') {
+          // Remove the condition.
+          unset($conditions[$key]);
+
+          // Re-add the condition and a condition on uid = 0 so that we end up
+          // with a query in the form:
+          //    WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
+          $or = db_or();
+          $or->condition($condition['field'], $condition['value'], $condition['operator']);
+          // Sadly, the Database layer doesn't allow us to build a condition
+          // in the form ':placeholder = :placeholder2', because the 'field'
+          // part of a condition is always escaped.
+          // As a (cheap) workaround, we separately build a condition with no
+          // field, and concatenate the field and the condition separately.
+          $value_part = db_and();
+          $value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
+          $value_part->compile(Database::getConnection(), $query);
+          $or->condition(db_and()
+            ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => format_username(user_load(0))))
+            ->condition('users.uid', 0)
+          );
+          $query->condition($or);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Override for the Comment type.
+ *
+ * This only exists to workaround core bugs.
+ */
+class EntityReference_SelectionHandler_Generic_comment extends EntityReference_SelectionHandler_Generic {
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+    // Adding the 'comment_access' tag is sadly insufficient for comments: core
+    // requires us to also know about the concept of 'published' and
+    // 'unpublished'.
+    if (!user_access('administer comments')) {
+      $tables = $query->getTables();
+      $query->condition(key($tables) . '.status', COMMENT_PUBLISHED);
+    }
+
+    // The Comment module doesn't implement any proper comment access,
+    // and as a consequence doesn't make sure that comments cannot be viewed
+    // when the user doesn't have access to the node.
+    $tables = $query->getTables();
+    $base_table = key($tables);
+    $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid');
+    // Pass the query to the node access control.
+    $this->reAlterQuery($query, 'node_access', $node_alias);
+
+    // Alas, the comment entity exposes a bundle, but doesn't have a bundle column
+    // in the database. We have to alter the query ourself to go fetch the
+    // bundle.
+    $conditions = &$query->conditions();
+    foreach ($conditions as $id => &$condition) {
+      if (is_array($condition) && $condition['field'] == 'node_type') {
+        $condition['field'] = $node_alias . '.type';
+        foreach ($condition['value'] as &$value) {
+          if (substr($value, 0, 13) == 'comment_node_') {
+            $value = substr($value, 13);
+          }
+        }
+        break;
+      }
+    }
+
+    // Passing the query to node_query_node_access_alter() is sadly
+    // insufficient for nodes.
+    // @see EntityReferenceHandler_node::entityFieldQueryAlter()
+    if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
+      $query->condition($node_alias . '.status', 1);
+    }
+  }
+}
+
+/**
+ * Override for the File type.
+ *
+ * This only exists to workaround core bugs.
+ */
+class EntityReference_SelectionHandler_Generic_file extends EntityReference_SelectionHandler_Generic {
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+    // Core forces us to know about 'permanent' vs. 'temporary' files.
+    $tables = $query->getTables();
+    $base_table = key($tables);
+    $query->condition('status', FILE_STATUS_PERMANENT);
+
+    // Access control to files is a very difficult business. For now, we are not
+    // going to give it a shot.
+    // @todo: fix this when core access control is less insane.
+    return $query;
+  }
+
+  public function getLabel($entity) {
+    // The file entity doesn't have a label. More over, the filename is
+    // sometimes empty, so use the basename in that case.
+    return $entity->filename !== '' ? $entity->filename : basename($entity->uri);
+  }
+}
+
+/**
+ * Override for the Taxonomy term type.
+ *
+ * This only exists to workaround core bugs.
+ */
+class EntityReference_SelectionHandler_Generic_taxonomy_term extends EntityReference_SelectionHandler_Generic {
+  public function entityFieldQueryAlter(SelectQueryInterface $query) {
+    // The Taxonomy module doesn't implement any proper taxonomy term access,
+    // and as a consequence doesn't make sure that taxonomy terms cannot be viewed
+    // when the user doesn't have access to the vocabulary.
+    $tables = $query->getTables();
+    $base_table = key($tables);
+    $vocabulary_alias = $query->innerJoin('taxonomy_vocabulary', 'n', '%alias.vid = ' . $base_table . '.vid');
+    $query->addMetadata('base_table', $vocabulary_alias);
+    // Pass the query to the taxonomy access control.
+    $this->reAlterQuery($query, 'taxonomy_vocabulary_access', $vocabulary_alias);
+
+    // Also, the taxonomy term entity exposes a bundle, but doesn't have a bundle
+    // column in the database. We have to alter the query ourself to go fetch
+    // the bundle.
+    $conditions = &$query->conditions();
+    foreach ($conditions as $id => &$condition) {
+      if (is_array($condition) && $condition['field'] == 'vocabulary_machine_name') {
+        $condition['field'] = $vocabulary_alias . '.machine_name';
+        break;
+      }
+    }
+  }
+}
