diff --git a/drafty.info b/drafty.info
index 9be3577..fa6f761 100644
--- a/drafty.info
+++ b/drafty.info
@@ -4,6 +4,8 @@ core = 7.x
 
 dependencies[] = entity
 
+configure = admin/config/system/drafty
+
 test_dependencies[] = field_collection
 test_dependencies[] = entity_translation
 test_dependencies[] = title (>7.x-1.0-alpha7)
diff --git a/drafty.module b/drafty.module
index 3834748..ce85e26 100644
--- a/drafty.module
+++ b/drafty.module
@@ -5,6 +5,35 @@
  */
 
 /**
+ * Implements hook_menu().
+ */
+function drafty_menu() {
+  $items = array();
+
+  $items['admin/config/system/drafty'] = array(
+    'title' => 'Drafty',
+    'description' => 'Manage Drafty settings.',
+    'type' => MENU_NORMAL_ITEM,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('drafty_form'),
+    'access arguments' => array('administer drafty'),
+    'file' => 'includes/drafty.admin.inc',
+  );
+  return $items;
+}
+
+/**
+ * Implements hook_permission().
+ */
+function drafty_permission() {
+  return array(
+    'administer drafty' => array(
+      'title' => t('Administer Drafty'),
+    ),
+  );
+}
+
+/**
  * Implements hook_module_implements_alter().
  */
 function drafty_module_implements_alter(&$implementations) {
@@ -20,7 +49,7 @@ function drafty_module_implements_alter(&$implementations) {
  */
 function drafty_entity_presave($entity, $type) {
   $recursion_level = &drupal_static('drafty_recursion_level', 0);
-  if (!$recursion_level && empty($entity->is_new) && !empty($entity->is_draft_revision)) {
+  if (!$recursion_level && !drafty_entity_is_new($entity, $type) && !empty($entity->is_draft_revision)) {
     // Since this is a draft revision, after saving we want the current,
     // published revision to remain in place in the base entity table and
     // field_data_*() tables. Set the revision to publish once the draft entity
@@ -139,6 +168,29 @@ function drafty() {
 }
 
 /**
+ * Helper function to determine if an entity is new or not.
+ *
+ * The $is_new property cannot be relied on, as not all entities use this. E.g.
+ * files.
+ *
+ * @param mixed $entity
+ *   The entity to check.
+ * @param string $entity_type
+ *   The entity type being passed in.
+ *
+ * @return bool
+ */
+function drafty_entity_is_new($entity, $entity_type) {
+  // Use is_new if it's available, since it's not impossible for new entities to
+  // have an ID set.
+  if (!empty($entity->is_new)) {
+    return TRUE;
+  }
+  list($id) = entity_extract_ids($entity_type, $entity);
+  return empty($id);
+}
+
+/**
  * Handles tracking, selecting and publishing revisions.
  */
 class Drafty {
@@ -267,7 +319,7 @@ class Drafty {
   public function restorePublishedRevisions() {
     $delete_old_revisions = variable_get('drafty_delete_old_revisions', FALSE);
     $delete_with_cron = variable_get('drafty_delete_with_cron', TRUE);
-    $queue = null;
+    $queue = NULL;
     $operations = array();
     foreach ($this->revisionsToPublish as $type => $value) {
       foreach ($value as $id => $vid) {
@@ -275,7 +327,7 @@ class Drafty {
         $this->publishRevision($type, $id, $vid);
         // Now that the revision is deleted, there are two identical copies of
         // the revision in the system. The original 'draft' revision and the
-        // newly saved published revision. 
+        // newly saved published revision.
         if ($delete_old_revisions) {
           // Deletion must be done on a different request thread, or any other
           // hooks called for the revision-to-be-deleted will fail.
@@ -284,25 +336,24 @@ class Drafty {
             'entity_id' => $id,
             'revision_id' => $vid,
           );
-          if ($delete_with_cron){
-            if (empty($queue)){
+          if ($delete_with_cron) {
+            if (empty($queue)) {
               $queue = DrupalQueue::get('drafty_revision_delete');
             }
             $queue->createItem($drafty_queue_item);
           }
           else {
             $operations[] = array(
-              'drafty_queue_delete_revision', 
-              array(
-                $drafty_queue_item)
-              );
+              'drafty_queue_delete_revision',
+              array($drafty_queue_item),
+            );
           }
         }
         // @todo: when restoring a published revision, should the revision
         // timestamp be set to the old value?
       }
     }
-    if (!empty($operations)){
+    if (!empty($operations)) {
       $batch = array(
         'operations' => $operations,
         'finished' => 'drafty_delete_batch_finished',
@@ -310,4 +361,5 @@ class Drafty {
       batch_set($batch);
     }
   }
+
 }
diff --git a/modules/drafty_enforce/drafty_enforce.module b/modules/drafty_enforce/drafty_enforce.module
index edafa37..c4093e1 100644
--- a/modules/drafty_enforce/drafty_enforce.module
+++ b/modules/drafty_enforce/drafty_enforce.module
@@ -9,9 +9,8 @@
  */
 function drafty_enforce_field_attach_submit($entity_type, $entity, $form, &$form_state) {
   // Only force a draft revision when the entity form is submitted.
-  list($id) = entity_extract_ids($entity_type, $entity);
   $info = entity_get_info();
-  if (!empty($info[$entity_type]['entity keys']['revision']) && !empty($id)) {
+  if (!empty($info[$entity_type]['entity keys']['revision']) && !drafty_entity_is_new($entity, $entity_type)) {
     $entity->is_draft_revision = TRUE;
   }
 }
