diff --git a/bootstrap.php b/bootstrap.php
index 671f569278863d360e0d4bb97a323d47503e448d..6132c2d1b842003c712630afe242029ecec80e28 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -87,10 +87,8 @@ class Bootstrap {
         define('TICKET_PRIORITY_TABLE',$prefix.'ticket_priority');
         define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
 
-        define('FORM_SEC_TABLE',$prefix.'form_section');
+        define('FORM_SEC_TABLE',$prefix.'form');
         define('FORM_FIELD_TABLE',$prefix.'form_field');
-        define('FORMSET_TABLE',$prefix.'formset');
-        define('FORMSET_SEC_TABLE',$prefix.'formset_sections');
 
         define('LIST_TABLE',$prefix.'list');
         define('LIST_ITEM_TABLE',$prefix.'list_items');
diff --git a/include/ajax.forms.php b/include/ajax.forms.php
index 08b0b396c4b0aaa8460105b62053b94a9648a83a..37c8657c04cac53f6c83d98276d9e85842aca678 100644
--- a/include/ajax.forms.php
+++ b/include/ajax.forms.php
@@ -5,7 +5,7 @@ require_once(INCLUDE_DIR . 'class.dynamic_forms.php');
 
 class DynamicFormsAjaxAPI extends AjaxController {
     function getForm($form_id) {
-        $form = DynamicFormSection::lookup($form_id);
+        $form = DynamicForm::lookup($form_id);
         if (!$form) return;
 
         foreach ($form->getFields() as $field) {
@@ -15,14 +15,12 @@ class DynamicFormsAjaxAPI extends AjaxController {
 
     function getFormsForHelpTopic($topic_id, $client=false) {
         $topic = Topic::lookup($topic_id);
-        foreach (DynamicFormset::lookup($topic->ht['formset_id'])->getForms() as $form) {
-            $set=$form;
-            $form=$form->getForm();
-            if ($client)
-                include(CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php');
-            else
-                include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php');
-        }
+        $form =DynamicForm::lookup($topic->ht['form_id']);
+        $set=$form;
+        if ($client)
+            include(CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php');
+        else
+            include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php');
     }
 
     function getClientFormsForHelpTopic($topic_id) {
diff --git a/include/api.tickets.php b/include/api.tickets.php
index a442d5b7f6fe4a3685271057ef011d919c3f98d3..a648d10f75d08447dceccd7f7e221cf2212599bd 100644
--- a/include/api.tickets.php
+++ b/include/api.tickets.php
@@ -20,10 +20,9 @@ class TicketApiController extends ApiController {
         # the names to the supported request structure
         if (isset($data['topicId'])) {
             $topic=Topic::lookup($data['topicId']);
-            $formset=DynamicFormset::lookup($topic->ht['formset_id']);
-            foreach ($formset->getForms() as $form)
-                foreach ($form->getForm()->getFields() as $field)
-                    $supported[] = $field->get('name');
+            $form=DynamicForm::lookup($topic->ht['form_id']);
+            foreach ($form->getFields() as $field)
+                $supported[] = $field->get('name');
         }
 
         if(!strcasecmp($format, 'email')) {
@@ -100,18 +99,15 @@ class TicketApiController extends ApiController {
         $errors = array();
 
         $topic=Topic::lookup($data['topicId']);
-        $forms=DynamicFormset::lookup($topic->ht['formset_id'])->getForms();
-        foreach ($forms as $idx=>$f) {
-            $forms[$idx] = $form = $f->getForm()->instanciate($f->sort);
-            # Collect name, email address, and subject for banning and such
-            foreach ($form->getFields() as $field) {
-                $fname = $field->get('name');
-                if ($fname && isset($data[$fname]))
-                    $field->value = $data[$fname];
-            }
-            if (!$form->isValid())
-                $errors = array_merge($errors, $form->errors());
+        $form=DynamicForm::lookup($topic->ht['form_id'])->instanciate();
+        # Collect name, email address, and subject for banning and such
+        foreach ($form->getFields() as $field) {
+            $fname = $field->get('name');
+            if ($fname && isset($data[$fname]))
+                $field->value = $data[$fname];
         }
+        if (!$form->isValid())
+            $errors = array_merge($errors, $form->errors());
 
         $ticket = Ticket::create($data, $errors, $data['source'], $autorespond, $alert);
         # Return errors (?)
diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index dab1ac6c877e659ead03add3d2e2977eacd6396a..6aad0b264ea7d3f2f9ce99d14df668fae0249c83 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -23,7 +23,7 @@ require_once(INCLUDE_DIR . 'class.forms.php');
  * Form template, used for designing the custom form and for entering custom
  * data for a ticket
  */
-class DynamicFormSection extends VerySimpleModel {
+class DynamicForm extends VerySimpleModel {
 
     static $meta = array(
         'table' => FORM_SEC_TABLE,
@@ -46,11 +46,17 @@ class DynamicFormSection extends VerySimpleModel {
     function getDynamicFields() {
         if (!isset($this->_dfields))
             $this->_dfields = DynamicFormField::objects()
-                ->filter(array('section_id'=>$this->id))
+                ->filter(array('form_id'=>$this->id))
                 ->all();
         return $this->_dfields;
     }
 
+    function hasField($name) {
+        foreach ($this->getDynamicFields() as $f)
+            if ($f->get('name') == $name)
+                return true;
+    }
+
     function getTitle() { return $this->get('title'); }
     function getInstructions() { return $this->get('instructions'); }
 
@@ -63,7 +69,7 @@ class DynamicFormSection extends VerySimpleModel {
 
     function instanciate($sort=1) {
         return DynamicFormEntry::create(array(
-            'section_id'=>$this->get('id'), 'sort'=>$sort));
+            'form_id'=>$this->get('id'), 'sort'=>$sort));
     }
 
     function save() {
@@ -79,7 +85,7 @@ class DynamicFormSection extends VerySimpleModel {
             $inst->save();
             foreach ($ht['fields'] as $f) {
                 $f = DynamicFormField::create($f);
-                $f->section_id = $inst->id;
+                $f->form_id = $inst->id;
                 $f->save();
             }
         }
@@ -98,7 +104,7 @@ class DynamicFormField extends VerySimpleModel {
         'joins' => array(
             'form' => array(
                 'null' => true,
-                'constraint' => array('section_id' => 'DynamicFormSection.id'),
+                'constraint' => array('form_id' => 'DynamicForm.id'),
             ),
         ),
     );
@@ -152,12 +158,12 @@ class DynamicFormField extends VerySimpleModel {
 
     function delete() {
         // Don't really delete form fields as that will screw up the data
-        // model. Instead, just drop the association with the form section
-        // which will give the appearance of deletion. Not deleting means
-        // that the field will continue to exist on form entries it may
-        // already have answers on, but since it isn't associated with the
-        // form section, it won't be available for new form submittals.
-        $this->set('section_id', 0);
+        // model. Instead, just drop the association with the form which
+        // will give the appearance of deletion. Not deleting means that
+        // the field will continue to exist on form entries it may already
+        // have answers on, but since it isn't associated with the form, it
+        // won't be available for new form submittals.
+        $this->set('form_id', 0);
         $this->save();
     }
 
@@ -195,7 +201,7 @@ class DynamicFormEntry extends VerySimpleModel {
         'joins' => array(
             'form' => array(
                 'null' => true,
-                'constraint' => array('section_id' => 'DynamicFormSection.id'),
+                'constraint' => array('form_id' => 'DynamicForm.id'),
             ),
         ),
     );
@@ -231,7 +237,7 @@ class DynamicFormEntry extends VerySimpleModel {
 
     function getForm() {
         if (!$this->_form)
-            $this->_form = DynamicFormSection::lookup($this->get('section_id'));
+            $this->_form = DynamicForm::lookup($this->get('form_id'));
         return $this->_form;
     }
 
@@ -275,10 +281,10 @@ class DynamicFormEntry extends VerySimpleModel {
     /**
      * addMissingFields
      *
-     * Adds fields that have been added to the linked form section (field
-     * set) since this entry was originally created. If fields are added to
-     * the form section, the method will automatically add the fields and
-     * null answers to the entry.
+     * Adds fields that have been added to the linked form (field set) since
+     * this entry was originally created. If fields are added to the form,
+     * the method will automatically add the fields and null answers to the
+     * entry.
      */
     function addMissingFields() {
         foreach ($this->getForm()->getFields() as $field) {
@@ -289,7 +295,6 @@ class DynamicFormEntry extends VerySimpleModel {
                 }
             }
             if (!$found) {
-                # Section ID is auto set in the ::save method
                 $a = DynamicFormEntryAnswer::create(
                     array('field_id'=>$field->get('id'), 'entry_id'=>$this->id));
                 $a->field = $field;
@@ -326,9 +331,9 @@ class DynamicFormEntry extends VerySimpleModel {
 }
 
 /**
- * Represents a single answer to a single field on a dynamic form section.
- * The data / answer to the field is linked back to the form section and
- * field which was originally used for the submission.
+ * Represents a single answer to a single field on a dynamic form. The
+ * data / answer to the field is linked back to the form and field which was
+ * originally used for the submission.
  */
 class DynamicFormEntryAnswer extends VerySimpleModel {
 
@@ -343,10 +348,6 @@ class DynamicFormEntryAnswer extends VerySimpleModel {
             'entry' => array(
                 'constraint' => array('entry_id' => 'DynamicFormEntry.id'),
             ),
-            'form' => array(
-                'lazy' => true,
-                'constraint' => array('form_id' => 'DynamicFormSection.id'),
-            ),
         ),
     );
 
@@ -384,106 +385,6 @@ class DynamicFormEntryAnswer extends VerySimpleModel {
     }
 }
 
-/**
- * A collection of form sections makes up a "form" in the context of dynamic
- * forms. This model represents that list of sections. The individual
- * association of form sections to this form are delegated to the
- * DynamicFormsetSections model
- */
-class DynamicFormset extends VerySimpleModel {
-
-    static $meta = array(
-        'table' => FORMSET_TABLE,
-        'ordering' => array('title'),
-        'pk' => array('id'),
-    );
-
-    var $_forms;
-
-    function getForms() {
-        if (!isset($this->_forms))
-            $this->_forms = DynamicFormsetSections::objects()->filter(
-                    array('formset_id'=>$this->id))->all();
-        return $this->_forms;
-    }
-
-    function hasField($name) {
-        foreach ($this->getForms() as $form)
-            foreach ($form->getForm()->getFields() as $f)
-                if ($f->get('name') == $name)
-                    return true;
-    }
-
-    function errors() {
-        return $this->_errors;
-    }
-
-    function isValid() {
-        if (!$this->_errors) $this->_errors = array();
-        return count($this->_errors) === 0;
-    }
-
-    function save() {
-        if (count($this->dirty))
-            $this->set('updated', new SqlFunction('NOW'));
-        return parent::save();
-    }
-
-    static function create($ht=false) {
-        $inst = parent::create($ht);
-        $inst->set('created', new SqlFunction('NOW'));
-        if (isset($ht['sections'])) {
-            $inst->save();
-            foreach ($ht['sections'] as $s) {
-                $sort = 1;
-                if (isset($s['sort'])) {
-                    $sort = $s['sort'];
-                    unset($s['sort']);
-                }
-                $sec = DynamicFormSection::create($s);
-                $sec->save();
-                DynamicFormsetSections::create(array(
-                    'formset_id' => $inst->id,
-                    'section_id' => $sec->id,
-                    'sort' => $sort
-                ))->save();
-            }
-        }
-        return $inst;
-    }
-}
-
-/**
- * Represents an assocation of form section (DynamicFormSection) with a
- * "form" (DynamicFormset).
- */
-class DynamicFormsetSections extends VerySimpleModel {
-    static $meta = array(
-        'table' => FORMSET_SEC_TABLE,
-        'ordering' => array('sort'),
-        'pk' => array('id'),
-    );
-
-    var $_section;
-
-    function getForm() {
-        if (!isset($this->_section))
-            $this->_section = DynamicFormSection::lookup($this->get('section_id'));
-        return $this->_section;
-    }
-
-    function errors() {
-        return $this->_errors;
-    }
-
-    function isValid() {
-        if (!$this->_errors) $this->_errors = array();
-        if (!is_numeric($this->get('sort')))
-            $this->_errors['sort'] = 'Enter a number';
-        return count($this->errors()) === 0;
-    }
-}
-
 /**
  * Dynamic lists are used to represent list of arbitrary data that can be
  * used as dropdown or typeahead selections in dynamic forms. This model
@@ -660,7 +561,7 @@ class SelectionWidget extends ChoicesWidget {
     function render() {
         $config = $this->field->getConfiguration();
         $value = false;
-        if ($this->value && get_class($this->value) == 'DynamicListItem') {
+        if (is_object($this->value) && get_class($this->value) == 'DynamicListItem') {
             // Loaded from database
             $value = $this->value->get('id');
             $name = $this->value->get('value');
diff --git a/include/class.i18n.php b/include/class.i18n.php
index b7e8e95d8f3e6b91df36782296fd19ffb93f80ce..7891d7ef937ecacf2bc148ae4a4e441801a8e003 100644
--- a/include/class.i18n.php
+++ b/include/class.i18n.php
@@ -46,7 +46,7 @@ class Internationalization {
             'email_template_group.yaml' => 'EmailTemplateGroup',
             'department.yaml' =>    'Dept',
             'sla.yaml' =>           'SLA',
-            'forms.yaml' =>         'DynamicFormset',
+            'form.yaml' =>          'DynamicForm',
             // Note that department, sla, and forms are required for
             // help_topic
             'help_topic.yaml' =>    'Topic',
diff --git a/include/class.nav.php b/include/class.nav.php
index 04080f25573f66b9bca5b973b94fe8883a428e5b..ac8c0228cc1f1bbce9236777dea180f30285b294 100644
--- a/include/class.nav.php
+++ b/include/class.nav.php
@@ -175,7 +175,6 @@ class AdminNav extends StaffNav{
             $tabs['dashboard']=array('desc'=>'Dashboard','href'=>'logs.php','title'=>'Admin Dashboard');
             $tabs['settings']=array('desc'=>'Settings','href'=>'settings.php','title'=>'System Settings');
             $tabs['manage']=array('desc'=>'Manage','href'=>'helptopics.php','title'=>'Manage Options');
-            $tabs['forms']=array('desc'=>'Forms','href'=>'dynamic-forms.php','title'=>'Manage Forms');
             $tabs['emails']=array('desc'=>'Emails','href'=>'emails.php','title'=>'Email Settings');
             $tabs['staff']=array('desc'=>'Staff','href'=>'staff.php','title'=>'Manage Staff');
             $this->tabs=$tabs;
@@ -208,12 +207,9 @@ class AdminNav extends StaffNav{
                                         'title'=>'Ticket Filters','iconclass'=>'ticketFilters');
                     $subnav[]=array('desc'=>'SLA Plans','href'=>'slas.php','iconclass'=>'sla');
                     $subnav[]=array('desc'=>'API Keys','href'=>'apikeys.php','iconclass'=>'api');
-                    $subnav[]=array('desc'=>'Site Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
-                    break;
-                case 'forms':
-                    $subnav[]=array('desc'=>'Dynamic Forms','href'=>'dynamic-forms.php','iconclass'=>'');
-                    $subnav[]=array('desc'=>'Form Sections','href'=>'dynamic-form-sections.php','iconclass'=>'');
-                    $subnav[]=array('desc'=>'Dynamic Lists','href'=>'dynamic-lists.php','iconclass'=>'');
+                    $subnav[]=array('desc'=>'Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
+                    $subnav[]=array('desc'=>'Forms','href'=>'forms.php','iconclass'=>'pages');
+                    $subnav[]=array('desc'=>'Lists','href'=>'lists.php','iconclass'=>'pages');
                     break;
                 case 'emails':
                     $subnav[]=array('desc'=>'Emails','href'=>'emails.php', 'title'=>'Email Addresses', 'iconclass'=>'emailSettings');
diff --git a/include/class.topic.php b/include/class.topic.php
index 0bbcdc8b308fdb64b5fbc0151af87ef6a39de630..d924f2ab7f1f4e3afec14e4cde5f20ebb069705a 100644
--- a/include/class.topic.php
+++ b/include/class.topic.php
@@ -209,13 +209,13 @@ class Topic {
         elseif(($tid=self::getIdByName($vars['topic'], $vars['pid'])) && $tid!=$id)
             $errors['topic']='Topic already exists';
 
-        if (!$vars['formset_id'])
-            $errors['formset_id'] = 'You must select a form';
+        if (!$vars['form_id'])
+            $errors['form_id'] = 'You must select a form';
         else {
-            $group=DynamicFormset::lookup($vars['formset_id']);
-            foreach (array('name', 'email', 'subject') as $f)
-                if (!$group->hasField($f))
-                    $errors['formset_id']="Form set must define the '$f' field";
+            $form=DynamicForm::lookup($vars['form_id']);
+            foreach (array('subject') as $f)
+                if (!$form->hasField($f))
+                    $errors['form_id']="Form must define the '$f' field";
         }
 
         if(!$vars['dept_id'])
@@ -232,7 +232,7 @@ class Topic {
             .',dept_id='.db_input($vars['dept_id'])
             .',priority_id='.db_input($vars['priority_id'])
             .',sla_id='.db_input($vars['sla_id'])
-            .',formset_id='.db_input($vars['formset_id'])
+            .',form_id='.db_input($vars['form_id'])
             .',page_id='.db_input($vars['page_id'])
             .',isactive='.db_input($vars['isactive'])
             .',ispublic='.db_input($vars['ispublic'])
diff --git a/include/i18n/en_US/form.yaml b/include/i18n/en_US/form.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..868b76422ce8d669cb96ce74150338311e291f23
--- /dev/null
+++ b/include/i18n/en_US/form.yaml
@@ -0,0 +1,44 @@
+#
+# Default (dynamic) form configuration
+#
+# Fields:
+---
+- id: 1
+  title: User Information
+  fields:
+    - type: text # notrans
+      name: email # notrans
+      label: Email Address
+      required: true
+      sort: 10
+      configuration:
+          size: 40
+          length: 40
+          validator: email # notrans
+
+    - type: text # notrans
+      name: name # notrans
+      label: Full Name
+      required: true
+      sort: 20
+      configuration:
+          size: 40
+          length: 40
+
+    - type: phone # notrans
+      name: phone # notrans
+      label: Phone Number
+      required: false
+      sort: 30
+
+- id: 2
+  title: Ticket Details
+  fields:
+    - type: text # notrans
+      name: subject # notrans
+      label: Subject
+      hint: Issue Summary
+      sort: 10
+      configuration:
+          size: 40
+          length: 50
diff --git a/include/i18n/en_US/forms.yaml b/include/i18n/en_US/forms.yaml
deleted file mode 100644
index 451889b14422c9ca4edb9682b18449f2d0048dd3..0000000000000000000000000000000000000000
--- a/include/i18n/en_US/forms.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Default (dynamic) form configuration
-#
-# Fields:
----
-- id: 1
-  title: Default
-  sections:
-    - title: User Information
-      sort: 10
-      fields:
-        - type: text # notrans
-          name: email # notrans
-          label: Email Address
-          required: true
-          sort: 10
-          configuration:
-              size: 40
-              length: 40
-              validator: email # notrans
-
-        - type: text # notrans
-          name: name # notrans
-          label: Full Name
-          required: true
-          sort: 20
-          configuration:
-              size: 40
-              length: 40
-
-        - type: phone # notrans
-          name: phone # notrans
-          label: Phone Number
-          required: false
-          sort: 30
-
-    - title: Ticket Details
-      sort: 20
-      fields:
-        - type: text # notrans
-          name: subject # notrans
-          label: Subject
-          hint: Issue Summary
-          sort: 10
-          configuration:
-              size: 40
-              length: 50
diff --git a/include/i18n/en_US/help_topic.yaml b/include/i18n/en_US/help_topic.yaml
index 2c99305c05216d8e33d38159663ef464a0ee69f1..8ee30e318bc3ad8cb6d6b9094c4e3520a8925a43 100644
--- a/include/i18n/en_US/help_topic.yaml
+++ b/include/i18n/en_US/help_topic.yaml
@@ -23,7 +23,7 @@
   dept_id: 1
   sla_id: 1
   priority_id: 2
-  formset_id: 1
+  form_id: 1
   topic: Support
   notes: |
     Tickets that primarily concern the support deparment
@@ -33,7 +33,7 @@
   dept_id: 1
   sla_id: 0
   priority_id: 2
-  formset_id: 1
+  form_id: 1
   topic: Billing
   notes: |
     Tickets that primarily concern the sales and billing deparments
diff --git a/include/staff/dynamic-form-section.inc.php b/include/staff/dynamic-form-section.inc.php
deleted file mode 100644
index 800f1b97bcd633fb17cd4a1e60d54f8223a7a853..0000000000000000000000000000000000000000
--- a/include/staff/dynamic-form-section.inc.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-$info=array();
-if($form && $_REQUEST['a']!='add') {
-    $title = 'Update dynamic form section';
-    $action = 'update';
-    $submit_text='Save Changes';
-    $info = $form->ht;
-    $newcount=2;
-} else {
-    $title = 'Add new dynamic form section';
-    $action = 'add';
-    $submit_text='Add Form Section';
-    $newcount=4;
-}
-$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
-
-?>
-<form action="?" method="post" id="save">
-    <?php csrf_token(); ?>
-    <input type="hidden" name="do" value="<?php echo $action; ?>">
-    <input type="hidden" name="id" value="<?php echo $info['id']; ?>">
-    <h2>Dynamic Form Section</h2>
-    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
-    <thead>
-        <tr>
-            <th colspan="2">
-                <h4><?php echo $title; ?></h4>
-                <em>Dynamic forms are used to allow custom data to be
-                associated with tickets</em>
-            </th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td width="180" class="required">Title:</td>
-            <td><input type="text" name="title" size="40" value="<?php
-                echo $info['title']; ?>"/></td>
-        </tr>
-        <tr>
-            <td width="180">Instructions:</td>
-            <td><textarea name="instructions" rows="3" cols="40"><?php
-                echo $info['instructions']; ?></textarea>
-            </td>
-        </tr>
-        <tr>
-            <td width="180">Internal Notes:</td>
-            <td><textarea name="notes" rows="4" cols="80"><?php
-                echo $info['notes']; ?></textarea>
-            </td>
-        </tr>
-    </tbody>
-    </table>
-    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
-    <thead>
-        <tr>
-            <th colspan="7">
-                <em>Form Fields</em>
-            </th>
-        </tr>
-        <tr>
-            <th>Delete</th>
-            <th>Label</th>
-            <th>Type</th>
-            <th>Name</th>
-            <th>Private</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody class="sortable-rows" data-sort="sort-">
-    <?php if ($form) foreach ($form->getFields() as $f) {
-        $id = $f->get('id');
-        $errors = $f->errors(); ?>
-        <tr>
-            <td><input type="checkbox" name="delete-<?php echo $id; ?>"/>
-                <input type="hidden" name="sort-<?php echo $id; ?>"
-                    value="<?php echo $f->get('sort'); ?>"/>
-                <font class="error"><?php
-                    if ($errors['sort']) echo '<br/>'; echo $errors['sort'];
-                ?></font>
-                </td>
-            <td><input type="text" size="32" name="label-<?php echo $id; ?>"
-                value="<?php echo $f->get('label'); ?>"/></td>
-            <td><select name="type-<?php echo $id; ?>">
-                <?php foreach (FormField::allTypes() as $type=>$nfo) { ?>
-                <option value="<?php echo $type; ?>" <?php
-                    if ($f->get('type') == $type) echo 'selected="selected"'; ?>>
-                    <?php echo $nfo[0]; ?></option>
-                <?php } ?>
-            </select>
-            <?php if ($f->isConfigurable()) { ?>
-                <a class="action-button" style="float:none"
-                    href="ajax.php/form/field-config/<?php
-                        echo $f->get('id'); ?>"
-                    onclick="javascript:
-                        $('#overlay').show();
-                        $('#field-config .body').load(this.href);
-                        $('#field-config').show();
-                        return false;
-                    "><i class="icon-edit"></i> Config</a>
-            <?php } ?></td>
-            <td>
-                <input type="text" size="20" name="name-<?php echo $id; ?>"
-                    value="<?php echo $f->get('name'); ?>"/>
-                <font class="error"><?php
-                    if ($errors['name']) echo '<br/>'; echo $errors['name'];
-                ?></font>
-                </td>
-            <td><input type="checkbox" name="private-<?php echo $id; ?>"
-                <?php if ($f->get('private')) echo 'checked="checked"'; ?>/></td>
-            <td><input type="checkbox" name="required-<?php echo $id; ?>"
-                <?php if ($f->get('required')) echo 'checked="checked"'; ?>/></td>
-        </tr>
-    <?php
-    }
-    for ($i=0; $i<$newcount; $i++) { ?>
-            <td><em>add</em>
-                <input type="hidden" name="sort-new-<?php echo $i; ?>"/></td>
-            <td><input type="text" size="32" name="label-new-<?php echo $i; ?>"/></td>
-            <td><select name="type-new-<?php echo $i; ?>">
-                <?php foreach (FormField::allTypes() as $type=>$nfo) { ?>
-                <option value="<?php echo $type; ?>">
-                    <?php echo $nfo[0]; ?></option>
-                <?php } ?>
-            </select></td>
-            <td><input type="text" size="20" name="name-new-<?php echo $i; ?>"/></td>
-            <td><input type="checkbox" name="private-new-<?php echo $i; ?>"/></td>
-            <td><input type="checkbox" name="required-new-<?php echo $i; ?>"/></td>
-        </tr>
-    <?php } ?>
-    </tbody>
-    </table>
-<p style="padding-left:225px;">
-    <input type="submit" name="submit" value="<?php echo $submit_text; ?>">
-    <input type="reset"  name="reset"  value="Reset">
-    <input type="button" name="cancel" value="Cancel" onclick='window.location.href="?"'>
-</p>
-</form>
-
-<div style="display:none;" class="dialog" id="field-config">
-    <div class="body"></div>
-</div>
diff --git a/include/staff/dynamic-form-sections.inc.php b/include/staff/dynamic-form-sections.inc.php
deleted file mode 100644
index ed715668a958304e5265b034ef6f3fe34a553880..0000000000000000000000000000000000000000
--- a/include/staff/dynamic-form-sections.inc.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<div style="width:700;padding-top:5px; float:left;">
- <h2>Dynamic Form Sections</h2>
-</div>
-<div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
- <b><a href="dynamic-form-sections.php?a=add" class="Icon">Add New Dynamic Form Section</a></b></div>
-<div class="clear"></div>
-
-<?php
-$page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
-$count = DynamicFormSection::objects()->count();
-$pageNav = new Pagenate($count, $page, PAGE_LIMIT);
-$pageNav->setURL('dynamic-form-sections.php');
-$showing=$pageNav->showing().' form sections';
-?>
-
-<table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
-    <caption><?php echo $showing; ?></caption>
-    <thead>
-        <tr>
-            <th width="7">&nbsp;</th>
-            <th>Title</th>
-            <th>Last Updated</th>
-        </tr>
-    </thead>
-    <tbody>
-    <?php foreach (DynamicFormSection::objects()->order_by('title')
-                ->limit($pageNav->getLimit())
-                ->offset($pageNav->getStart()) as $form) { ?>
-        <tr>
-            <td/>
-            <td><a href="?id=<?php echo $form->get('id'); ?>"><?php echo $form->get('title'); ?></a></td>
-            <td><?php echo $form->get('updated'); ?></td>
-        </tr>
-    <?php }
-    ?>
-    </tbody>
-</table>
-<?php
-if ($count) //Show options..
-    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
-?>
diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php
index c2753063d2b1dbe6b334c30d3d69cfff05677bf2..9ce167350272724e1ac96f0fecb0021bd37b467e 100644
--- a/include/staff/dynamic-form.inc.php
+++ b/include/staff/dynamic-form.inc.php
@@ -1,14 +1,14 @@
 <?php
 
 $info=array();
-if($group && $_REQUEST['a']!='add') {
-    $title = 'Update dynamic form';
+if($form && $_REQUEST['a']!='add') {
+    $title = 'Update dynamic form section';
     $action = 'update';
     $submit_text='Save Changes';
-    $info = $group->ht;
+    $info = $form->ht;
     $newcount=2;
 } else {
-    $title = 'Add new dynamic form';
+    $title = 'Add new dynamic form section';
     $action = 'add';
     $submit_text='Add Form';
     $newcount=4;
@@ -24,81 +24,119 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
     <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
     <thead>
         <tr>
-            <th colspan="4">
+            <th colspan="2">
                 <h4><?php echo $title; ?></h4>
-                <em>Dynamic forms are used to combine several form sections
-                into a larger form for use in the ticketing system. This
-                allows for common sections to be reused among various forms
-                </em>
+                <em>Dynamic forms are used to allow custom data to be
+                associated with tickets</em>
             </th>
         </tr>
     </thead>
     <tbody>
         <tr>
             <td width="180" class="required">Title:</td>
-            <td colspan="3"><input size="40" type="text" name="title"
-                value="<?php echo $info['title']; ?>"/></td>
+            <td><input type="text" name="title" size="40" value="<?php
+                echo $info['title']; ?>"/></td>
         </tr>
         <tr>
-            <td width="180">Description:</td>
-            <td colspan="3"><textarea name="notes" rows="3" cols="40"><?php
+            <td width="180">Instructions:</td>
+            <td><textarea name="instructions" rows="3" cols="40"><?php
+                echo $info['instructions']; ?></textarea>
+            </td>
+        </tr>
+        <tr>
+            <td width="180">Internal Notes:</td>
+            <td><textarea name="notes" rows="4" cols="80"><?php
                 echo $info['notes']; ?></textarea>
             </td>
         </tr>
     </tbody>
-    <tbody>
-       <tr><th>Delete</th><th>Form name</th></tr>
-    </tbody>
+    </table>
+    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
+    <thead>
+        <tr>
+            <th colspan="7">
+                <em>Form Fields</em>
+            </th>
+        </tr>
+        <tr>
+            <th>Delete</th>
+            <th>Label</th>
+            <th>Type</th>
+            <th>Name</th>
+            <th>Private</th>
+            <th>Required</th>
+        </tr>
+    </thead>
     <tbody class="sortable-rows" data-sort="sort-">
-       <?php if ($group) foreach ($group->getForms() as $formatt) {
-           $form = $formatt->getForm();
-           $errors = $formatt->errors(); ?>
-           <tr>
-               <td>
-                    <input type="checkbox" name="delete-<?php echo $formatt->get('id'); ?>"/>
-                    <input type="hidden" name="sort-<?php echo $formatt->get('id'); ?>"
-                       value="<?php echo $formatt->get('sort'); ?>"/>
-                    <font class="error"><?php
-                        if ($errors['sort']) echo '<br/>'; echo $errors['sort'];
-                    ?></font>
-               </td><td>
-                   <select name="section_id-<?php echo $formatt->get('id'); ?>">
-                   <?php foreach (DynamicFormSection::objects() as $form) { ?>
-                       <option value="<?php echo $form->get('id'); ?>" <?php
-                            if ($formatt->get('section_id') == $form->get('id'))
-                                echo 'selected="selected"'; ?>>
-                           <?php echo $form->get('title'); ?>
-                       </option>
-                   <?php } ?>
-                   </select>
-                    <a class="action-button" style="float:none"
-                        href="dynamic-form-sections.php?id=<?php
-                            echo $formatt->get('section_id'); ?>"><i class="icon-edit"></i
-                            > Edit</a>
-               </td>
-           </tr>
-       <?php }
-       for ($i=0; $i<$newcount; $i++) { ?>
-       <tr>
-           <td><em>add</em>
-               <input type="hidden" name="sort-new-<?php echo $i; ?>" size="4"/>
-           </td><td>
-               <select name="section_id-new-<?php echo $i; ?>">
-                   <option value="0">&mdash; Select Form &mdash;</option>
-               <?php foreach (DynamicFormSection::objects() as $form) { ?>
-                   <option value="<?php echo $form->get('id'); ?>">
-                       <?php echo $form->get('title'); ?>
-                   </option>
-               <?php } ?>
-               </select>
-            </td>
+    <?php if ($form) foreach ($form->getFields() as $f) {
+        $id = $f->get('id');
+        $errors = $f->errors(); ?>
+        <tr>
+            <td><input type="checkbox" name="delete-<?php echo $id; ?>"/>
+                <input type="hidden" name="sort-<?php echo $id; ?>"
+                    value="<?php echo $f->get('sort'); ?>"/>
+                <font class="error"><?php
+                    if ($errors['sort']) echo '<br/>'; echo $errors['sort'];
+                ?></font>
+                </td>
+            <td><input type="text" size="32" name="label-<?php echo $id; ?>"
+                value="<?php echo $f->get('label'); ?>"/></td>
+            <td><select name="type-<?php echo $id; ?>">
+                <?php foreach (FormField::allTypes() as $type=>$nfo) { ?>
+                <option value="<?php echo $type; ?>" <?php
+                    if ($f->get('type') == $type) echo 'selected="selected"'; ?>>
+                    <?php echo $nfo[0]; ?></option>
+                <?php } ?>
+            </select>
+            <?php if ($f->isConfigurable()) { ?>
+                <a class="action-button" style="float:none"
+                    href="ajax.php/form/field-config/<?php
+                        echo $f->get('id'); ?>"
+                    onclick="javascript:
+                        $('#overlay').show();
+                        $('#field-config .body').load(this.href);
+                        $('#field-config').show();
+                        return false;
+                    "><i class="icon-edit"></i> Config</a>
+            <?php } ?></td>
+            <td>
+                <input type="text" size="20" name="name-<?php echo $id; ?>"
+                    value="<?php echo $f->get('name'); ?>"/>
+                <font class="error"><?php
+                    if ($errors['name']) echo '<br/>'; echo $errors['name'];
+                ?></font>
+                </td>
+            <td><input type="checkbox" name="private-<?php echo $id; ?>"
+                <?php if ($f->get('private')) echo 'checked="checked"'; ?>/></td>
+            <td><input type="checkbox" name="required-<?php echo $id; ?>"
+                <?php if ($f->get('required')) echo 'checked="checked"'; ?>/></td>
         </tr>
-        <?php } ?>
+    <?php
+    }
+    for ($i=0; $i<$newcount; $i++) { ?>
+            <td><em>add</em>
+                <input type="hidden" name="sort-new-<?php echo $i; ?>"/></td>
+            <td><input type="text" size="32" name="label-new-<?php echo $i; ?>"/></td>
+            <td><select name="type-new-<?php echo $i; ?>">
+                <?php foreach (FormField::allTypes() as $type=>$nfo) { ?>
+                <option value="<?php echo $type; ?>">
+                    <?php echo $nfo[0]; ?></option>
+                <?php } ?>
+            </select></td>
+            <td><input type="text" size="20" name="name-new-<?php echo $i; ?>"/></td>
+            <td><input type="checkbox" name="private-new-<?php echo $i; ?>"/></td>
+            <td><input type="checkbox" name="required-new-<?php echo $i; ?>"/></td>
+        </tr>
+    <?php } ?>
     </tbody>
-</table>
+    </table>
 <p style="padding-left:225px;">
     <input type="submit" name="submit" value="<?php echo $submit_text; ?>">
     <input type="reset"  name="reset"  value="Reset">
     <input type="button" name="cancel" value="Cancel" onclick='window.location.href="?"'>
 </p>
 </form>
+
+<div style="display:none;" class="dialog" id="field-config">
+    <div class="body"></div>
+</div>
diff --git a/include/staff/dynamic-forms.inc.php b/include/staff/dynamic-forms.inc.php
index fdb93ca79a095f4f4187d2977e3cd4a826927039..e1c590831ecc218c805feede51946006b30677ad 100644
--- a/include/staff/dynamic-forms.inc.php
+++ b/include/staff/dynamic-forms.inc.php
@@ -2,15 +2,15 @@
  <h2>Dynamic Forms</h2>
 </div>
 <div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
- <b><a href="dynamic-forms.php?a=add" class="Icon">Add Dynamic Form</a></b></div>
+ <b><a href="forms.php?a=add" class="Icon">Add New Dynamic Form</a></b></div>
 <div class="clear"></div>
 
 <?php
 $page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
-$count = DynamicFormset::objects()->count();
+$count = DynamicForm::objects()->count();
 $pageNav = new Pagenate($count, $page, PAGE_LIMIT);
-$pageNav->setURL('dynamic-lists.php');
-$showing=$pageNav->showing().' dynamic forms';
+$pageNav->setURL('forms.php');
+$showing=$pageNav->showing().' forms';
 ?>
 
 <table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
@@ -23,7 +23,7 @@ $showing=$pageNav->showing().' dynamic forms';
         </tr>
     </thead>
     <tbody>
-    <?php foreach (DynamicFormset::objects()->order_by('title')
+    <?php foreach (DynamicForm::objects()->order_by('title')
                 ->limit($pageNav->getLimit())
                 ->offset($pageNav->getStart()) as $form) { ?>
         <tr>
diff --git a/include/staff/dynamic-list.inc.php b/include/staff/dynamic-list.inc.php
index 02d5e9314f8dbcbd504af686cacf74bfc63c8546..3505160210c0526bd36d73748824f67e01e50a5f 100644
--- a/include/staff/dynamic-list.inc.php
+++ b/include/staff/dynamic-list.inc.php
@@ -84,6 +84,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         <?php if ($list)
         $icon = ($info['sort_mode'] == 'SortCol')
             ? '<i class="icon-sort"></i>&nbsp;' : '';
+        if ($list) {
         foreach ($list->getItems($pageNav->getLimit(), $pageNav->getStart()) as $i) {
             $id = $i->get('id'); ?>
         <tr>
@@ -97,6 +98,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 value="<?php echo $i->get('extra'); ?>"/></td>
         </tr>
     <?php }
+    }
     for ($i=0; $i<$newcount; $i++) { ?>
         <tr>
             <td><?php echo $icon; ?> <em>add</em>
diff --git a/include/staff/dynamic-lists.inc.php b/include/staff/dynamic-lists.inc.php
index 0427666d66f22357c1bdc67b881a0fb4c7b29e0a..a5742f3fd5f30b9cd3a928e54e8c944aa3f58ed6 100644
--- a/include/staff/dynamic-lists.inc.php
+++ b/include/staff/dynamic-lists.inc.php
@@ -2,14 +2,14 @@
  <h2>Dynamic Lists</h2>
 </div>
 <div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
- <b><a href="dynamic-lists.php?a=add" class="Icon">Add New Dynamic List</a></b></div>
+ <b><a href="lists.php?a=add" class="Icon">Add New Dynamic List</a></b></div>
 <div class="clear"></div>
 
 <?php
 $page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
 $count = DynamicList::objects()->count();
 $pageNav = new Pagenate($count, $page, PAGE_LIMIT);
-$pageNav->setURL('dynamic-lists.php');
+$pageNav->setURL('lists.php');
 $showing=$pageNav->showing().' dynamic lists';
 ?>
 
diff --git a/include/staff/helptopic.inc.php b/include/staff/helptopic.inc.php
index 07bc83a700c7fdb55152ad584163fb2ca38048eb..8aa9be725e396a07c0da9cf07b58a38c46fe8e12 100644
--- a/include/staff/helptopic.inc.php
+++ b/include/staff/helptopic.inc.php
@@ -90,19 +90,19 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
 
         <tr><th colspan="2"><em>New ticket options</em></th></tr>
        <tr>
-           <td><strong>Formset</strong>:</td>
-           <td><select name="formset_id">
-               <option value="0">&mdash; Select a Formset &mdash;</option>
-               <?php foreach (DynamicFormset::objects() as $group) { ?>
+           <td><strong>Dynamic Form</strong>:</td>
+           <td><select name="form_id">
+               <option value="0">&mdash; Select a Form &mdash;</option>
+               <?php foreach (DynamicForm::objects() as $group) { ?>
                    <option value="<?php echo $group->get('id'); ?>"
-                       <?php if ($group->get('id') == $info['formset_id'])
+                       <?php if ($group->get('id') == $info['form_id'])
                             echo 'selected="selected"'; ?>>
                        <?php echo $group->get('title'); ?>
                    </option>
                <?php } ?>
                </select>
                <em>Information for tickets associated with this help topic</em>
-               &nbsp;<span class="error">&nbsp;<?php echo $errors['formset_id']; ?></span>
+               &nbsp;<span class="error">&nbsp;<?php echo $errors['form_id']; ?></span>
            </td>
        </tr>
         <tr>
diff --git a/include/staff/ticket-edit.inc.php b/include/staff/ticket-edit.inc.php
index fca5a366c9c38f76d3449ef95d5672bc12e7e5a8..10e042588c3fa04456fd26c9c6e8f715b7b25503 100644
--- a/include/staff/ticket-edit.inc.php
+++ b/include/staff/ticket-edit.inc.php
@@ -8,7 +8,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo());
  <input type="hidden" name="do" value="update">
  <input type="hidden" name="a" value="edit">
  <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
- <h2>Update Ticket# <?php echo $ticket->getExtId(); ?></h2>
+ <h2>Update Ticket #<?php echo $ticket->getExtId(); ?></h2>
  <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
     <thead>
         <tr>
diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php
index ab0eba20e9b1ea9f4066bf64f5f9fc63d879dfa6..c06117c272285b895b9ce02ccea7eed5d3c6dd3e 100644
--- a/include/staff/ticket-open.inc.php
+++ b/include/staff/ticket-open.inc.php
@@ -186,11 +186,9 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         } ?>
         </tbody>
         <tbody id="dynamic-form">
-        <?php if ($forms) {
-            foreach ($forms as $form) {
-                include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php');
-            }
-        } ?>
+        <?php if ($form)
+            include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php');
+        ?>
         </tbody>
         <tbody>
         <tr>
diff --git a/open.php b/open.php
index 7d7742cdfd326bf547a2d604a1b98fa90919f6fc..372c338392b5582169ea3e84cf10d46ac6e06027 100644
--- a/open.php
+++ b/open.php
@@ -32,21 +32,17 @@ if($_POST):
 
     $interest=array('name','email','subject');
     $topic=Topic::lookup($vars['topicId']);
-    $forms=DynamicFormset::lookup($topic->ht['formset_id'])->getForms();
-    foreach ($forms as $idx=>$f) {
-        $form=$f->getForm()->instanciate($f->sort);
-        # Collect name, email, and subject address for banning and such
-        foreach ($form->getAnswers() as $answer) {
-            $fname = $answer->getField()->get('name');
-            if (in_array($fname, $interest))
-                # XXX: Assigning to _POST not considered great PHP
-                #      coding style
-                $vars[$fname] = $answer->getField()->getClean();
-        }
-        $forms[$idx] = $form;
-        if (!$form->isValid())
-            $errors = array_merge($errors, $form->errors());
+    $form=DynamicForm::lookup($topic->ht['form_id'])->instanciate();
+    # Collect name, email, and subject address for banning and such
+    foreach ($form->getAnswers() as $answer) {
+        $fname = $answer->getField()->get('name');
+        if (in_array($fname, $interest))
+            # XXX: Assigning to _POST not considered great PHP
+            #      coding style
+            $vars[$fname] = $answer->getField()->getClean();
     }
+    if (!$form->isValid())
+        $errors = array_merge($errors, $form->errors());
 
     if(!$errors && $cfg->allowOnlineAttachments() && $_FILES['attachments'])
         $vars['files'] = AttachmentFile::format($_FILES['attachments'], true);
@@ -56,10 +52,8 @@ if($_POST):
         $msg='Support ticket request created';
         Draft::deleteForNamespace('ticket.client.'.substr(session_id(), -12));
         # TODO: Save dynamic form(s)
-        foreach ($forms as $f) {
-            $f->set('ticket_id', $ticket->getId());
-            $f->save();
-        }
+        $form->set('ticket_id', $ticket->getId());
+        $form->save();
         $ticket->loadDynamicData();
         //Logged in...simply view the newly created ticket.
         if($thisclient && $thisclient->isValid()) {
diff --git a/scp/dynamic-forms.php b/scp/dynamic-forms.php
deleted file mode 100644
index 13de499b0ab97fb40cdd4d9c16bd58c8c27b4410..0000000000000000000000000000000000000000
--- a/scp/dynamic-forms.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-require('admin.inc.php');
-require_once(INCLUDE_DIR."/class.dynamic_forms.php");
-
-$group=null;
-if($_REQUEST['id'] && !($group=DynamicFormset::lookup($_REQUEST['id'])))
-    $errors['err']='Unknown or invalid dynamic form ID.';
-
-if($_POST) {
-    $fields = array('title', 'notes');
-    $deleted = array();
-    switch(strtolower($_POST['do'])) {
-        case 'update':
-            foreach ($fields as $f)
-                if (isset($_POST[$f]))
-                    $group->set($f, $_POST[$f]);
-            foreach ($group->getForms() as $idx=>$form) {
-                $id = $form->get('id');
-                if ($_POST["delete-$id"] == 'on') {
-                    // Don't delete yet, in case this makes the formset
-                    // invalid. XXX: When is osTicket going to adopt database
-                    // transactions?
-                    unset($group->_forms[$idx]);
-                    $deleted[] = $form;
-                    continue;
-                }
-                foreach (array('sort','section_id') as $f)
-                    if (isset($_POST["$f-$id"]))
-                        $form->set($f, $_POST["$f-$id"]);
-                if ($form->isValid())
-                    $form->save();
-            }
-            break;
-        case 'add':
-            $group = DynamicFormset::create(array(
-                'title'=>$_POST['title'],
-                'notes'=>$_POST['notes']));
-            break;
-    }
-
-    if ($group) {
-        for ($i=0; isset($_POST["sort-new-$i"]); $i++) {
-            if (!$_POST["section_id-new-$i"])
-                continue;
-            $form = DynamicFormsetSections::create(array(
-                'formset_id'=>$group->get('id'),
-                'sort'=>$_POST["sort-new-$i"],
-                'section_id'=>$_POST["section_id-new-$i"],
-            ));
-            // XXX: Use an instrumented list to make this better
-            $group->_forms[] = $form;
-            if ($form->isValid())
-                $form->save();
-        }
-
-        if ($group->isValid()) {
-            $new = $group->__new__;
-            $group->save();
-            // Add the correct 'id' value to the attached form sections
-            if ($new) {
-                foreach ($group->getForms() as $form) {
-                    $form->set('formset_id', $group->get('id'));
-                    $form->save();
-                }
-            }
-            // Now delete requested items
-            foreach ($deleted as $form)
-                $form->delete();
-        }
-        else
-            $errors = array_merge($errors, $group->errors());
-    }
-}
-
-$page='dynamic-forms.inc.php';
-if($group || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add')))
-    $page='dynamic-form.inc.php';
-
-$nav->setTabActive('forms');
-require(STAFFINC_DIR.'header.inc.php');
-require(STAFFINC_DIR.$page);
-include(STAFFINC_DIR.'footer.inc.php');
-?>
diff --git a/scp/dynamic-form-sections.php b/scp/forms.php
similarity index 88%
rename from scp/dynamic-form-sections.php
rename to scp/forms.php
index eb1881847bb516961c958b7f1204e9eccacde023..399d8b5d0266cb593ffed9dd38bd2613afbbb641 100644
--- a/scp/dynamic-form-sections.php
+++ b/scp/forms.php
@@ -3,12 +3,12 @@ require('admin.inc.php');
 require_once(INCLUDE_DIR."/class.dynamic_forms.php");
 
 $form=null;
-if($_REQUEST['id'] && !($form=DynamicFormSection::lookup($_REQUEST['id'])))
+if($_REQUEST['id'] && !($form=DynamicForm::lookup($_REQUEST['id'])))
     $errors['err']='Unknown or invalid dynamic form ID.';
 
 if($_POST) {
     $fields = array('title', 'notes', 'instructions');
-    $required = array('name','email','subject');
+    $required = array('subject');
     switch(strtolower($_POST['do'])) {
         case 'update':
             foreach ($fields as $f)
@@ -38,7 +38,7 @@ if($_POST) {
             }
             break;
         case 'add':
-            $form = DynamicFormSection::create(array(
+            $form = DynamicForm::create(array(
                 'title'=>$_POST['title'],
                 'instructions'=>$_POST['instructions'],
                 'notes'=>$_POST['notes']));
@@ -52,7 +52,7 @@ if($_POST) {
             if (!$_POST["label-new-$i"])
                 continue;
             $field = DynamicFormField::create(array(
-                'section_id'=>$form->get('id'),
+                'form_id'=>$form->get('id'),
                 'sort'=>$_POST["sort-new-$i"],
                 'label'=>$_POST["label-new-$i"],
                 'type'=>$_POST["type-new-$i"],
@@ -68,11 +68,11 @@ if($_POST) {
     }
 }
 
-$page='dynamic-form-sections.inc.php';
+$page='dynamic-forms.inc.php';
 if($form || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add')))
-    $page='dynamic-form-section.inc.php';
+    $page='dynamic-form.inc.php';
 
-$nav->setTabActive('forms');
+$nav->setTabActive('manage');
 require(STAFFINC_DIR.'header.inc.php');
 require(STAFFINC_DIR.$page);
 include(STAFFINC_DIR.'footer.inc.php');
diff --git a/scp/dynamic-lists.php b/scp/lists.php
similarity index 98%
rename from scp/dynamic-lists.php
rename to scp/lists.php
index ec8b77fe1e75926ec540c4e6ca4a74fcfae7337f..47e736fa98707abb8237af41e5c5b7b757249c2d 100644
--- a/scp/dynamic-lists.php
+++ b/scp/lists.php
@@ -59,7 +59,7 @@ $page='dynamic-lists.inc.php';
 if($list || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add')))
     $page='dynamic-list.inc.php';
 
-$nav->setTabActive('forms');
+$nav->setTabActive('manage');
 require(STAFFINC_DIR.'header.inc.php');
 require(STAFFINC_DIR.$page);
 include(STAFFINC_DIR.'footer.inc.php');
diff --git a/scp/tickets.php b/scp/tickets.php
index 16d84ee6c3efa0bf8c73f199328ab6324f5e3a60..f7ee1ac9c97fb1ffe0586d29d52e27cb0d52f587 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -459,21 +459,18 @@ if($_POST && !$errors):
                 $ticket=null;
                 $interest=array('name','email','subject');
                 $topic=Topic::lookup($_POST['topicId']);
-                $forms=DynamicFormset::lookup($topic->ht['formset_id'])->getForms();
-                foreach ($forms as $idx=>$f) {
-                    $form=$f->getForm()->instanciate($f->sort);
-                    # Collect name, email, and subject address for banning and such
-                    foreach ($form->getAnswers() as $answer) {
-                        $fname = $answer->getField()->get('name');
-                        if (in_array($fname, $interest))
-                            # XXX: Assigning to _POST not considered great PHP
-                            #      coding style
-                            $_POST[$fname] = $answer->getField()->getClean();
-                    }
-                    $forms[$idx] = $form;
-                    if (!$form->isValid())
-                        $errors = array_merge($errors, $form->errors());
+                $form=DynamicForm::lookup($topic->ht['form_id']);
+                $form=$form->instanciate();
+                # Collect name, email, and subject address for banning and such
+                foreach ($form->getAnswers() as $answer) {
+                    $fname = $answer->getField()->get('name');
+                    if (in_array($fname, $interest))
+                        # XXX: Assigning to _POST not considered great PHP
+                        #      coding style
+                        $_POST[$fname] = $answer->getField()->getClean();
                 }
+                if (!$form->isValid())
+                    $errors = array_merge($errors, $form->errors());
                 if(!$thisstaff || !$thisstaff->canCreateTickets()) {
                      $errors['err']='You do not have permission to create tickets. Contact admin for such access';
                 } else {
@@ -485,10 +482,8 @@ if($_POST && !$errors):
                         $msg='Ticket created successfully';
                         $_REQUEST['a']=null;
                         # TODO: Save dynamic form(s)
-                        foreach ($forms as $f) {
-                            $f->set('ticket_id', $ticket->getId());
-                            $f->save();
-                        }
+                        $form->set('ticket_id', $ticket->getId());
+                        $form->save();
                         $ticket->loadDynamicData();
                         if(!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed())
                             $ticket=null;
diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql
index d37ff15db887044a94bb89b1bfa2cec6e9a359b5..8d27e2076d8a726e2daa371fc4b47b7d88600a18 100644
--- a/setup/inc/streams/core/install-mysql.sql
+++ b/setup/inc/streams/core/install-mysql.sql
@@ -170,31 +170,8 @@ INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES
   ('core', 'helpdesk_url', ''),
   ('core', 'schema_signature', '');
 
-DROP TABLE IF EXISTS `%TABLE_PREFIX%formset`;
-CREATE TABLE `%TABLE_PREFIX%formset` (
-    `id` int(11) unsigned auto_increment,
-    `title` varchar(255) NOT NULL,
-    `instructions` varchar(512),
-    `notes` text,
-    `created` datetime NOT NULL,
-    `updated` datetime NOT NULL,
-    PRIMARY KEY (`id`)
-) DEFAULT CHARSET=utf8;
-
-DROP TABLE IF EXISTS `%TABLE_PREFIX%formset_sections`;
-CREATE TABLE `%TABLE_PREFIX%formset_sections` (
-    `id` int(11) unsigned NOT NULL auto_increment,
-    `formset_id` int(11) NOT NULL,
-    `section_id` int(11) NOT NULL,
-    `title` varchar(255),
-    `instructions` text,
-    -- Allow more than one form, sorted in this order
-    `sort` int(11) NOT NULL DEFAULT 1,
-    PRIMARY KEY (`id`)
-) DEFAULT CHARSET=utf8;
-
-DROP TABLE IF EXISTS `%TABLE_PREFIX%form_section`;
-CREATE TABLE `%TABLE_PREFIX%form_section` (
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form`;
+CREATE TABLE `%TABLE_PREFIX%form` (
     `id` int(11) unsigned NOT NULL auto_increment,
     `title` varchar(255) NOT NULL,
     `instructions` varchar(512),
@@ -207,7 +184,7 @@ CREATE TABLE `%TABLE_PREFIX%form_section` (
 DROP TABLE IF EXISTS `%TABLE_PREFIX%form_field`;
 CREATE TABLE `%TABLE_PREFIX%form_field` (
     `id` int(11) unsigned NOT NULL auto_increment,
-    `section_id` int(11) unsigned NOT NULL,
+    `form_id` int(11) unsigned NOT NULL,
     `type` varchar(255) NOT NULL DEFAULT 'text',
     `label` varchar(255) NOT NULL,
     `required` tinyint(1) NOT NULL DEFAULT 0,
@@ -224,8 +201,9 @@ CREATE TABLE `%TABLE_PREFIX%form_field` (
 DROP TABLE IF EXISTS `%TABLE_PREFIX%form_entry`;
 CREATE TABLE `%TABLE_PREFIX%form_entry` (
     `id` int(11) unsigned NOT NULL auto_increment,
-    `section_id` int(11) unsigned NOT NULL,
-    `ticket_id` int(11) unsigned,
+    `form_id` int(11) unsigned NOT NULL,
+    `object_id` int(11) unsigned,
+    `object_type` char(1),
     `sort` int(11) unsigned NOT NULL DEFAULT 1,
     `created` datetime NOT NULL,
     `updated` datetime NOT NULL,
@@ -355,7 +333,7 @@ CREATE TABLE `%TABLE_PREFIX%filter` (
   `staff_id` int(10) unsigned NOT NULL default '0',
   `team_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
-  `formset_id` int(11) unsigned NOT NULL default '0',
+  `form_id` int(11) unsigned NOT NULL default '0',
   `target` ENUM(  'Any',  'Web',  'Email',  'API' ) NOT NULL DEFAULT  'Any',
   `name` varchar(32) NOT NULL default '',
   `notes` text,
@@ -474,7 +452,7 @@ CREATE TABLE `%TABLE_PREFIX%help_topic` (
   `team_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
   `page_id` int(10) unsigned NOT NULL default '0',
-  `formset_id` int(10) unsigned NOT NULL default '0',
+  `form_id` int(10) unsigned NOT NULL default '0',
   `topic` varchar(32) NOT NULL default '',
   `notes` text,
   `created` datetime NOT NULL,