diff --git a/modules/taxonomy.workbench_access.inc b/modules/taxonomy.workbench_access.inc
index 43d13c6..feed172 100644
--- a/modules/taxonomy.workbench_access.inc
+++ b/modules/taxonomy.workbench_access.inc
@@ -93,6 +93,27 @@ function taxonomy_workbench_access_field_form_alter(&$form, &$form_state, $activ
 /**
  * Implements hook_workbench_access_FORM_ID_alter().
  */
+function taxonomy_workbench_access_field_ui_field_edit_form_alter(&$form, &$form_state, $active) {
+  _workbench_access_taxonomy_remove_option($form);
+  $form['instance']['workbench_access_field'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Workbench Access control field'),
+    '#description' => t('Use this field to determine access control for content editing.'),
+    '#default_value' => !empty($form['#instance']['workbench_access_field']),
+    '#weight' => -15,
+  );
+  $allowed = workbench_access_get_assigned_fields($form['#instance']['bundle']);
+  $instance = $form['#instance']['field_name'];
+  if (!isset($allowed[$instance])) {
+    $form['instance']['workbench_access_field']['#disabled'] = TRUE;
+    $form['instance']['workbench_access_field']['#default_value'] = 0;
+    $form['instance']['workbench_access_field']['#description'] = t('This field cannot be used for access control.');
+  }
+}
+
+/**
+ * Implements hook_workbench_access_FORM_ID_alter().
+ */
 function taxonomy_workbench_access_field_ui_field_settings_form_alter(&$form, &$form_state, $active) {
   _workbench_access_taxonomy_remove_option($form);
 }
@@ -101,6 +122,9 @@ function taxonomy_workbench_access_field_ui_field_settings_form_alter(&$form, &$
  * Helper function to remove the option from Field UI forms.
  */
 function _workbench_access_taxonomy_remove_option(&$form) {
+  if (!variable_get('workbench_access_custom_form', 1)) {
+    return;
+  }
   // The element we want is nested very deeply in the form.
   if (!isset($form['field']['settings']['allowed_values'])) {
     return;
@@ -242,3 +266,95 @@ function workbench_access_taxonomy_vocabulary_delete($vocabulary) {
     workbench_access_section_delete($access_scheme);
   }
 }
+
+/**
+ * Executes a form alter on a specific FieldAPI form element.
+ */
+function taxonomy_workbench_access_default_form_alter(&$form, &$form_state, $options) {
+  foreach ($form['workbench_access_fields']['#value'] as $item) {
+    // If the element isn't set, we can't do anything.
+    if (!isset($form[$item][$form[$item]['#language']])) {
+      continue;
+    }
+
+    // Set the element to be altered.
+    $element = &$form[$item][$form[$item]['#language']];
+    // Set the options for the form.
+    if (isset($form[$item][$form[$item]['#language']]['#options'])) {
+      foreach ($element['#options'] as $key => $value) {
+        if ($key != '_none' && !isset($options[$key])) {
+          unset($element['#options'][$key]);
+        }
+      }
+    }
+    // To act on autocompletes, we need to add the node type to the callback.
+    elseif (isset($element['#autocomplete_path'])) {
+      $element['#autocomplete_path'] .= '/' . $form['#node']->type;
+      // We need our own validation, too.
+      $element['#element_validate'][] = 'workbench_access_taxonomy_autocomplete_validate';
+    }
+  }
+  // Inform Workbench Access which data element we store on the node.
+  // (e.g.) $node->{$field}[LANGUAGE][][COLUMN].
+  $form['workbench_access_column'] = array(
+    '#type' => 'value',
+    '#value' => 'tid',
+  );
+  $form['workbench_access_language'] = array(
+    '#type' => 'value',
+    '#value' => TRUE,
+  );
+}
+
+/**
+ * Helper function for autocompletion of taxonomy terms.
+ *
+ * To determine if this is an access control field, we need to know the node
+ * type.
+ *
+ * @see workbench_access_menu_alter()
+ * @see workbench_access_query_term_access_alter()
+ *
+ * @param $field_name
+ *  The name of the field being queried.
+ * @param $node_type
+ *  The content type for this field instance.
+ * @param $tags_typed
+ *  The data input by the user.
+ *
+ * @return
+ *  No return value, the taxonomy_autocomplete() fires a JSON object.
+ */
+function workbench_access_taxonomy_autocomplete($field_name, $node_type, $tags_typed = '') {
+  module_load_include('inc', 'taxonomy', 'taxonomy.pages');
+  taxonomy_autocomplete($field_name, $tags_typed);
+}
+
+/**
+ * Form element validate handler for taxonomy term autocomplete element.
+ *
+ * @TODO: How to handle the creation (or not) of new items here?
+ */
+function workbench_access_taxonomy_autocomplete_validate($element, &$form_state) {
+  global $user;
+  $item = $form_state['values'][$element['#field_name']][$form_state['values']['language']];
+  if (empty($item)) {
+    return;
+  }
+  if (!isset($user->workbench_access)) {
+    workbench_access_user_load_data($user);
+  }
+  $tree = workbench_access_get_user_tree($user);
+  // TODO: What if the user tree is empty?
+  $terms = array();
+  if (!empty($tree)) {
+    foreach ($item as $key => $value) {
+      if (!isset($tree[$value['tid']])) {
+        $terms[] = check_plain($value['name']);
+      }
+    }
+  }
+  if (!empty($terms)) {
+    form_set_error($element['#field_name'], t('You may not assign this content to: !terms', array('!terms' => implode(', ', $terms))));
+  }
+}
diff --git a/workbench_access.admin.inc b/workbench_access.admin.inc
index 8fded4e..2b420f7 100644
--- a/workbench_access.admin.inc
+++ b/workbench_access.admin.inc
@@ -71,6 +71,59 @@ function workbench_access_settings_form($form, &$form_state) {
     $form['node_types']['message'] = array(
       '#markup' => '<em>' . t('Only selected content types will have Workbench Access rules enforced.') . '</em>',
     );
+    // Set the field settings for Taxonomy, if required.
+    if (!variable_get('workbench_access_custom_form', 1)) {
+      $form['field_elements'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Access control fields'),
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+        '#tree' => TRUE,
+        '#description' => t('Set the field elements that control access to each content type.'),
+      );
+      if (!module_exists('field_property')) {
+        $form['field_elements']['#collapsed'] = FALSE;
+        $form['field_elements']['#description'] = '<strong>' . t('Installing and enabling the <a href="!url">Field Property module</a> is recommended.', array('!url' => 'http://drupal.org/project/field_property')) . '</strong><br />' . $form['field_elements']['#description'];
+      }
+      foreach ($types as $type => $data) {
+        $fields = workbench_access_get_assigned_fields($type);
+        $name = node_type_get_name($type);
+        $controlled = variable_get('workbench_access_node_type_' . $type, 1);
+        if (empty($controlled)) {
+          $form['field_elements'][$type] = array(
+            '#type' => 'item',
+            '#title' => t('%type access control fields', array('%type' => $name)),
+            '#markup' => t('This content type is not under access control.'),
+          );
+        }
+        elseif (empty($fields)) {
+          $message = t('The %type content type does not have an access field configured.', array('%type' => $name));
+          drupal_set_message($message, 'warning', FALSE);
+          $form['field_elements'][$type] = array(
+            '#type' => 'item',
+            '#title' => t('%type access control fields', array('%type' => $name)),
+            '#markup' => $message,
+          );
+        }
+        else {
+          $field_options = array();
+          $default_options = array();
+          foreach ($fields as $field => $info) {
+            $field_options[$field] = t('!label (!field)', array('!label' => $info['instance_info']['label'], '!field' => $field));
+            if (!empty($info['instance_info']['workbench_access_field'])) {
+              $default_options[$field] = $field;
+            }
+          }
+          $form['field_elements'][$type] = array(
+            '#type' => 'select',
+            '#title' => t('%type access control fields', array('%type' => $name)),
+            '#options' => $field_options,
+            '#default_value' => $default_options,
+            '#multiple' => variable_get('workbench_access_allow_multiple', 0),
+          );
+        }
+      }
+    }
   }
   $form['workbench_access_label'] = array(
     '#type' => 'textfield',
@@ -90,6 +143,12 @@ function workbench_access_settings_form($form, &$form_state) {
     '#default_value' => variable_get('workbench_access_allow_multiple', 0),
     '#description' => t('Let content be assigned to multiple sections.'),
   );
+  $form['workbench_access_custom_form'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Require a Workbench Access form element'),
+    '#default_value' => variable_get('workbench_access_custom_form', 1),
+    '#description' => t('If not selected, Workbench Access settings will inherit from the standard node form.'),
+  );
   $form = system_settings_form($form);
   $form['#validate'][] = 'workbench_access_settings_validate';
   $form['#submit'][] = 'workbench_access_settings_submit';
@@ -154,6 +213,27 @@ function workbench_access_settings_submit($form, &$form_state) {
       workbench_access_section_delete((array) $section);
     }
   }
+  // If field settings are present, save them.
+  if (isset($form_state['values']['field_elements'])) {
+    workbench_access_save_field_elements($form_state['values']['field_elements']);
+  }
+}
+
+/**
+ * Save field element settings for native forms.
+ *
+ * @param $types
+ *  An array of field options for each active node type.
+ */
+function workbench_access_save_field_elements($types) {
+  foreach ($types as $type => $settings) {
+    $fields = workbench_access_get_assigned_fields($type);
+    foreach ($fields as $field => $info) {
+      $instance = $info['instance_info'];
+      $instance['workbench_access_field'] = (int) !empty($settings[$field]);
+      field_update_instance($instance);
+    }
+  }
 }
 
 /**
diff --git a/workbench_access.install b/workbench_access.install
index 3dff412..0275b61 100644
--- a/workbench_access.install
+++ b/workbench_access.install
@@ -162,6 +162,7 @@ function workbench_access_requirements($phase) {
   if ($phase == 'runtime') {
     $tree = workbench_access_get_active_tree();
     $roles = workbench_access_get_roles('access workbench access by role');
+    $types = workbench_access_check_access_fields();
     $description = array();
     // If this variable has not been set, workbench access is not fully configured.
     if (!variable_get('workbench_access', FALSE)) {
@@ -174,6 +175,13 @@ function workbench_access_requirements($phase) {
     if (empty($roles)) {
       $description[] = t('At least one role must be have the <a href="!url">Allow all members of this role to be assigned to Workbench Access sections</a> permission', array('!url' => url('admin/people/permissions', array('fragment' => 'module-workbench_access'))));
     }
+    if (!empty($types)) {
+      $items = array();
+      foreach ($types as $type) {
+        $items[] = check_plain(node_type_get_name($type));
+      }
+      $description[] = t('The following content types are not properly configured for access control: !types', array('!types' => theme('item_list', array('items' => $items))));
+    }
     if (empty($description)) {
       $requirements['workbench_access'] = array(
         'title' => t('Workbench Access'),
diff --git a/workbench_access.module b/workbench_access.module
index 35a4cd7..b6fbac0 100644
--- a/workbench_access.module
+++ b/workbench_access.module
@@ -101,6 +101,19 @@ function workbench_access_menu_alter(&$items) {
   $items['taxonomy/term/%taxonomy_term']['access callback'] = 'workbench_access_taxonomy_page_access';
   $items['taxonomy/term/%taxonomy_term']['access arguments'] = array(2);
 
+  // Taxonomy autocomplete does not pass enough context.
+  // Not using a custom form element or taxonomy? Then we don't need this.
+  if (!variable_get('workbench_access_custom_form', 1) || variable_get('workbench_access', 'taxonomy') != 'taxonomy') {
+    $items['taxonomy/autocomplete'] = array(
+      'title' => 'Autocomplete taxonomy',
+      'page callback' => 'workbench_access_taxonomy_autocomplete',
+      'access arguments' => array('access content'),
+      'type' => MENU_CALLBACK,
+      'file' => 'taxonomy.workbench_access.inc',
+      'file path' => drupal_get_path('module', 'workbench_access') . '/modules',
+    );
+  }
+
   // Only needed if Workbench module is disabled.
   if (module_exists('workbench')) {
     return;
@@ -283,6 +296,10 @@ function workbench_access_views_default_views() {
  * Implements hook_field_extra_fields()
  */
 function workbench_access_field_extra_fields() {
+  // Not using a custom form element?
+  if (!variable_get('workbench_access_custom_form', 1)) {
+    return;
+  }
   $extra = array();
   foreach (node_type_get_names() as $name => $value) {
     if (variable_get('workbench_access_node_type_' . $name, 1)) {
@@ -620,6 +637,33 @@ function workbench_access_node_insert($node) {
  * Implements hook_node_presave().
  */
 function workbench_access_node_presave($node) {
+  // Did we use the default field form?
+  if (isset($node->workbench_access_fields)) {
+    $node->workbench_access_id = array();
+    foreach ($node->workbench_access_fields as $field) {
+      if (!is_array($node->{$field})) {
+        $node->workbench_access_id[] = $node->{$field};
+      }
+      else {
+        if (!empty($node->workbench_access_language)) {
+          $data = $node->{$field}[$node->language];
+        }
+        else {
+          $data = array($node->{$field});
+        }
+        foreach ($data as $value) {
+          if (isset($value[$node->workbench_access_column])) {
+            // Handle disabled menu links.
+            if (!isset($value['enabled']) || !empty($value['enabled'])) {
+              $node->workbench_access_id[] = $value[$node->workbench_access_column];
+            }
+          }
+        }
+      }
+    }
+  }
+  // Ensure that the data format is consistent and that items that cannot
+  // be changed by this editor are preserved.
   if (isset($node->workbench_access_id) && isset($node->workbench_access_fixed)) {
     if (!is_array($node->workbench_access_id)) {
       $node->workbench_access_id = array($node->workbench_access_id);
@@ -629,6 +673,10 @@ function workbench_access_node_presave($node) {
     }
     $node->workbench_access_id += $node->workbench_access_fixed;
   }
+  // Due to form handling, it is possible that we have duplicate entries.
+  if (isset($node->workbench_access_id) && is_array($node->workbench_access_id)) {
+    $node->workbench_access_id = array_unique($node->workbench_access_id);
+  }
 }
 
 /**
@@ -1262,96 +1310,37 @@ function workbench_access_is_active_id($access_type, $access_type_id) {
  */
 function workbench_access_form_alter(&$form, $form_state, $form_id) {
   global $user;
-  // Fire any active internal module hooks.
+
+  // Make sure we prepared the user.
+  if (!isset($user->workbench_access)) {
+    workbench_access_user_load_data($user);
+  }
+
+  // Fire any active internal module hooks for non-node forms.
   if (empty($form['#node_edit_form'])) {
     workbench_access_alter_form($form_id, $form, $form_state);
+    return;
   }
-  // Ensure that we can enforce our rules.
-  elseif (!isset($form['#node']->type) || !variable_get('workbench_access_node_type_' . $form['#node']->type, 1)) {
+
+  // Fire the node form alter, if there are configured sections.
+  if (!workbench_access_allow_form_alter()) {
     return;
   }
-  // Fire the node form alter.
-  else {
-    // Make sure we prepared the user.
-    if (!isset($user->workbench_access)) {
-      workbench_access_user_load_data($user);
-    }
-    // Prepare the form element.
-    $active = workbench_access_get_active_tree();
-    if (empty($active['active'])) {
-      drupal_set_message(workbench_access_sections_needed_message(), 'warning');
-      return;
-    }
-    $tree = workbench_access_get_user_tree();
-    // Generate options so we can check for access.
-    $options = workbench_access_options($tree, $active['active']);
-    $default = array();
-    if (!empty($form['#node']->workbench_access)) {
-      $default = array_keys($form['#node']->workbench_access);
-    }
-    // If there are no options and the 'workbench_access' variable has not been set
-    // then it seems that Workbench Access has not been configured.
-    if (empty($options) && !variable_get('workbench_access', FALSE)) {
-      $message = workbench_access_configuration_needed_message();
-      // Using 'error' instead of warning because the user should not have gotten this far
-      // without configuring Workbench Access.
-      drupal_set_message($message, 'error', $repeat = FALSE);
-    }
 
-    // The base form element.
-    $multiple = variable_get('workbench_access_allow_multiple', 0);
-    $element = array(
-      '#type' => 'select',
-      '#title' => t('@message_label', array('@message_label' => variable_get('workbench_access_label', 'Section'))),
-      '#options' => $options,
-      '#required' => TRUE,
-      '#default_value' => $default,
-      '#multiple' => $multiple,
-      '#description' => ($multiple) ? t('Select the proper editorial group(s) for this content.') : t('Select the proper editorial group for this content.'),
-    );
-    // If the default is set and is not in the user's range, then pass hidden and
-    // display a message.
-    // TODO: $default might legitimately be zero in some edge cases.
-    if (!empty($default)) {
-      $all = array();
-      $disallowed = array();
-      foreach ($default as $item) {
-        if (isset($active['tree'][$item]['name'])) {
-          $all[$active['tree'][$item]['access_id']] = check_plain($active['tree'][$item]['name']);
-          if (!isset($options[$item])) {
-            $disallowed[$active['tree'][$item]['access_id']] = check_plain($active['tree'][$item]['name']);
-          }
-        }
-      }
-      if (!empty($disallowed)) {
-        $diff = array_diff($all, $disallowed);
-        // TODO: If we toggle from single to multiple, then this can get messy.
-        if (empty($diff) || !variable_get('workbench_access_allow_multiple', 0)) {
-          $element['#type'] = 'value';
-          $element['#value'] = $element['#default_value'];
-          $form['workbench_access']['message'] = array(
-            '#type' => 'item',
-            '#title' => t('Workbench access'),
-            '#markup' => t('%title is assigned to the %section editorial group(s), which may not be changed.', array('%title' => $form['#node']->title, '%section' => implode(', ', $disallowed))),
-          );
-        }
-        else {
-          $form['workbench_access']['workbench_access_fixed'] = array(
-            '#type' => 'value',
-            '#value' => array_keys($disallowed),
-          );
-          $element['#description'] = $element['#description'] . '<br />' . t('%title is also assigned to the %section editorial group(s), which may not be changed.', array('%title' => $form['#node']->title, '%section' => implode(', ', $disallowed)));
-        }
-      }
-    }
-    workbench_access_alter_form('node_element', $element, $form_state);
-    $form['workbench_access']['#type'] = 'container';
-    $form['workbench_access']['workbench_access_id'] = $element;
-    $form['workbench_access']['workbench_access_scheme'] = array(
-      '#type' => 'value',
-      '#value' => $active['access_scheme'],
-    );
+  // Determine which form element to target.
+  if (variable_get('workbench_access_custom_form', 1)) {
+    // Provide a form element.
+    workbench_access_node_form_element($form, $form_state);
+  }
+  else {
+    workbench_access_default_form_element($form, $form_state);
   }
+  // Register the access scheme with the form.
+  $active = workbench_access_get_active_tree();
+  $form['workbench_access']['workbench_access_scheme'] = array(
+    '#type' => 'value',
+    '#value' => $active['access_scheme'],
+  );
 }
 
 /**
@@ -1369,6 +1358,152 @@ function workbench_access_alter_form($hook, &$form, &$form_state) {
 }
 
 /**
+ * Check to see if the module is configured and we can run our form alter.
+ *
+ * TODO: Make this a generic function, which is called elsewhere.
+ */
+function workbench_access_allow_form_alter() {
+  $active = workbench_access_get_active_tree();
+  $ids = array_filter($active['access_scheme']['access_type_id']);
+  if (!empty($ids)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Provides a module-specific form for access control.
+ */
+function workbench_access_node_form_element(&$form, $form_state) {
+  global $user;
+
+  // Prepare the form element.
+  $active = workbench_access_get_active_tree();
+  if (empty($active['active'])) {
+    drupal_set_message(workbench_access_sections_needed_message(), 'warning');
+    return;
+  }
+  $tree = workbench_access_get_user_tree();
+  // Generate options so we can check for access.
+  $options = workbench_access_options($tree, $active['active']);
+  $default = array();
+  if (!empty($form['#node']->workbench_access)) {
+    $default = array_keys($form['#node']->workbench_access);
+  }
+  // If there are no options and the 'workbench_access' variable has not been set
+  // then it seems that Workbench Access has not been configured.
+  if (empty($options) && !variable_get('workbench_access', FALSE)) {
+    $message = workbench_access_configuration_needed_message();
+    // Using 'error' instead of warning because the user should not have gotten this far
+    // without configuring Workbench Access.
+    drupal_set_message($message, 'error', $repeat = FALSE);
+  }
+
+  // The base form element.
+  $multiple = variable_get('workbench_access_allow_multiple', 0);
+  $element = array(
+    '#type' => 'select',
+    '#title' => t('@message_label', array('@message_label' => variable_get('workbench_access_label', 'Section'))),
+    '#options' => $options,
+    '#required' => TRUE,
+    '#default_value' => $default,
+    '#multiple' => $multiple,
+    '#description' => ($multiple) ? t('Select the proper editorial group(s) for this content.') : t('Select the proper editorial group for this content.'),
+  );
+  // If the default is set and is not in the user's range, then pass hidden and
+  // display a message.
+  // TODO: $default might legitimately be zero in some edge cases.
+  if (!empty($default)) {
+    $all = array();
+    $disallowed = array();
+    foreach ($default as $item) {
+      if (isset($active['tree'][$item]['name'])) {
+        $all[$active['tree'][$item]['access_id']] = check_plain($active['tree'][$item]['name']);
+        if (!isset($options[$item])) {
+          $disallowed[$active['tree'][$item]['access_id']] = check_plain($active['tree'][$item]['name']);
+        }
+      }
+      }
+    if (!empty($disallowed)) {
+      $diff = array_diff($all, $disallowed);
+      // TODO: If we toggle from single to multiple, then this can get messy.
+      if (empty($diff) || !variable_get('workbench_access_allow_multiple', 0)) {
+        $element['#type'] = 'value';
+        $element['#value'] = $element['#default_value'];
+        $form['workbench_access']['message'] = array(
+          '#type' => 'item',
+          '#title' => t('Workbench access'),
+          '#markup' => t('%title is assigned to the %section editorial group(s), which may not be changed.', array('%title' => $form['#node']->title, '%section' => implode(', ', $disallowed))),
+        );
+      }
+      else {
+        $form['workbench_access']['workbench_access_fixed'] = array(
+          '#type' => 'value',
+          '#value' => array_keys($disallowed),
+        );
+        $element['#description'] = $element['#description'] . '<br />' . t('%title is also assigned to the %section editorial group(s), which may not be changed.', array('%title' => $form['#node']->title, '%section' => implode(', ', $disallowed)));
+      }
+    }
+  }
+  workbench_access_alter_form('node_element', $element, $form_state);
+  $form['workbench_access']['workbench_access_id'] = $element;
+}
+
+/**
+ * Find and alter the native form element for node editing.
+ *
+ * FieldAPI makes this much harder than it needs to be.
+ */
+function workbench_access_default_form_element(&$form, &$form_state) {
+  // Try to find the form element(s) to target.
+  workbench_access_find_form_elements($form);
+  if (empty($form['workbench_access_fields']['#value'])) {
+    drupal_set_message(workbench_access_configuration_needed_message(), 'warning');
+  }
+  else {
+    // Prepare the form element.
+    $active = workbench_access_get_active_tree();
+    $tree = workbench_access_get_user_tree();
+    // Generate options so we can check for access.
+    $options = workbench_access_options($tree, $active['active']);
+    // Call the function.
+    $func = $form['workbench_access_fields']['#access_type'] . '_workbench_access_default_form_alter';
+    if (function_exists($func)) {
+      $func($form, $form_state, $options);
+    }
+  }
+}
+  
+/**
+ * Find form elements that control access.
+ *
+ * @see workbench_access_get_assigned_fields()
+ */
+function workbench_access_find_form_elements(&$form) {
+  $active = workbench_access_get_active_tree();
+  $form['workbench_access_fields'] = array(
+    '#type' => 'value',
+    '#value' => array(),
+    '#access_type' => $active['access_scheme']['access_type'],
+  );
+  // Find the menu form, which is easy.
+  if ($active['access_scheme']['access_type'] == 'menu') {
+    $form['workbench_access_fields']['#value'][] = 'menu';
+  }
+
+  // Find taxonomy and other fieldable entities.
+  else {
+    $type = $form['#node']->type;
+    $fields = workbench_access_get_assigned_fields($type);
+    foreach ($fields as $field => $info) {
+      if (!empty($info['instance_info']['workbench_access_field'])) {
+        $form['workbench_access_fields']['#value'][] = $field;
+      }
+    }
+  }
+}
+
+/**
  * Return the text directing admins to Workbench Access configuration.
  */
 function workbench_access_configuration_needed_message() {
@@ -1722,6 +1857,38 @@ function workbench_access_get_roles($permission) {
 }
 
 /**
+ * Tests content types for proper field configuration.
+ *
+ * @return
+ *  An array of node types that are _not_ configured properly.
+ */
+function workbench_access_check_access_fields() {
+  $broken = array();
+  if (variable_get('workbench_access_custom_form', 1)) {
+    return $broken;
+  }
+  $types = node_type_get_types();
+  foreach ($types as $type => $data) {
+    $fields = workbench_access_get_assigned_fields($type);
+    $check = FALSE;
+    if (variable_get('workbench_access_node_type_' . $type, 1)) {
+      foreach ($fields as $field) {
+        if (!empty($field['instance_info']['workbench_access_field'])) {
+          $check = TRUE;
+        }
+      }
+    }
+    else {
+      $check = TRUE;
+    }
+    if (!$check) {
+      $broken[] = $type;
+    }
+  }
+  return $broken;
+}
+
+/**
  * Load callback to load information about an access scheme.
  */
 function workbench_access_access_scheme_load($scheme) {
@@ -1729,3 +1896,84 @@ function workbench_access_access_scheme_load($scheme) {
   $info = module_invoke_all('workbench_access_info');
   return isset($info[$scheme]) ? $info[$scheme] : FALSE;
 }
+
+/**
+ * Finds fields associated with a content type.
+ *
+ * @param $type
+ *  The content type machine name.
+ *
+ * @return
+ *  An array of field data that matches the current access scheme.
+ */
+function workbench_access_get_assigned_fields($type) {
+  $matches = array();
+  $fields = field_info_instances('node', $type);
+  $scheme = variable_get('workbench_access', 'taxonomy');
+  $settings = variable_get('workbench_access_' . $scheme, array());
+  foreach ($fields as $field => $info) {
+    $data = field_info_field($field);
+    if ($data['module'] == $scheme) {
+      foreach ($data['settings']['allowed_values'] as $key => $value) {
+        // Currently, only works for taxonomy.
+        if (!empty($settings[$value['vocabulary']])) {
+          $data['instance_info'] = $info;
+          $matches[$field] = $data;
+        }
+      }
+    }
+  }
+  return $matches;
+}
+
+/**
+ * Determines is the current path is an autocomplete request.
+ *
+ * @param $path
+ *  The active menu callback path.
+ * @param $page_arguments
+ *  The page arguments, which include the field, node type and text.
+ *
+ * @return
+ *  TRUE or FALSE, indicating that we should alter the query.
+ */
+function workbench_access_is_active_autocomplete($path, $page_arguments) {
+  if ($path != 'taxonomy/autocomplete' || empty($page_arguments[0]) || empty($page_arguments[1]) || empty($page_arguments[2])) {
+    return;
+  }
+  $field = $page_arguments[0];
+  $node_type = $page_arguments[1];
+  $tags_typed = $page_arguments[2];
+  $fields = workbench_access_get_assigned_fields($node_type);
+  if (isset($fields[$field])) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_query_TAG_alter().
+ *
+ * If this is a restricted taxonomy autocomplete query, add the conditions
+ * required by Workbench Access.
+ *
+ * @see taxonomy_autocomplete()
+ */
+function workbench_access_query_term_access_alter(QueryAlterableInterface $query) {
+  global $user;
+  $item = menu_get_item();
+  if (workbench_access_is_active_autocomplete($item['path'], $item['page_arguments'])) {
+    // Alter the query.
+    if (!isset($user->workbench_access)) {
+      workbench_access_user_load_data($user);
+    }
+    $tree = workbench_access_get_user_tree($user);
+    if (!empty($tree)) {
+      $query->condition('t.tid', array_keys($tree), 'IN');
+    }
+    // Force a NULL return.
+    else {
+      $query->condition('t.tid', -10);
+    }
+  }
+}
