diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php
index ba4c22a6ab3f0b3d7c9c3781e2f5dfece301a71f..aab438e21a8c749688aa63977b305a8e09f1698b 100644
--- a/CRM/Core/DAO.php
+++ b/CRM/Core/DAO.php
@@ -1679,6 +1679,64 @@ FROM   civicrm_domain
     return $newObject;
   }
 
+  /**
+   * Method that copies custom fields values from an old entity to a new one.
+   *
+   * Fixes bug CRM-19302,
+   * where if a custom field of File type was present, left both events using the same file,
+   * breaking download URL's for the old event.
+   *
+   * @todo the goal here is to clean this up so that it works for any entity. Copy Generic already DOES some custom field stuff
+   * but it seems to be bypassed & perhaps less good than this (or this just duplicates it...)
+   *
+   * @param int $entityID
+   * @param int $newEntityID
+   */
+  public function copyCustomFields($entityID, $newEntityID) {
+    $entity = CRM_Core_DAO_AllCoreTables::getBriefName(get_class($this));
+    $tableName = CRM_Core_DAO_AllCoreTables::getTableForClass(get_class($this));
+    // Obtain custom values for old event
+    $customParams = $htmlType = [];
+    $customValues = CRM_Core_BAO_CustomValueTable::getEntityValues($entityID, $entity);
+
+    // If custom values present, we copy them
+    if (!empty($customValues)) {
+      // Get Field ID's and identify File type attributes, to handle file copying.
+      $fieldIds = implode(', ', array_keys($customValues));
+      $sql = "SELECT id FROM civicrm_custom_field WHERE html_type = 'File' AND id IN ( {$fieldIds} )";
+      $result = CRM_Core_DAO::executeQuery($sql);
+
+      // Build array of File type fields
+      while ($result->fetch()) {
+        $htmlType[] = $result->id;
+      }
+
+      // Build params array of custom values
+      foreach ($customValues as $field => $value) {
+        if ($value !== NULL) {
+          // Handle File type attributes
+          if (in_array($field, $htmlType)) {
+            $fileValues = CRM_Core_BAO_File::path($value, $entityID);
+            $customParams["custom_{$field}_-1"] = [
+              'name' => CRM_Utils_File::duplicate($fileValues[0]),
+              'type' => $fileValues[1],
+            ];
+          }
+          // Handle other types
+          else {
+            $customParams["custom_{$field}_-1"] = $value;
+          }
+        }
+      }
+
+      // Save Custom Fields for new Event
+      CRM_Core_BAO_CustomValueTable::postProcess($customParams, $tableName, $newEntityID, $entity);
+    }
+
+    // copy activity attachments ( if any )
+    CRM_Core_BAO_File::copyEntityFile($tableName, $entityID, $tableName, $newEntityID);
+  }
+
   /**
    * Cascade update through related entities.
    *
diff --git a/CRM/Event/BAO/Event.php b/CRM/Event/BAO/Event.php
index 518bc9bd0bb325e78c6398865ef82a0e251f563f..35b747363258d3da89d70d193bf19da5295a1135 100644
--- a/CRM/Event/BAO/Event.php
+++ b/CRM/Event/BAO/Event.php
@@ -986,7 +986,7 @@ WHERE civicrm_event.is_active = 1
       ['entity_value' => $id, 'mapping_id' => $oldMapping->getId()],
       ['entity_value' => $copyEvent->id, 'mapping_id' => $copyMapping->getId()]
     );
-    self::copyCustomFields($id, $copyEvent->id);
+    $copyEvent->copyCustomFields($id, $copyEvent->id);
 
     $copyEvent->save();
 
@@ -996,57 +996,6 @@ WHERE civicrm_event.is_active = 1
     return $copyEvent;
   }
 
-  /**
-   * Method that copies custom fields values from an old event to a new one. Fixes bug CRM-19302,
-   * where if a custom field of File type was present, left both events using the same file,
-   * breaking download URL's for the old event.
-   *
-   * @param int $oldEventID
-   * @param int $newCopyID
-   */
-  public static function copyCustomFields($oldEventID, $newCopyID) {
-    // Obtain custom values for old event
-    $customParams = $htmlType = [];
-    $customValues = CRM_Core_BAO_CustomValueTable::getEntityValues($oldEventID, 'Event');
-
-    // If custom values present, we copy them
-    if (!empty($customValues)) {
-      // Get Field ID's and identify File type attributes, to handle file copying.
-      $fieldIds = implode(', ', array_keys($customValues));
-      $sql = "SELECT id FROM civicrm_custom_field WHERE html_type = 'File' AND id IN ( {$fieldIds} )";
-      $result = CRM_Core_DAO::executeQuery($sql);
-
-      // Build array of File type fields
-      while ($result->fetch()) {
-        $htmlType[] = $result->id;
-      }
-
-      // Build params array of custom values
-      foreach ($customValues as $field => $value) {
-        if ($value !== NULL) {
-          // Handle File type attributes
-          if (in_array($field, $htmlType)) {
-            $fileValues = CRM_Core_BAO_File::path($value, $oldEventID);
-            $customParams["custom_{$field}_-1"] = [
-              'name' => CRM_Utils_File::duplicate($fileValues[0]),
-              'type' => $fileValues[1],
-            ];
-          }
-          // Handle other types
-          else {
-            $customParams["custom_{$field}_-1"] = $value;
-          }
-        }
-      }
-
-      // Save Custom Fields for new Event
-      CRM_Core_BAO_CustomValueTable::postProcess($customParams, 'civicrm_event', $newCopyID, 'Event');
-    }
-
-    // copy activity attachments ( if any )
-    CRM_Core_BAO_File::copyEntityFile('civicrm_event', $oldEventID, 'civicrm_event', $newCopyID);
-  }
-
   /**
    * This is sometimes called in a loop (during event search).
    *