diff --git a/src/TaxonomyPermissions.php b/src/TaxonomyPermissions.php
new file mode 100644
index 0000000..77ff36f
--- /dev/null
+++ b/src/TaxonomyPermissions.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Drupal\taxonomy_permissions;
+
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\taxonomy\Entity\Vocabulary;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Defines a class for dynamic permissions based on vocabularies.
+ */
+class TaxonomyPermissions implements ContainerInjectionInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructor.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static($container->get('entity_type.manager'));
+  }
+
+  /**
+   * Returns an array of transition permissions.
+   *
+   * @return array
+   *   The access protected permissions.
+   */
+  public function permissions() {
+
+    $perms = [];
+    $vocabularies = Vocabulary::loadMultiple();
+    /* @var \Drupal\taxonomy\Entity\Vocabulary $vocabulary */
+    foreach ($vocabularies as $id => $vocabulary) {
+      $perms['view terms in ' . $id] = [
+        'title' => $this->t('View terms in %label', [
+          '%label' => $vocabulary->label(),
+        ]),
+        'description' => $this->t('View the terms of %label vocabulary', [
+          '%label' => $vocabulary->label(),
+        ]),
+      ];
+    }
+
+    return $perms;
+  }
+
+}
diff --git a/src/TaxonomyPermissionsControlHandler.php b/src/TaxonomyPermissionsControlHandler.php
new file mode 100644
index 0000000..06f87f0
--- /dev/null
+++ b/src/TaxonomyPermissionsControlHandler.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\taxonomy_permissions;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityAccessControlHandler;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Defines the access control handler for the taxonomy term entity type.
+ *
+ * @see \Drupal\taxonomy\Entity\Term
+ */
+class TaxonomyPermissionsControlHandler extends EntityAccessControlHandler {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
+    switch ($operation) {
+      case 'view':
+        return AccessResult::allowedIfHasPermissions($account, ["view terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
+        break;
+
+      case 'create':
+        return AccessResult::allowedIfHasPermissions($account, ["create terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
+        break;
+
+      case 'update':
+        return AccessResult::allowedIfHasPermissions($account, ["edit terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
+        break;
+
+      case 'delete':
+        return AccessResult::allowedIfHasPermissions($account, ["delete terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
+        break;
+
+      default:
+        // No opinion.
+        return AccessResult::neutral();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
+    return AccessResult::allowedIfHasPermission($account, 'administer taxonomy');
+  }
+
+}
diff --git a/src/Tests/TaxonomyPermissionsTestBase.php b/src/Tests/TaxonomyPermissionsTestBase.php
new file mode 100644
index 0000000..b71d00d
--- /dev/null
+++ b/src/Tests/TaxonomyPermissionsTestBase.php
@@ -0,0 +1,394 @@
+<?php
+
+/**
+ * @file
+ * General setup and helper functions.
+ */
+
+namespace Drupal\taxonomy_permissions\Tests;
+
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Core\Entity\Entity\EntityFormDisplay;
+use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\simpletest\WebTestBase;
+use Drupal\taxonomy\Tests\TaxonomyTestTrait;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\taxonomy\VocabularyInterface;
+use Drupal\user\Entity\User;
+
+/**
+ * General setup and helper function for testing taxonomy permissions module.
+ *
+ * @group taxonomy_permissions
+ */
+class TaxonomyPermissionsTestBase extends WebTestBase {
+
+  use TaxonomyTestTrait;
+  /**
+   * Modules to install.
+   *
+   * @var array
+   */
+  public static $modules = array(
+    'system',
+    'user',
+    'node',
+    'field',
+    'field_ui',
+    'taxonomy',
+    'taxonomy_permissions',
+  );
+
+  /**
+   * Entity form display.
+   *
+   * @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface
+   */
+  protected $formDisplay;
+
+  /**
+   * Entity view display.
+   *
+   * @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface
+   */
+  protected $viewDisplay;
+
+  /**
+   * User with permission to view terms.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $authorizedUser;
+
+  /**
+   * Basic User without permissions to view terms.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $basicUser;
+
+  /**
+   * A node created.
+   *
+   * @var \Drupal\node\NodeInterface
+   */
+  protected $article1;
+
+  /**
+   * A node created.
+   *
+   * @var \Drupal\node\NodeInterface
+   */
+  protected $article2;
+
+  /**
+   * A vocabulary created.
+   *
+   * @var \Drupal\taxonomy\VocabularyInterface
+   */
+  protected $vocabulary;
+
+  /**
+   * A term created.
+   *
+   * @var \Drupal\taxonomy\TermInterface
+   */
+  protected $term1;
+
+  /**
+   * A term created.
+   *
+   * @var \Drupal\taxonomy\TermInterface
+   */
+  protected $term2;
+
+  /**
+   * Setup.
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Create vocabulary and terms.
+    $this->vocabulary = $this->createVocabulary();
+    $this->term1 = $this->createTerm($this->vocabulary);
+
+    // We remove standard permission provided by default.
+    $perms[] = 'view terms in ' . $this->vocabulary->id();
+    user_role_revoke_permissions(AccountInterface::ANONYMOUS_ROLE, $perms);
+    user_role_revoke_permissions(AccountInterface::AUTHENTICATED_ROLE, $perms);
+
+    $this->drupalCreateContentType(['type' => 'article']);
+
+    $this->authorizedUser = $this->drupalCreateUser([
+      'create article content',
+      'edit any article content',
+      'access content',
+      'view terms in ' . $this->vocabulary->id(),
+    ]);
+
+    $this->basicUser = $this->drupalCreateUser([
+      'create article content',
+      'edit any article content',
+      'access content',
+    ]);
+
+    $field_name = 'field_term';
+    $this->attachFields($field_name);
+
+    $this->article1 = $this->createSimpleArticle('Article 1', $field_name, $this->term1->id());
+  }
+
+  /**
+   * Tests if a user without permissions can view terms on node.
+   */
+  protected function testViewTerm() {
+
+    $this->drupalLogin($this->authorizedUser);
+    $this->drupalGet("node/{$this->article1->id()}");
+    $this->assertResponse(200);
+    $this->assertText($this->term1->getName());
+    $this->assertLink($this->term1->getName());
+
+    $this->drupalLogin($this->basicUser);
+    $this->drupalGet("node/{$this->article1->id()}");
+    $this->assertResponse(200);
+    $this->assertNoText($this->term1->getName());
+    $this->assertNoLink($this->term1->getName());
+  }
+
+  /**
+   * Tests if a user without permissions can access to term's page.
+   */
+  protected  function testAccessTermPage() {
+    $this->drupalLogin($this->authorizedUser);
+    $this->drupalGet("taxonomy/term/{$this->term1->id()}");
+    $this->assertResponse(200);
+
+    $this->drupalLogin($this->basicUser);
+    $this->drupalGet("taxonomy/term/{$this->term1->id()}");
+    $this->assertResponse(403);
+
+
+  }
+
+  /**
+   * Tests if a user without permissions can access to the field form.
+   */
+  protected  function testAccessFormTerm() {
+
+    $this->drupalLogin($this->authorizedUser);
+    $this->drupalGet("node/{$this->article1->id()}/edit");
+    $this->assertResponse(200);
+    $this->assertFieldByName('field_term[0][target_id]', $this->term1->getName() . ' (' . $this->term1->id() . ')', 'The expected value is found in the input field');
+
+    $this->drupalLogin($this->basicUser);
+    $this->drupalGet("node/{$this->article1->id()}/edit");
+    $this->assertResponse(200);
+    $this->assertNoFieldByName('field_term[0][target_id]', $this->term1->getName() . ' (' . $this->term1->id() . ')', 'The input field taxonomy reference is not accessible');
+
+  }
+
+  /**
+   * Creates a taxonomy term reference field on the specified bundle.
+   *
+   * @param string $entity_type
+   *   The type of entity the field will be attached to.
+   * @param string $bundle
+   *   The bundle name of the entity the field will be attached to.
+   * @param string $field_name
+   *   The name of the field; if it already exists, a new instance of existing
+   *   field will be created.
+   * @param string $field_label
+   *   The label of the field.
+   * @param string $target_entity_type
+   *   The type of the referenced entity.
+   * @param string $selection_handler
+   *   The selection handler used by this field.
+   * @param array $selection_handler_settings
+   *   An array of settings supported by the selection handler specified above.
+   *   (e.g. 'target_bundles', 'sort', 'auto_create', etc).
+   * @param int $cardinality
+   *   The cardinality of the field.
+   * @param string $user_method
+   *   The method used for granting access to user.
+   * @param int $priority
+   *   The priority access.
+   *
+   * @return \Drupal\field\Entity\FieldConfig $field
+   *   The field created or loaded.
+   *
+   * @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase::buildConfigurationForm()
+   */
+  protected function createField($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = array(), $cardinality = 1, $user_method = 'user', $priority = 0) {
+    // Look for or add the specified field to the requested entity bundle.
+    if (!FieldStorageConfig::loadByName($entity_type, $field_name)) {
+      FieldStorageConfig::create(array(
+        'field_name' => $field_name,
+        'type' => 'entity_reference',
+        'entity_type' => $entity_type,
+        'cardinality' => $cardinality,
+        'settings' => array(
+          'target_type' => $target_entity_type,
+        ),
+      ))->save();
+    }
+    if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) {
+      FieldConfig::create(array(
+        'field_name' => $field_name,
+        'entity_type' => $entity_type,
+        'bundle' => $bundle,
+        'label' => $field_label,
+        'settings' => array(
+          'handler' => $selection_handler,
+          'handler_settings' => $selection_handler_settings,
+        ),
+      ))->save();
+    }
+    $field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
+    return $field;
+  }
+
+  /**
+   * Set the widget for a component in a form display.
+   *
+   * @param string $form_display_id
+   *   The form display id.
+   * @param string $entity_type
+   *   The entity type name.
+   * @param string $bundle
+   *   The bundle name.
+   * @param string $field_name
+   *   The field name to set.
+   * @param string $widget_id
+   *   The widget id to set.
+   * @param array $settings
+   *   The settings of widget.
+   * @param string $mode
+   *   The mode name.
+   */
+  protected function setFormDisplay($form_display_id, $entity_type, $bundle, $field_name, $widget_id, $settings, $mode = 'default') {
+    // Set article's form display.
+    $this->formDisplay = EntityFormDisplay::load($form_display_id);
+
+    if (!$this->formDisplay) {
+      EntityFormDisplay::create([
+        'targetEntityType' => $entity_type,
+        'bundle' => $bundle,
+        'mode' => $mode,
+        'status' => TRUE,
+      ])->save();
+      $this->formDisplay = EntityFormDisplay::load($form_display_id);
+    }
+    if ($this->formDisplay instanceof EntityFormDisplayInterface) {
+      $this->formDisplay->setComponent($field_name, [
+        'type' => $widget_id,
+        'settings' => $settings,
+      ])->save();
+    }
+  }
+
+  /**
+   * Set the widget for a component in a View display.
+   *
+   * @param string $form_display_id
+   *   The form display id.
+   * @param string $entity_type
+   *   The entity type name.
+   * @param string $bundle
+   *   The bundle name.
+   * @param string $field_name
+   *   The field name to set.
+   * @param string $formatter_id
+   *   The formatter id to set.
+   * @param array $settings
+   *   The settings of widget.
+   * @param string $mode
+   *   The mode name.
+   */
+  protected function setViewDisplay($form_display_id, $entity_type, $bundle, $field_name, $formatter_id, $settings, $mode = 'default') {
+    // Set article's view display.
+    $this->viewDisplay = EntityViewDisplay::load($form_display_id);
+    if (!$this->viewDisplay) {
+      EntityViewDisplay::create([
+        'targetEntityType' => $entity_type,
+        'bundle' => $bundle,
+        'mode' => $mode,
+        'status' => TRUE,
+      ])->save();
+      $this->viewDisplay = EntityViewDisplay::load($form_display_id);
+    }
+    if ($this->viewDisplay instanceof EntityViewDisplayInterface) {
+      $this->viewDisplay->setComponent($field_name, [
+        'type' => $formatter_id,
+        'settings' => $settings,
+      ])->save();
+    }
+
+  }
+
+  /**
+   * Helper function to create and attach a field to a node.
+   *
+   * @param string $field_name
+   *   The field name to create and attach.
+   */
+  protected function attachFields($field_name) {
+    // Add a field to the article content type which reference term.
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
+      ),
+      'auto_create' => FALSE,
+    );
+
+    $this->createField('node', 'article', $field_name, 'Term referenced', 'taxonomy_term', 'default', $handler_settings);
+
+    // Set the form display.
+    $settings = [
+      'match_operator' => 'CONTAINS',
+      'size' => 30,
+      'placeholder' => '',
+    ];
+    $this->setFormDisplay('node.article.default', 'node', 'article', $field_name, 'entity_reference_autocomplete', $settings);
+
+    // Set the view display.
+    $settings = [
+      'link' => TRUE,
+    ];
+    $this->setViewDisplay('node.article.default', 'node', 'article', $field_name, 'entity_reference_label', $settings);
+
+  }
+
+  /**
+   * Create an article with value for field field_term.
+   *
+   * @param string $title
+   *   The content title.
+   * @param string $field_name
+   *   The Pbf field name to populate.
+   * @param int|string $target_id
+   *   The target id of taxonomy term.
+   *
+   * @return \Drupal\node\NodeInterface
+   *   The node created.
+   */
+  protected function createSimpleArticle($title, $field_name = '', $target_id = NULL) {
+    $values = array(
+      'type' => 'article',
+      'title' => $title,
+      'body' => [
+        'value' => 'Content body for ' . $title,
+      ],
+    );
+    if ($field_name) {
+      $values[$field_name] = [
+        'target_id' => $target_id,
+      ];
+    }
+    return $this->drupalCreateNode($values);
+  }
+
+}
diff --git a/taxonomy_permissions.info b/taxonomy_permissions.info
deleted file mode 100644
index a8f1e64..0000000
--- a/taxonomy_permissions.info
+++ /dev/null
@@ -1,8 +0,0 @@
-name = Taxonomy Permissions
-description = Adds the missing 'view' permissions to the Taxonomy module.
-dependencies[] = taxonomy
-package = Other
-core = 7.x
-
-files[] = tests/taxonomy_permissions.test
-
diff --git a/taxonomy_permissions.info.yml b/taxonomy_permissions.info.yml
new file mode 100644
index 0000000..c53f969
--- /dev/null
+++ b/taxonomy_permissions.info.yml
@@ -0,0 +1,7 @@
+name: Taxonomy Permissions
+description: Adds the missing 'view' permissions to the Taxonomy module.
+type: module
+dependencies:
+  - taxonomy
+package: Other
+core: 8.x
diff --git a/taxonomy_permissions.install b/taxonomy_permissions.install
index a4058bb..ce31a4a 100644
--- a/taxonomy_permissions.install
+++ b/taxonomy_permissions.install
@@ -3,48 +3,25 @@
 /**
  * @file
  * Install, update and uninstall functions for the taxonomy_permissions module.
- *
  */
 
-/*
+use Drupal\Core\Session\AccountInterface;
+use Drupal\taxonomy\Entity\Vocabulary;
+
+/**
  * Implements hook_install().
  *
  * Give 'view terms' access to all vocabularies to all users to avoid surprises
  * upon installation.
  */
 function taxonomy_permissions_install() {
-  $perms = array();
-  foreach (taxonomy_get_vocabularies() as $vocabulary) {
-    $perms[] = 'view terms in ' . $vocabulary->vid;
+  $perms = [];
+  $vocabularies = Vocabulary::loadMultiple();
+  foreach ($vocabularies as $id => $vocabulary) {
+    $perms[] = 'view terms in ' . $id;
   }
-  user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, $perms);
-  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, $perms);
-}
-
-/*
- * Implements hook_disable().
- */
-function taxonomy_permissions_disable() {
-  // Re-register taxonomy.module's permissions under its own name to keep them
-  // from being purged in case we're uninstalled.
-  taxonomy_permissions_disabling(TRUE);
-  module_implements('permission', FALSE, TRUE);
-  cache_clear_all('module_implements', 'cache_bootstrap');
-  $modules = user_permission_get_modules();
-  $perms = user_role_permissions(user_roles());
-  foreach ($perms as $rid => $perm) {
-    foreach (array_keys($perm) as $p) {
-      if (!isset($modules[$p]) || $modules[$p] != 'taxonomy') {
-        unset($perm[$p]);
-      }
-    }
-    user_role_change_permissions($rid, $perm);
+  if ($perms) {
+    user_role_grant_permissions(AccountInterface::ANONYMOUS_ROLE, $perms);
+    user_role_grant_permissions(AccountInterface::AUTHENTICATED_ROLE, $perms);
   }
 }
-
-/*
- * Implements hook_uninstall().
- */
-function taxonomy_permissions_uninstall() {
-}
-
diff --git a/taxonomy_permissions.module b/taxonomy_permissions.module
index 49791e0..3b8e142 100644
--- a/taxonomy_permissions.module
+++ b/taxonomy_permissions.module
@@ -5,121 +5,89 @@
  * taxonomy_permissions.module
  *
  * This module adds 'view' permissions to the Taxonomy core module.
- *
  */
 
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Access\AccessResult;
+
 /**
- * Implements hook_module_implements_alter().
+ * Implements hook_help().
  */
-function taxonomy_permissions_module_implements_alter(&$implementations, $hook) {
-  // Remove taxonomy.module's permissions because we supply them.
-  if ($hook == 'permission') {
-    if (taxonomy_permissions_disabling()) {
-      unset($implementations['taxonomy_permissions']);
-    }
-    else {
-      unset($implementations['taxonomy']);
-    }
+function taxonomy_permissions_help($route_name, RouteMatchInterface $route_match) {
+  switch ($route_name) {
+    case 'help.page.taxonomy_permissions':
+      $output = '';
+      $output .= '<h3>' . t("About") . '</h3>';
+      $output .= '<p>' . t("Taxonomy Permissions adds 'view terms in
+      %vocabulary%' permissions to the list of permissions of the Taxonomy
+      core module.") . '</p>';
+      $output .= '<p>' . t("To avoid surprises, vocabularies are visible by
+      authenticated and anonymous users by default. You have to change the
+      permissions to see any effect of this module.") . '</p>';
+      return $output;
+
+    default:
   }
 }
 
 /**
- * Implements hook_permission().
+ * Implements hook_entity_type_alter().
  */
-function taxonomy_permissions_permission() {
-  // Insert a 'View terms in X' permission ahead of every 'Edit terms in X'
-  // permission from taxonomy.module.
-  $perms = taxonomy_permission();
-  $vocabularies = taxonomy_get_vocabularies();
-  $new_perms = array();
-  $matches = array();
-  foreach ($perms as $key => $perm) {
-    if (preg_match('#edit terms in ([0-9]*)#',$key, $matches)) {
-      $vid = $matches[1];
-      $new_perms['view terms in ' . $vid] = array(
-        'title' => t('View terms in %vocabulary', array('%vocabulary' => $vocabularies[$vid]->name)),
-      );
-    }
-    $new_perms[$key] = $perm;
-  }
-  return $new_perms;
+function taxonomy_permissions_entity_type_alter(array &$entity_types) {
+  /* @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
+  $entity_types['taxonomy_term']->setAccessClass('Drupal\taxonomy_permissions\TaxonomyPermissionsControlHandler');
 }
 
 /**
- * Implements hook_query_term_access_alter().
+ * Implements hook_entity_field_access().
  */
-function taxonomy_permissions_query_term_access_alter(QueryAlterableInterface $query) {
-  global $user;
-  $uid = $user->uid;
+function taxonomy_permissions_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
+  if ($field_definition->getType() == 'entity_reference' &&
+    $field_definition->getSetting('target_type') == 'taxonomy_term' &&
+    $operation == 'edit') {
 
-  $vids_by_user = &drupal_static(__FUNCTION__, array());
-  if (!isset($vids_by_user[$uid])) {
-    // Save the vids that $user is allowed to access.
-    $vids = array();
-    $vocabularies = taxonomy_get_vocabularies();
-    foreach ($vocabularies as $vid => $vocabulary) {
-      if (user_access('view terms in ' . $vocabulary->vid)) {
-        $vids[] = $vid;
+    $handler_settings = $field_definition->getSetting('handler_settings');
+    $target_bundles = $handler_settings['target_bundles'];
+    // We grant access to the taxonomy reference field if the user has the
+    // permissions to view at least one vocabulary from the target bundles.
+    $access = FALSE;
+    foreach ($target_bundles as $vid => $target_bundle) {
+      if ($account->hasPermission('view terms in ' . $vid)) {
+        $access = TRUE;
       }
     }
-    $vids_by_user[$uid] = $vids;
-  }
-
-  // Restrict {taxonomy_term_data} to the allowed vocabularies only.
-  $tables = $query->getTables();
-  foreach ($tables as $table) {
-    if ($table['table'] == 'taxonomy_term_data') {
-      $or = db_or();
-      $or->condition($table['alias'] . '.vid', $vids_by_user[$uid], 'IN');
-      $or->isNull($table['alias'] . '.vid');
-      $query->condition($or);
+    if ($access) {
+      return AccessResult::allowed();
     }
-  }
-}
-
-/**
- * Implements hook_field_access().
- */
-function taxonomy_permissions_field_access($op, $field, $entity_type, $entity, $account) {
-  // Remove taxonomy_term_reference fields for disallowed vocabularies.
-  if ($field['type'] == 'taxonomy_term_reference') {
-    foreach ($field['settings']['allowed_values'] as $tree) {
-      if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
-        if (!user_access('view terms in ' . $vocabulary->vid, $account)) {
-          return FALSE;
-        }
-      }
+    else {
+      return AccessResult::forbidden();
     }
   }
+  return AccessResult::neutral();
 }
 
 /**
- * Implements hook_taxonomy_vocabulary_insert().
- */
-function taxonomy_permissions_taxonomy_vocabulary_insert($vocabulary) {
-  $perms[] = 'view terms in ' . $vocabulary->vid;
-  user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, $perms);
-  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, $perms);
-}
-
-/**
- * Implements hook_taxonomy_vocabulary_delete().
+ * Implements hook_entity_insert().
  */
-function taxonomy_permissions_taxonomy_vocabulary_delete($vocabulary) {
-  $perms[] = 'view terms in ' . $vocabulary->vid;
-  user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, $perms);
-  user_role_revoke_permissions(DRUPAL_AUTHENTICATED_RID, $perms);
+function taxonomy_permissions_entity_insert(EntityInterface $entity) {
+  if ($entity->getEntityTypeId() == 'taxonomy_vocabulary') {
+    $perms[] = 'view terms in ' . $entity->id();
+    user_role_grant_permissions(AccountInterface::ANONYMOUS_ROLE, $perms);
+    user_role_grant_permissions(AccountInterface::AUTHENTICATED_ROLE, $perms);
+  }
 }
 
 /**
- * Remembers if we have disabled access.
+ * Implements hook_entity_delete().
  */
-function taxonomy_permissions_disabling($set = NULL) {
-  static $disabling = FALSE;
-
-  if (isset($set)) {
-    $disabling = $set;
+function taxonomy_permissions_entity_delete(EntityInterface $entity) {
+  if ($entity->getEntityTypeId() == 'taxonomy_vocabulary') {
+    $perms[] = 'view terms in ' . $entity->id();
+    user_role_revoke_permissions(AccountInterface::ANONYMOUS_ROLE, $perms);
+    user_role_revoke_permissions(AccountInterface::AUTHENTICATED_ROLE, $perms);
   }
-  return $disabling;
 }
-
diff --git a/taxonomy_permissions.permissions.yml b/taxonomy_permissions.permissions.yml
new file mode 100644
index 0000000..60ef7e8
--- /dev/null
+++ b/taxonomy_permissions.permissions.yml
@@ -0,0 +1,2 @@
+permission_callbacks:
+  - \Drupal\taxonomy_permissions\TaxonomyPermissions::permissions
diff --git a/tests/taxonomy_permissions.test b/tests/taxonomy_permissions.test
deleted file mode 100644
index 61335fa..0000000
--- a/tests/taxonomy_permissions.test
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- * @file
- * Tests for the Taxonomy Permissions module.
- */
-
-/**
- * Test case for Taxonomy Permissions module.
- */
-class TaxonomyPermissionsWebTestCase extends DrupalWebTestCase {
-
-  /**
-   * Implements getInfo().
-   *
-   * @return array
-   */
-  public static function getInfo() {
-    return array(
-      'name' => 'Taxonomy Permissions Test',
-      'description' => "This is a dummy test to keep d.o's testbot happy; real tests are welcome!",
-      'group' => 'Taxonomy Permissions',
-    );
-  }
-
-  /**
-   * Dummy test that always succeeds.
-   */
-  function testTrue() {
-    $this->assertTrue(TRUE);
-  }
-
-
-}
-
