diff --git a/entity_clone.info.yml b/entity_clone.info.yml
index 7e8c6ac..77a1100 100644
--- a/entity_clone.info.yml
+++ b/entity_clone.info.yml
@@ -1,6 +1,6 @@
 name: Entity Clone
 description: Add a clone action for all entities
-core_version_requirement: ^10.3 || ^11
+core_version_requirement: ^11.4 || ^12
 type: module
 configure: entity_clone.settings
 package: 'Entity Clone'
diff --git a/entity_clone.module b/entity_clone.module
index d331867..4fd3ead 100644
--- a/entity_clone.module
+++ b/entity_clone.module
@@ -5,108 +5,26 @@
  * Contains entity_clone.module.
  */
 
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
-use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\entity_clone\Hook\EntityCloneHooks;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\entity_clone\EntityClone\Config\ConfigEntityCloneBase;
-use Drupal\entity_clone\EntityClone\Config\ConfigEntityCloneFormBase;
-use Drupal\entity_clone\EntityClone\Config\ConfigWithFieldEntityClone;
-use Drupal\entity_clone\EntityClone\Config\FieldConfigEntityClone;
-use Drupal\entity_clone\EntityClone\Config\LayoutBuilderEntityClone;
-use Drupal\entity_clone\EntityClone\Config\MenuEntityClone;
-use Drupal\entity_clone\EntityClone\Config\MenuEntityCloneForm;
-use Drupal\entity_clone\EntityClone\Content\ContentEntityCloneBase;
-use Drupal\entity_clone\EntityClone\Content\ContentEntityCloneFormBase;
-use Drupal\entity_clone\EntityClone\Content\FileEntityClone;
-use Drupal\entity_clone\EntityClone\Content\TaxonomyTermEntityClone;
-use Drupal\entity_clone\EntityClone\Content\UserEntityClone;
 
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function entity_clone_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    // Main module help for the entity_clone module.
-    case 'help.page.entity_clone':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('Provides a new operation to clone all Entities.') . '</p>';
-      return $output;
-
-    default:
-      return;
-
-  }
+  return \Drupal::service(EntityCloneHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_entity_type_build().
  */
+#[LegacyHook]
 function entity_clone_entity_type_build(array &$entity_types) {
-  $specific_handler = [
-    'file' => [
-      'entity_clone' => FileEntityClone::class,
-    ],
-    'user' => [
-      'entity_clone' => UserEntityClone::class,
-    ],
-    'field_config' => [
-      'entity_clone' => FieldConfigEntityClone::class,
-    ],
-    'node_type' => [
-      'entity_clone' => ConfigWithFieldEntityClone::class,
-    ],
-    'comment_type' => [
-      'entity_clone' => ConfigWithFieldEntityClone::class,
-    ],
-    'block_content_type' => [
-      'entity_clone' => ConfigWithFieldEntityClone::class,
-    ],
-    'contact_form' => [
-      'entity_clone' => ConfigWithFieldEntityClone::class,
-    ],
-    'taxonomy_term' => [
-      'entity_clone' => TaxonomyTermEntityClone::class,
-    ],
-    'menu' => [
-      'entity_clone_form' => MenuEntityCloneForm::class,
-      'entity_clone' => MenuEntityClone::class,
-    ],
-    'taxonomy_vocabulary' => [
-      'entity_clone' => ConfigWithFieldEntityClone::class,
-    ],
-    'entity_view_display' => [
-      'entity_clone' => \Drupal::moduleHandler()->moduleExists('layout_builder') ? LayoutBuilderEntityClone::class : NULL,
-    ],
-  ];
-
-  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
-  foreach ($entity_types as $entity_type_id => $entity_type) {
-    $has_entity_clone_handler = $entity_type->getHandlerClass('entity_clone');
-    if (!$has_entity_clone_handler) {
-      if ($entity_type instanceof ContentEntityTypeInterface) {
-        $entity_type->setHandlerClass('entity_clone', ContentEntityCloneBase::class);
-        $entity_type->setHandlerClass('entity_clone_form', ContentEntityCloneFormBase::class);
-      }
-      elseif ($entity_type instanceof ConfigEntityTypeInterface) {
-        $entity_type->setHandlerClass('entity_clone', ConfigEntityCloneBase::class);
-        $entity_type->setHandlerClass('entity_clone_form', ConfigEntityCloneFormBase::class);
-      }
-    }
-
-    if (isset($specific_handler[$entity_type->id()]['entity_clone'])) {
-      $entity_type->setHandlerClass('entity_clone', $specific_handler[$entity_type->id()]['entity_clone']);
-    }
-    if (isset($specific_handler[$entity_type->id()]['entity_clone_form'])) {
-      $entity_type->setHandlerClass('entity_clone_form', $specific_handler[$entity_type->id()]['entity_clone_form']);
-    }
-
-    $entity_type->setLinkTemplate('clone-form', "/entity_clone/$entity_type_id/{{$entity_type_id}}");
-  }
+  \Drupal::service(EntityCloneHooks::class)->entityTypeBuild($entity_types);
 }
 
 /**
@@ -139,62 +57,7 @@ function entity_clone_entity_operation(EntityInterface $entity) {
 /**
  * Implements hook_entity_access().
  */
+#[LegacyHook]
 function entity_clone_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
-  if ($operation !== 'clone') {
-    return AccessResult::neutral();
-  }
-
-  $cache = new CacheableMetadata();
-
-  // Check the cloneable entities config and deny access if the entity is not
-  // enabled.
-  $cloneable_entities = \Drupal::configFactory()->get('entity_clone.cloneable_entities');
-  $cache->addCacheTags($cloneable_entities->getCacheTags());
-  $cloneable_entities = $cloneable_entities->get('cloneable_entities') ?? [];
-  if (!in_array($entity->getEntityTypeId(), $cloneable_entities)) {
-    return AccessResult::forbidden()->addCacheableDependency($cache);
-  }
-
-  $cache->addCacheContexts(['user.permissions']);
-
-  // Deny access if the user cannot clone the entity.
-  $access = AccessResult::forbiddenIf(
-    !$account->hasPermission('clone ' . $entity->getEntityTypeId() . ' entity')
-    &&
-    !$account->hasPermission('clone ' . $entity->bundle() . ' ' . $entity->getEntityTypeId() . ' entities')
-  );
-  if ($access->isForbidden()) {
-    return $access->addCacheableDependency($cache);
-  }
-
-  // Deny access if the user can clone but cannot create new entities of this
-  // type. However, we have some exceptions in which the access control handler
-  // doesn't have a say in things. In these cases, we go based on the clone
-  // permission only.
-  $exceptions = [
-    'file',
-    'paragraph',
-  ];
-
-  if (in_array($entity->getEntityTypeId(), $exceptions)) {
-    return AccessResult::allowed()->addCacheableDependency($cache);
-  }
-
-  $handler = \Drupal::entityTypeManager()->getAccessControlHandler($entity->getEntityTypeId());
-  // Prepare the context.
-  $context = [];
-  // Handle specific context elements.
-  if ($entity->getEntityTypeId() == 'group_content') {
-    // Group content must have a specific context item.
-    $context['group'] = $entity->getGroup();
-  }
-  // Check access.
-  $access = $handler->createAccess($entity->bundle(), $account, $context, TRUE);
-  if (!$access->isAllowed()) {
-    $cache->addCacheableDependency($access);
-    $forbidden = AccessResult::forbidden();
-    return $forbidden->addCacheableDependency($cache);
-  }
-
-  return AccessResult::allowed()->addCacheableDependency($cache);
+  return \Drupal::service(EntityCloneHooks::class)->entityAccess($entity, $operation, $account);
 }
diff --git a/entity_clone.services.yml b/entity_clone.services.yml
index 8f78a9e..e10d787 100644
--- a/entity_clone.services.yml
+++ b/entity_clone.services.yml
@@ -23,3 +23,7 @@ services:
   entity_clone.clonable_field:
     class: Drupal\entity_clone\EntityCloneClonableField
     arguments: ['@entity_type.manager']
+
+  Drupal\entity_clone\Hook\EntityCloneHooks:
+    class: Drupal\entity_clone\Hook\EntityCloneHooks
+    autowire: true
diff --git a/modules/entity_clone_extras/entity_clone_extras.info.yml b/modules/entity_clone_extras/entity_clone_extras.info.yml
index d2ca90a..d899d50 100644
--- a/modules/entity_clone_extras/entity_clone_extras.info.yml
+++ b/modules/entity_clone_extras/entity_clone_extras.info.yml
@@ -1,7 +1,7 @@
 name: 'Entity Clone Extras'
 type: module
 description: 'Allow for bundle-level permissions for Node (and Media) entity types'
-core_version_requirement: ^10.3 || ^11
+core_version_requirement: ^11.4 || ^12
 package: 'Entity Clone'
 dependencies:
   - drupal:entity_clone
diff --git a/modules/entity_clone_extras/entity_clone_extras.module b/modules/entity_clone_extras/entity_clone_extras.module
index e2336b1..74e9468 100644
--- a/modules/entity_clone_extras/entity_clone_extras.module
+++ b/modules/entity_clone_extras/entity_clone_extras.module
@@ -5,7 +5,8 @@
  * Contains entity_clone_extras.module.
  */
 
-use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\entity_clone_extras\Hook\EntityCloneExtrasHooks;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -13,53 +14,25 @@ use Drupal\Core\Session\AccountInterface;
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function entity_clone_extras_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    // Main module help for the entity_clone_extras module.
-    case 'help.page.entity_clone_extras':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('Allow for bundle-level permissions for Node (and Media) entity types') . '</p>';
-      return $output;
-
-    default:
-  }
+  return \Drupal::service(EntityCloneExtrasHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_entity_operation_alter().
  */
+#[LegacyHook]
 function entity_clone_extras_entity_operation_alter(array &$operations, EntityInterface $entity) {
-  // Check if entity type supports cloning:
-  if ($entity->hasLinkTemplate('clone-form')) {
-    // If it does, get the current user.
-    $user = \Drupal::currentUser();
-    $entity_types = entity_clone_extras_supported_entity_types();
-    if (in_array($entity->getEntityTypeId(), $entity_types)) {
-      if (!$user->hasPermission('clone ' . $entity->getEntityTypeId() . ' entity')) {
-        // If we are dealing with a supported entity type, we handle permissions
-        // per bundle.
-        $bundle = $entity->bundle();
-        $entity_type = $entity->getEntityTypeId();
-        // Check the bundle access.
-        if (!$user->hasPermission("clone $bundle $entity_type entities")) {
-          // Remove the operation if the user has no access to it.
-          unset($operations['clone']);
-        }
-      }
-    }
-  }
+  \Drupal::service(EntityCloneExtrasHooks::class)->entityOperationAlter($operations, $entity);
 }
 
 /**
  * Implements hook_entity_access().
  */
+#[LegacyHook]
 function entity_clone_extras_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
-  $entity_types = entity_clone_extras_supported_entity_types();
-  if ($operation === 'clone' && in_array($entity->getEntityTypeId(), $entity_types)) {
-    return AccessResult::allowedIfHasPermission($account, 'clone ' . $entity->bundle() . ' ' . $entity->getEntityTypeId() . ' entities');
-  }
-  return AccessResult::neutral();
+  return \Drupal::service(EntityCloneExtrasHooks::class)->entityAccess($entity, $operation, $account);
 }
 
 /**
diff --git a/modules/entity_clone_extras/entity_clone_extras.services.yml b/modules/entity_clone_extras/entity_clone_extras.services.yml
new file mode 100644
index 0000000..a073b2b
--- /dev/null
+++ b/modules/entity_clone_extras/entity_clone_extras.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\entity_clone_extras\Hook\EntityCloneExtrasHooks:
+    class: Drupal\entity_clone_extras\Hook\EntityCloneExtrasHooks
+    autowire: true
diff --git a/modules/entity_clone_extras/src/Hook/EntityCloneExtrasHooks.php b/modules/entity_clone_extras/src/Hook/EntityCloneExtrasHooks.php
new file mode 100644
index 0000000..5425e56
--- /dev/null
+++ b/modules/entity_clone_extras/src/Hook/EntityCloneExtrasHooks.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Drupal\entity_clone_extras\Hook;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for entity_clone_extras.
+ */
+class EntityCloneExtrasHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match) {
+    switch ($route_name) {
+      // Main module help for the entity_clone_extras module.
+      case 'help.page.entity_clone_extras':
+        $output = '';
+        $output .= '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('Allow for bundle-level permissions for Node (and Media) entity types') . '</p>';
+        return $output;
+
+      default:
+    }
+  }
+
+  /**
+   * Implements hook_entity_operation_alter().
+   */
+  #[Hook('entity_operation_alter')]
+  public static function entityOperationAlter(array &$operations, EntityInterface $entity) {
+    // Check if entity type supports cloning:
+    if ($entity->hasLinkTemplate('clone-form')) {
+      // If it does, get the current user.
+      $user = \Drupal::currentUser();
+      $entity_types = entity_clone_extras_supported_entity_types();
+      if (in_array($entity->getEntityTypeId(), $entity_types)) {
+        if (!$user->hasPermission('clone ' . $entity->getEntityTypeId() . ' entity')) {
+          // If we are dealing with a supported entity type, we handle permissions
+          // per bundle.
+          $bundle = $entity->bundle();
+          $entity_type = $entity->getEntityTypeId();
+          // Check the bundle access.
+          if (!$user->hasPermission("clone {$bundle} {$entity_type} entities")) {
+            // Remove the operation if the user has no access to it.
+            unset($operations['clone']);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Implements hook_entity_access().
+   */
+  #[Hook('entity_access')]
+  public static function entityAccess(EntityInterface $entity, $operation, AccountInterface $account) {
+    $entity_types = entity_clone_extras_supported_entity_types();
+    if ($operation === 'clone' && in_array($entity->getEntityTypeId(), $entity_types)) {
+      return AccessResult::allowedIfHasPermission($account, 'clone ' . $entity->bundle() . ' ' . $entity->getEntityTypeId() . ' entities');
+    }
+    return AccessResult::neutral();
+  }
+
+}
diff --git a/src/EntityClone/Content/FileEntityClone.php b/src/EntityClone/Content/FileEntityClone.php
index 83140a6..f68ed3b 100644
--- a/src/EntityClone/Content/FileEntityClone.php
+++ b/src/EntityClone/Content/FileEntityClone.php
@@ -2,11 +2,11 @@
 
 namespace Drupal\entity_clone\EntityClone\Content;
 
+use Drupal\Core\File\FileExists;
 use Drupal\Component\Datetime\TimeInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\entity_clone\EntityCloneClonableFieldInterface;
@@ -77,7 +77,7 @@ class FileEntityClone extends ContentEntityCloneBase {
   public function cloneEntity(EntityInterface $entity, EntityInterface $cloned_entity, array $properties = [], array &$already_cloned = []) {
     /** @var \Drupal\file\FileInterface $cloned_entity */
     // @phpstan-ignore-next-line as it is removed from D12.
-    $cloned_file = $this->fileRepository->copy($cloned_entity, $cloned_entity->getFileUri(), FileSystemInterface::EXISTS_RENAME);
+    $cloned_file = $this->fileRepository->copy($cloned_entity, $cloned_entity->getFileUri(), FileExists::Rename);
     if (isset($properties['take_ownership']) && $properties['take_ownership'] === 1) {
       $cloned_file->setOwnerId($this->user->id());
     }
diff --git a/src/Hook/EntityCloneHooks.php b/src/Hook/EntityCloneHooks.php
new file mode 100644
index 0000000..64c4398
--- /dev/null
+++ b/src/Hook/EntityCloneHooks.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace Drupal\entity_clone\Hook;
+
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\entity_clone\EntityClone\Config\ConfigEntityCloneFormBase;
+use Drupal\entity_clone\EntityClone\Config\ConfigEntityCloneBase;
+use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
+use Drupal\entity_clone\EntityClone\Content\ContentEntityCloneFormBase;
+use Drupal\entity_clone\EntityClone\Content\ContentEntityCloneBase;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\entity_clone\EntityClone\Config\LayoutBuilderEntityClone;
+use Drupal\entity_clone\EntityClone\Config\MenuEntityClone;
+use Drupal\entity_clone\EntityClone\Config\MenuEntityCloneForm;
+use Drupal\entity_clone\EntityClone\Content\TaxonomyTermEntityClone;
+use Drupal\entity_clone\EntityClone\Config\ConfigWithFieldEntityClone;
+use Drupal\entity_clone\EntityClone\Config\FieldConfigEntityClone;
+use Drupal\entity_clone\EntityClone\Content\UserEntityClone;
+use Drupal\entity_clone\EntityClone\Content\FileEntityClone;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for entity_clone.
+ */
+class EntityCloneHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match) {
+    switch ($route_name) {
+      // Main module help for the entity_clone module.
+      case 'help.page.entity_clone':
+        $output = '';
+        $output .= '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('Provides a new operation to clone all Entities.') . '</p>';
+        return $output;
+
+      default:
+        return;
+    }
+  }
+
+  /**
+   * Implements hook_entity_type_build().
+   */
+  #[Hook('entity_type_build')]
+  public static function entityTypeBuild(array &$entity_types) {
+    $specific_handler = [
+      'file' => [
+        'entity_clone' => FileEntityClone::class,
+      ],
+      'user' => [
+        'entity_clone' => UserEntityClone::class,
+      ],
+      'field_config' => [
+        'entity_clone' => FieldConfigEntityClone::class,
+      ],
+      'node_type' => [
+        'entity_clone' => ConfigWithFieldEntityClone::class,
+      ],
+      'comment_type' => [
+        'entity_clone' => ConfigWithFieldEntityClone::class,
+      ],
+      'block_content_type' => [
+        'entity_clone' => ConfigWithFieldEntityClone::class,
+      ],
+      'contact_form' => [
+        'entity_clone' => ConfigWithFieldEntityClone::class,
+      ],
+      'taxonomy_term' => [
+        'entity_clone' => TaxonomyTermEntityClone::class,
+      ],
+      'menu' => [
+        'entity_clone_form' => MenuEntityCloneForm::class,
+        'entity_clone' => MenuEntityClone::class,
+      ],
+      'taxonomy_vocabulary' => [
+        'entity_clone' => ConfigWithFieldEntityClone::class,
+      ],
+      'entity_view_display' => [
+        'entity_clone' => \Drupal::moduleHandler()->moduleExists('layout_builder') ? LayoutBuilderEntityClone::class : NULL,
+      ],
+    ];
+    /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
+    foreach ($entity_types as $entity_type_id => $entity_type) {
+      $has_entity_clone_handler = $entity_type->getHandlerClass('entity_clone');
+      if (!$has_entity_clone_handler) {
+        if ($entity_type instanceof ContentEntityTypeInterface) {
+          $entity_type->setHandlerClass('entity_clone', ContentEntityCloneBase::class);
+          $entity_type->setHandlerClass('entity_clone_form', ContentEntityCloneFormBase::class);
+        }
+        elseif ($entity_type instanceof ConfigEntityTypeInterface) {
+          $entity_type->setHandlerClass('entity_clone', ConfigEntityCloneBase::class);
+          $entity_type->setHandlerClass('entity_clone_form', ConfigEntityCloneFormBase::class);
+        }
+      }
+      if (isset($specific_handler[$entity_type->id()]['entity_clone'])) {
+        $entity_type->setHandlerClass('entity_clone', $specific_handler[$entity_type->id()]['entity_clone']);
+      }
+      if (isset($specific_handler[$entity_type->id()]['entity_clone_form'])) {
+        $entity_type->setHandlerClass('entity_clone_form', $specific_handler[$entity_type->id()]['entity_clone_form']);
+      }
+      $entity_type->setLinkTemplate('clone-form', "/entity_clone/{$entity_type_id}/{{$entity_type_id}}");
+    }
+  }
+
+  /**
+   * Implements hook_entity_access().
+   */
+  #[Hook('entity_access')]
+  public static function entityAccess(EntityInterface $entity, $operation, AccountInterface $account) {
+    if ($operation !== 'clone') {
+      return AccessResult::neutral();
+    }
+    $cache = new CacheableMetadata();
+    // Check the cloneable entities config and deny access if the entity is not
+    // enabled.
+    $cloneable_entities = \Drupal::configFactory()->get('entity_clone.cloneable_entities');
+    $cache->addCacheTags($cloneable_entities->getCacheTags());
+    $cloneable_entities = $cloneable_entities->get('cloneable_entities') ?? [];
+    if (!in_array($entity->getEntityTypeId(), $cloneable_entities)) {
+      return AccessResult::forbidden()->addCacheableDependency($cache);
+    }
+    $cache->addCacheContexts([
+      'user.permissions',
+    ]);
+    // Deny access if the user cannot clone the entity.
+    $access = AccessResult::forbiddenIf(!$account->hasPermission('clone ' . $entity->getEntityTypeId() . ' entity') && !$account->hasPermission('clone ' . $entity->bundle() . ' ' . $entity->getEntityTypeId() . ' entities'));
+    if ($access->isForbidden()) {
+      return $access->addCacheableDependency($cache);
+    }
+    // Deny access if the user can clone but cannot create new entities of this
+    // type. However, we have some exceptions in which the access control handler
+    // doesn't have a say in things. In these cases, we go based on the clone
+    // permission only.
+    $exceptions = [
+      'file',
+      'paragraph',
+    ];
+    if (in_array($entity->getEntityTypeId(), $exceptions)) {
+      return AccessResult::allowed()->addCacheableDependency($cache);
+    }
+    $handler = \Drupal::entityTypeManager()->getAccessControlHandler($entity->getEntityTypeId());
+    // Prepare the context.
+    $context = [];
+    // Handle specific context elements.
+    if ($entity->getEntityTypeId() == 'group_content') {
+      // Group content must have a specific context item.
+      $context['group'] = $entity->getGroup();
+    }
+    // Check access.
+    $access = $handler->createAccess($entity->bundle(), $account, $context, TRUE);
+    if (!$access->isAllowed()) {
+      $cache->addCacheableDependency($access);
+      $forbidden = AccessResult::forbidden();
+      return $forbidden->addCacheableDependency($cache);
+    }
+    return AccessResult::allowed()->addCacheableDependency($cache);
+  }
+
+}
diff --git a/src/Services/EntityCloneServiceProvider.php b/src/Services/EntityCloneServiceProvider.php
index afc4532..60924d6 100644
--- a/src/Services/EntityCloneServiceProvider.php
+++ b/src/Services/EntityCloneServiceProvider.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\entity_clone\Services;
 
+use Drupal\Component\Utility\DeprecationHelper;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\user\EntityOwnerTrait;
 
@@ -33,7 +34,7 @@ class EntityCloneServiceProvider {
    */
   public function entityTypeHasOwnerTrait(EntityTypeInterface $entityType) {
     try {
-      $reflectionClass = new \ReflectionClass($entityType->getOriginalClass());
+      $reflectionClass = new \ReflectionClass(DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '11.4.0', fn() => $entityType->getDecoratedClasses()[0], fn() => $entityType->getOriginalClass()));
     }
     catch (\ReflectionException $e) {
       return FALSE;
diff --git a/tests/src/Kernel/EntityCloneAccessTest.php b/tests/src/Kernel/EntityCloneAccessTest.php
index 92fbac8..832b2ad 100644
--- a/tests/src/Kernel/EntityCloneAccessTest.php
+++ b/tests/src/Kernel/EntityCloneAccessTest.php
@@ -35,7 +35,6 @@ class EntityCloneAccessTest extends KernelTestBase {
     parent::setUp();
     $this->installEntitySchema('node');
     $this->installEntitySchema('user');
-    $this->installSchema('system', ['sequences']);
     $this->installSchema('node', ['node_access']);
 
     $this->installConfig([
