diff --git a/ctools.module b/ctools.module
index 7a80579..9fc5872 100644
--- a/ctools.module
+++ b/ctools.module
@@ -668,8 +668,7 @@ function ctools_export_ui_load($item_name, $plugin_name) {
 
   if (!$return) {
     ctools_include('export-ui');
-    $plugin = ctools_get_export_ui($plugin_name);
-    $handler = ctools_export_ui_get_handler($plugin);
+    $handler = ctools_export_ui_get_instance($plugin_name);
 
     if ($handler) {
       return $handler->load_item($item_name);
@@ -687,8 +686,7 @@ function ctools_export_ui_load($item_name, $plugin_name) {
  */
 function ctools_export_ui_task_access($plugin_name, $op, $item = NULL) {
   ctools_include('export-ui');
-  $plugin = ctools_get_export_ui($plugin_name);
-  $handler = ctools_export_ui_get_handler($plugin);
+  $handler = ctools_export_ui_get_instance($plugin_name);
 
   if ($handler) {
     return $handler->access($op, $item);
@@ -725,8 +723,7 @@ function ctools_export_ui_ctools_access_get($argument) {
   ctools_include('export-ui');
   list($plugin_name, $key) = explode(':', $argument, 2);
 
-  $plugin = ctools_get_export_ui($plugin_name);
-  $handler = ctools_export_ui_get_handler($plugin);
+  $handler = ctools_export_ui_get_instance($plugin_name);
 
   if ($handler) {
     ctools_include('context');
@@ -751,8 +748,7 @@ function ctools_export_ui_ctools_access_set($argument, $access) {
   ctools_include('export-ui');
   list($plugin_name, $key) = explode(':', $argument, 2);
 
-  $plugin = ctools_get_export_ui($plugin_name);
-  $handler = ctools_export_ui_get_handler($plugin);
+  $handler = ctools_export_ui_get_instance($plugin_name);
 
   if ($handler) {
     ctools_include('context');
diff --git a/ctools_access_ruleset/plugins/export_ui/ctools_access_ruleset.inc b/ctools_access_ruleset/plugins/export_ui/ctools_access_ruleset.inc
index d2a1c60..6437908 100644
--- a/ctools_access_ruleset/plugins/export_ui/ctools_access_ruleset.inc
+++ b/ctools_access_ruleset/plugins/export_ui/ctools_access_ruleset.inc
@@ -5,19 +5,19 @@ $plugin = array(
   'access' => 'administer ctools access ruleset',
 
   'menu' => array(
-    'menu item' => 'ctools-rulesets',
-    'menu title' => 'Custom access rulesets',
-    'menu description' => 'Add, edit or delete custom access rulesets for use with Panels and other systems that utilize CTools content plugins.',
+    'menu_item' => 'ctools-rulesets',
+    'menu_title' => 'Custom access rulesets',
+    'menu_description' => 'Add, edit or delete custom access rulesets for use with Panels and other systems that utilize CTools content plugins.',
   ),
 
-  'title singular' => t('ruleset'),
-  'title singular proper' => t('Ruleset'),
-  'title plural' => t('rulesets'),
-  'title plural proper' => t('Rulesets'),
+  'title_singular' => t('ruleset'),
+  'title_singular_proper' => t('Ruleset'),
+  'title_plural' => t('rulesets'),
+  'title_plural_proper' => t('Rulesets'),
 
   'handler' => 'ctools_access_ruleset_ui',
 
-  'use wizard' => TRUE,
+  'use_wizard' => TRUE,
   'form info' => array(
     'order' => array(
       'basic' => t('Basic information'),
diff --git a/ctools_custom_content/plugins/export_ui/ctools_custom_content.inc b/ctools_custom_content/plugins/export_ui/ctools_custom_content.inc
index 467dc58..a60119e 100644
--- a/ctools_custom_content/plugins/export_ui/ctools_custom_content.inc
+++ b/ctools_custom_content/plugins/export_ui/ctools_custom_content.inc
@@ -5,15 +5,15 @@ $plugin = array(
   'access' => 'administer custom content',
 
   'menu' => array(
-    'menu item' => 'ctools-content',
-    'menu title' => 'Custom content panes',
-    'menu description' => 'Add, edit or delete custom content panes.',
+    'menu_item' => 'ctools-content',
+    'menu_title' => 'Custom content panes',
+    'menu_description' => 'Add, edit or delete custom content panes.',
   ),
 
-  'title singular' => t('content pane'),
-  'title singular proper' => t('Content pane'),
-  'title plural' => t('content panes'),
-  'title plural proper' => t('Content panes'),
+  'title_singular' => t('content pane'),
+  'title_singular_proper' => t('Content pane'),
+  'title_plural' => t('content panes'),
+  'title_plural_proper' => t('Content panes'),
 
   'handler' => 'ctools_custom_content_ui',
 );
diff --git a/help/export-ui.html b/help/export-ui.html
index e6b1086..9a6d703 100644
--- a/help/export-ui.html
+++ b/help/export-ui.html
@@ -24,24 +24,24 @@ $plugin = array(
   // is required here. If you leave out the values, the prefix will default
   // to admin/structure and the item will default to the plugin name.
   'menu' => array(
-    'menu prefix' => 'admin/structure',
-    'menu item' => 'example',
+    'menu_prefix' => 'admin/structure',
+    'menu_item' => 'example',
     // Title of the top level menu. Note this should not be translated,
     // as the menu system will translate it.
-    'menu title' => 'Example', 
+    'menu_title' => 'Example',
     // Description of the top level menu, which is usually needed for
     // menu items in an administration list. Will be translated
     // by the menu system.
-    'menu description' => 'Administer site example objects.',
+    'menu_description' => 'Administer site example objects.',
   ),
 
   // These are required to provide proper strings for referring to the
   // actual type of exportable. "proper" means it will appear at the
   // beginning of a sentence.
-  'title singular' => t('example'),
-  'title singular proper' => t('Example'),
-  'title plural' => t('examples'),
-  'title plural proper' => t('Examples'),
+  'title_singular' => t('example'),
+  'title_singular_proper' => t('Example'),
+  'title_plural' => t('examples'),
+  'title_plural_proper' => t('Examples'),
 
   // This will provide you with a form for editing the properties on your
   // exportable, with validate and submit handler.
diff --git a/includes/dependent.inc b/includes/dependent.inc
index 74de919..163cef9 100644
--- a/includes/dependent.inc
+++ b/includes/dependent.inc
@@ -42,7 +42,7 @@
  * On any form item, add
  * - @code '#dependency' => array('id-of-form-without-the-#' => array(list, of, values, that, make, this, gadget, visible)), @endcode
  *
- * A fuller example, that hides the menu title when no menu is selected:
+ * A fuller example, that hides the menu_title when no menu is selected:
  * @code
  *function ctools_dependent_example() {
  *  $form = array();
diff --git a/includes/export-ui.inc b/includes/export-ui.inc
index 16e57d6..2639a0a 100644
--- a/includes/export-ui.inc
+++ b/includes/export-ui.inc
@@ -7,6 +7,8 @@
  * See Advanced Help for documentation.
  */
 
+use Drupal\ctools\Plugin\Type\ExportUIPluginManager;
+
 /**
  * Process an export-ui plugin to provide it with defaults.
  */
@@ -14,10 +16,10 @@ function ctools_export_ui_process(&$plugin, $info) {
   ctools_include('export');
 
   $plugin += array(
-    'has menu' => TRUE,
+    'has_menu' => TRUE,
     'title' => $plugin['name'],
     'export' => array(),
-    'allowed operations' => array(),
+    'allowed_operations' => array(),
     'menu' => array(),
     'redirect' => array(),
     'form' => array(),
@@ -28,27 +30,27 @@ function ctools_export_ui_process(&$plugin, $info) {
 
   // Provide CRUD access defaults based on the base 'access' setting:
   $plugin += array(
-    'create access' => $plugin['access'],
-    'delete access' => $plugin['access'],
+    'create_access' => $plugin['access'],
+    'delete_access' => $plugin['access'],
   );
 
-  if (empty($plugin['has menu'])) {
+  if (empty($plugin['has_menu'])) {
     return;
   }
 
   // The following keys are required and the plugin cannot be processed
   // without them.
   $keys = array(
-    'title singular',
-    'title plural',
-    'title singular proper',
-    'title plural proper',
+    'title_singular',
+    'title_plural',
+    'title_singular_proper',
+    'title_plural_proper',
     'schema',
   );
 
   foreach ($keys as $key) {
     if (empty($plugin[$key])) {
-      drupal_set_message(t('The plugin definition of @plugin is missing the %key key.', array('%key' => $key, '@plugin' => $plugin['name'])), 'error');
+      drupal_set_message(t('The plugin definition of @plugin is missing the %key key.', array('%key' => $key, '@plugin' => $plugin['id'])), 'error');
     }
   }
 
@@ -61,7 +63,7 @@ function ctools_export_ui_process(&$plugin, $info) {
   if (empty($schema)) {
     // If we're updating the schema may not have been read yet, so don't report this error in that case.
     if (!defined('MAINTENANCE_MODE')) {
-      drupal_set_message(t('The plugin definition of @plugin cannot locate schema %schema.', array('%schema' => $plugin['schema'], '@plugin' => $plugin['name'])), 'error');
+      drupal_set_message(t('The plugin definition of @plugin cannot locate schema %schema.', array('%schema' => $plugin['schema'], '@plugin' => $plugin['id'])), 'error');
     }
     return;
   }
@@ -90,7 +92,7 @@ function ctools_export_ui_process(&$plugin, $info) {
   }
 
   // Define allowed operations, and the name of the operations.
-  $plugin['allowed operations'] += array(
+  $plugin['allowed_operations'] += array(
     'edit'    => array('title' => t('Edit')),
     'enable'  => array('title' => t('Enable'), 'ajax' => TRUE, 'token' => TRUE),
     'disable' => array('title' => t('Disable'), 'ajax' => TRUE, 'token' => TRUE),
@@ -102,13 +104,13 @@ function ctools_export_ui_process(&$plugin, $info) {
   );
 
   $plugin['menu'] += array(
-    'menu item' => str_replace(' ', '-', $plugin['name']),
-    'menu prefix' => 'admin/structure',
-    'menu title' => $plugin['title'],
-    'menu description' => '',
+    'menu_item' => str_replace(' ', '-', $plugin['name']),
+    'menu_prefix' => 'admin/structure',
+    'menu_title' => $plugin['title'],
+    'menu_description' => '',
   );
   $base_path = ctools_export_ui_plugin_base_path($plugin);
-  $prefix_count = count(explode('/', $plugin['menu']['menu prefix']));
+  $prefix_count = count(explode('/', $plugin['menu']['menu_prefix']));
 
   $plugin['menu'] += array(
     // Default menu items that should be declared.
@@ -119,7 +121,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     'list callback' => array(),
     'list' => array(),
     'add' => array(),
-    'edit callback' => array(),
+    'edit_callback' => array(),
     'edit' => array(),
   );
 
@@ -129,8 +131,8 @@ function ctools_export_ui_process(&$plugin, $info) {
     // TODO: We need more flexibility in title. The title of the admin page
     // is not necessarily the title of the object, plus we need
     // plural, singular, proper, not proper, etc.
-    'title' => $plugin['menu']['menu title'],
-    'description' => $plugin['menu']['menu description'],
+    'title' => $plugin['menu']['menu_title'],
+    'description' => $plugin['menu']['menu_description'],
     'page callback' => 'ctools_export_ui_switcher_page',
     'page arguments' => array($plugin['name'], 'list'),
     'access callback' => 'ctools_export_ui_task_access',
@@ -159,7 +161,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     'type' => MENU_LOCAL_ACTION,
   );
 
-  $plugin['menu']['items']['edit callback'] += array(
+  $plugin['menu']['items']['edit_callback'] += array(
     'path' => 'list/%ctools_export_ui',
     'page callback' => 'ctools_export_ui_switcher_page',
     'page arguments' => array($plugin['name'], 'edit', $prefix_count + 2),
@@ -181,7 +183,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     'weight' => -10,
   );
 
-  if ($plugin['allowed operations']['import']) {
+  if ($plugin['allowed_operations']['import']) {
     $plugin['menu']['items'] += array('import' => array());
     $plugin['menu']['items']['import'] += array(
       'path' => 'import',
@@ -194,7 +196,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['export']) {
+  if ($plugin['allowed_operations']['export']) {
     $plugin['menu']['items'] += array('export' => array());
     $plugin['menu']['items']['export'] += array(
       'path' => 'list/%ctools_export_ui/export',
@@ -208,7 +210,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['revert']) {
+  if ($plugin['allowed_operations']['revert']) {
     $plugin['menu']['items'] += array('revert' => array());
     $plugin['menu']['items']['revert'] += array(
       'path' => 'list/%ctools_export_ui/revert',
@@ -223,7 +225,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['delete']) {
+  if ($plugin['allowed_operations']['delete']) {
     $plugin['menu']['items'] += array('delete' => array());
     $plugin['menu']['items']['delete'] += array(
       'path' => 'list/%ctools_export_ui/delete',
@@ -237,7 +239,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['clone']) {
+  if ($plugin['allowed_operations']['clone']) {
     $plugin['menu']['items'] += array('clone' => array());
     $plugin['menu']['items']['clone'] += array(
       'path' => 'list/%ctools_export_ui/clone',
@@ -251,7 +253,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['enable']) {
+  if ($plugin['allowed_operations']['enable']) {
     $plugin['menu']['items'] += array('enable' => array());
     $plugin['menu']['items']['enable'] += array(
       'path' => 'list/%ctools_export_ui/enable',
@@ -265,7 +267,7 @@ function ctools_export_ui_process(&$plugin, $info) {
     );
   }
 
-  if ($plugin['allowed operations']['disable']) {
+  if ($plugin['allowed_operations']['disable']) {
     $plugin['menu']['items'] += array('disable' => array());
     $plugin['menu']['items']['disable'] += array(
       'path' => 'list/%ctools_export_ui/disable',
@@ -309,14 +311,14 @@ function ctools_export_ui_process(&$plugin, $info) {
 
   // Strings used in drupal_set_title().
   $plugin['strings']['title'] += array(
-    'add' => t('Add a new @plugin', array('@plugin' => $plugin['title singular'])),
+    'add' => t('Add a new @plugin', array('@plugin' => $plugin['title_singular'])),
     // The "%title" will be replaced in ctools_export_ui_form(), as in this
     // stage we dont have the specific exportable object.
-    'edit' => t('Edit @plugin %title', array('@plugin' => $plugin['title singular'])),
-    'clone' => t('Clone @plugin %title', array('@plugin' => $plugin['title singular'])),
+    'edit' => t('Edit @plugin %title', array('@plugin' => $plugin['title_singular'])),
+    'clone' => t('Clone @plugin %title', array('@plugin' => $plugin['title_singular'])),
 
-    'import' => t('Import @plugin', array('@plugin' => $plugin['title singular'])),
-    'export' => t('Export @plugin %title', array('@plugin' => $plugin['title singular'])),
+    'import' => t('Import @plugin', array('@plugin' => $plugin['title_singular'])),
+    'export' => t('Export @plugin %title', array('@plugin' => $plugin['title_singular'])),
   );
 
   // Strings used in confirmation pages.
@@ -356,9 +358,9 @@ function ctools_export_ui_process(&$plugin, $info) {
 
   // Strings used in drupal_set_message().
   $plugin['strings']['message'] += array(
-    'enable' => t('@plugin %title was enabled.', array('@plugin' => $plugin['title singular proper'])),
-    'disable' => t('@plugin %title was disabled.', array('@plugin' => $plugin['title singular proper'])),
-    'no items' => t('There are no @titles to display.', array('@titles' => $plugin['title plural'])),
+    'enable' => t('@plugin %title was enabled.', array('@plugin' => $plugin['title_singular_proper'])),
+    'disable' => t('@plugin %title was disabled.', array('@plugin' => $plugin['title_singular_proper'])),
+    'no items' => t('There are no @titles to display.', array('@titles' => $plugin['title_plural'])),
   );
 }
 
@@ -368,6 +370,8 @@ function ctools_export_ui_process(&$plugin, $info) {
  * If a plugin does not define a lister class at all, then the default
  * lister class will be used.
  *
+ * @deprecated use ctools_export_ui_get_instance instead
+ *
  * @return
  *   Either the lister class or FALSE if one could not be had.
  */
@@ -393,6 +397,36 @@ function ctools_export_ui_get_handler($plugin) {
 }
 
 /**
+ * Get an instance of an export ui plugin.
+ *
+ * @param string $id
+ *   The id of the export ui plugin.
+ *
+ * @return Drupal\ctools\Plugin\ctools\export_ui\ExportUIPluginBase
+ *   The instance of the export ui plugin.
+ */
+function ctools_export_ui_get_instance($id = 'standard') {
+  $manager = ctools_export_ui_get_manager();
+  $definition = $manager->getDefinition($id);
+  if (!empty($definition)) {
+    $instance = $manager->createInstance($id);
+    $instance->init($definition);
+    return $instance;
+  }
+  else {
+    debug(format_string("instance @id not found", array('@id' => $id)));
+  }
+}
+
+function ctools_export_ui_get_manager() {
+  static $manager = NULL;
+  if (!isset($manager)) {
+    $manager = new ExportUIPluginManager();
+  }
+  return $manager;
+}
+
+/**
  * Get the base path from a plugin.
  *
  * @param $plugin
@@ -402,7 +436,7 @@ function ctools_export_ui_get_handler($plugin) {
  *   The menu path to the plugin's list.
  */
 function ctools_export_ui_plugin_base_path($plugin) {
-  return $plugin['menu']['menu prefix'] . '/' . $plugin['menu']['menu item'];
+  return $plugin['menu']['menu_prefix'] . '/' . $plugin['menu']['menu_item'];
 }
 
 /**
@@ -433,7 +467,9 @@ function ctools_export_ui_plugin_menu_path($plugin, $item_id, $export_key = NULL
  */
 function ctools_get_export_ui($plugin_name) {
   ctools_include('plugins');
-  return ctools_get_plugins('ctools', 'export_ui', $plugin_name);
+  $manager = ctools_export_ui_get_manager();
+  $definition = $manager->getDefinition($plugin_name);
+  return $definition;
 
 }
 
@@ -441,8 +477,9 @@ function ctools_get_export_ui($plugin_name) {
  * Helper function to include CTools plugins and get all export-ui exportables.
  */
 function ctools_get_export_uis() {
-  ctools_include('plugins');
-  return ctools_get_plugins('ctools', 'export_ui');
+  $manager = ctools_export_ui_get_manager();
+  $definitions = $manager->getDefinitions();
+  return $definitions;
 }
 
 /**
@@ -457,8 +494,7 @@ function ctools_export_ui_switcher_page($plugin_name, $op) {
   $js = !empty($_REQUEST['js']);
 
   // Load the $plugin information
-  $plugin = ctools_get_export_ui($plugin_name);
-  $handler = ctools_export_ui_get_handler($plugin);
+  $handler = ctools_export_ui_get_instance($plugin_name);
 
   if ($handler) {
     $method = $op . '_page';
@@ -473,3 +509,219 @@ function ctools_export_ui_switcher_page($plugin_name, $op) {
     return t('Configuration error. No handler found.');
   }
 }
+
+/**
+ * @todo Move all the form callback/helper functions into an extra .form.inc
+ *  file.
+ */
+
+// Since Drupal's forms are completely procedural, these forms will
+// mostly just be pass-throughs back to the object.
+
+/**
+ * Add all appropriate includes to forms so that caching the form
+ * still loads the files that we need.
+ */
+function _ctools_export_ui_add_form_files($form, &$form_state) {
+  ctools_form_include($form_state, 'export');
+  ctools_form_include($form_state, 'export-ui');
+
+  // Also make sure the plugin .inc file is loaded.
+  ctools_form_include_file($form_state, $form_state['object']->plugin['path'] . '/' . $form_state['object']->plugin['file']);
+}
+
+/**
+ * Form callback to handle the filter/sort form when listing items.
+ *
+ * This simply loads the object defined in the plugin and hands it off.
+ */
+function ctools_export_ui_list_form($form, $form_state) {
+  $form_state['object']->list_form($form, $form_state);
+  return $form;
+}
+
+/**
+ * Validate handler for ctools_export_ui_list_form.
+ */
+function ctools_export_ui_list_form_validate(&$form, &$form_state) {
+  $form_state['object']->list_form_validate($form, $form_state);
+}
+
+/**
+ * Submit handler for ctools_export_ui_list_form.
+ */
+function ctools_export_ui_list_form_submit(&$form, &$form_state) {
+  $form_state['object']->list_form_submit($form, $form_state);
+}
+
+/**
+ * Form callback to edit an exportable item.
+ *
+ * This simply loads the object defined in the plugin and hands it off.
+ */
+function ctools_export_ui_edit_item_form($form, &$form_state) {
+  // When called using #ajax via ajax_form_callback(), 'export' may
+  // not be included so include it here.
+  _ctools_export_ui_add_form_files($form, $form_state);
+
+  $form_state['object']->edit_form($form, $form_state);
+  return $form;
+}
+
+/**
+ * Validate handler for ctools_export_ui_edit_item_form.
+ */
+function ctools_export_ui_edit_item_form_validate(&$form, &$form_state) {
+  $form_state['object']->edit_form_validate($form, $form_state);
+}
+
+/**
+ * Submit handler for ctools_export_ui_edit_item_form.
+ */
+function ctools_export_ui_edit_item_form_submit(&$form, &$form_state) {
+  $form_state['object']->edit_form_submit($form, $form_state);
+}
+
+/**
+ * Submit handler to delete for ctools_export_ui_edit_item_form
+ *
+ * @todo Put this on a callback in the object.
+ */
+function ctools_export_ui_edit_item_form_delete(&$form, &$form_state) {
+  _ctools_export_ui_add_form_files($form, $form_state);
+
+  $export_key = $form_state['plugin']['export']['key'];
+  $path = $form_state['item']->export_type & EXPORT_IN_CODE ? 'revert' : 'delete';
+
+  drupal_goto(ctools_export_ui_plugin_menu_path($form_state['plugin'], $path, $form_state['item']->{$export_key}), array('cancel_path' => current_path()));
+}
+
+/**
+ * Validate that an export item name is acceptable and unique during add.
+ */
+function ctools_export_ui_edit_name_validate($element, &$form_state) {
+  $plugin = $form_state['plugin'];
+  // Check for string identifier sanity
+  if (!preg_match('!^[a-z0-9_]+$!', $element['#value'])) {
+    form_error($element, t('The export id can only consist of lowercase letters, underscores, and numbers.'));
+    return;
+  }
+
+  // Check for name collision
+  if (empty($form_state['item']->export_ui_allow_overwrite) && $exists = ctools_export_crud_load($plugin['schema'], $element['#value'])) {
+    form_error($element, t('A @plugin with this name already exists. Please choose another name or delete the existing item before creating a new one.', array('@plugin' => $plugin['title_singular'])));
+  }
+}
+
+/**
+ * Test for #machine_name type to see if an export exists.
+ */
+function ctools_export_ui_edit_name_exists($name, $element, &$form_state) {
+  $plugin = $form_state['plugin'];
+
+  return (empty($form_state['item']->export_ui_allow_overwrite) && ctools_export_crud_load($plugin['schema'], $name));
+}
+
+/**
+ * Delete/Revert confirm form.
+ *
+ * @todo -- call back into the object instead.
+ */
+function ctools_export_ui_delete_confirm_form($form, &$form_state) {
+  _ctools_export_ui_add_form_files($form, $form_state);
+
+  $plugin = $form_state['plugin'];
+  $item = $form_state['item'];
+
+  $form = array();
+
+  $export_key = $plugin['export']['key'];
+  $question = str_replace('%title', check_plain($item->{$export_key}), $plugin['strings']['confirmation'][$form_state['op']]['question']);
+  $path = empty($_REQUEST['cancel_path']) ? ctools_export_ui_plugin_base_path($plugin) : $_REQUEST['cancel_path'];
+
+  $form = confirm_form($form,
+    $question,
+    $path,
+    $plugin['strings']['confirmation'][$form_state['op']]['information'],
+    $plugin['allowed_operations'][$form_state['op']]['title'], t('Cancel')
+  );
+  return $form;
+}
+
+// --------------------------------------------------------------------------
+// Forms and callbacks for using the edit system with the wizard.
+
+/**
+ * Form callback to edit an exportable item using the wizard
+ *
+ * This simply loads the object defined in the plugin and hands it off.
+ */
+function ctools_export_ui_edit_item_wizard_form($form, &$form_state) {
+  _ctools_export_ui_add_form_files($form, $form_state);
+
+  $method = 'edit_form_' . $form_state['step'];
+  if (!method_exists($form_state['object'], $method)) {
+    $method = 'edit_form';
+  }
+
+  $form_state['object']->$method($form, $form_state);
+  return $form;
+}
+
+/**
+ * Validate handler for ctools_export_ui_edit_item_wizard_form.
+ */
+function ctools_export_ui_edit_item_wizard_form_validate(&$form, &$form_state) {
+  $method = 'edit_form_' . $form_state['step'] . '_validate';
+  if (!method_exists($form_state['object'], $method)) {
+    $method = 'edit_form_validate';
+  }
+
+  $form_state['object']->$method($form, $form_state);
+
+  // Additionally, if there were no errors from that, and we're finishing,
+  // perform a final validate to make sure everything is ok.
+  if (isset($form_state['clicked_button']['#wizard type']) && $form_state['clicked_button']['#wizard type'] == 'finish' && !form_get_errors()) {
+    $form_state['object']->edit_finish_validate($form, $form_state);
+  }
+}
+
+/**
+ * Submit handler for ctools_export_ui_edit_item_wizard_form.
+ */
+function ctools_export_ui_edit_item_wizard_form_submit(&$form, &$form_state) {
+  $method = 'edit_form_' . $form_state['step'] . '_submit';
+  if (!method_exists($form_state['object'], $method)) {
+    $method = 'edit_form_submit';
+  }
+
+  $form_state['object']->$method($form, $form_state);
+}
+
+/**
+ * Wizard 'back' callback when using a wizard to edit an item.
+ */
+function ctools_export_ui_wizard_back(&$form_state) {
+  $form_state['object']->edit_wizard_back($form_state);
+}
+
+/**
+ * Wizard 'next' callback when using a wizard to edit an item.
+ */
+function ctools_export_ui_wizard_next(&$form_state) {
+  $form_state['object']->edit_wizard_next($form_state);
+}
+
+/**
+ * Wizard 'cancel' callback when using a wizard to edit an item.
+ */
+function ctools_export_ui_wizard_cancel(&$form_state) {
+  $form_state['object']->edit_wizard_cancel($form_state);
+}
+
+/**
+ * Wizard 'finish' callback when using a wizard to edit an item.
+ */
+function ctools_export_ui_wizard_finish(&$form_state) {
+  $form_state['object']->edit_wizard_finish($form_state);
+}
diff --git a/includes/export-ui.menu.inc b/includes/export-ui.menu.inc
index d27bf15..3f3bfb3 100644
--- a/includes/export-ui.menu.inc
+++ b/includes/export-ui.menu.inc
@@ -14,8 +14,8 @@ function ctools_export_ui_menu(&$items) {
   foreach (ctools_get_export_uis() as $plugin) {
     // We also need to make sure that the module hasn't been disabled. During
     // the disable process, the module's plugins still still appear.
-    if ($plugin['has menu'] && module_exists($plugin['module'])) {
-      $handler = ctools_export_ui_get_handler($plugin);
+    if ($plugin['has_menu'] && module_exists($plugin['module'])) {
+      $handler = ctools_export_ui_get_instance($plugin['id']);
       if ($handler) {
         $handler->hook_menu($items);
       }
diff --git a/includes/export-ui.plugin-type.inc b/includes/export-ui.plugin-type.inc
deleted file mode 100644
index f1a7510..0000000
--- a/includes/export-ui.plugin-type.inc
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains plugin type registration information for the context tool.
- *
- * Don't actually need to declare anything for these plugin types right now,
- * apart from the fact that they exist. So, an empty array.
- */
-
-function ctools_export_ui_plugin_type(&$items) {
-  $items['export_ui'] = array(
-    'process' => array(
-      'function' => 'ctools_export_ui_process',
-      'file' => 'export-ui.inc',
-      'path' => drupal_get_path('module', 'ctools') . '/includes',
-    ),
-    'classes' => array('handler'),
-  );
-}
\ No newline at end of file
diff --git a/lib/Drupal/ctools/Plugin/Type/ExportUIPluginManager.php b/lib/Drupal/ctools/Plugin/Type/ExportUIPluginManager.php
new file mode 100644
index 0000000..4692e07
--- /dev/null
+++ b/lib/Drupal/ctools/Plugin/Type/ExportUIPluginManager.php
@@ -0,0 +1,30 @@
+<?php
+
+  /**
+   * @file
+   * Definition of Drupal\ctools\Plugin\Type\ExportUIPluginManager.
+   */
+
+namespace Drupal\ctools\Plugin\Type;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Core\Plugin\Discovery\CacheDecorator;
+
+class ExportUIPluginManager extends PluginManagerBase {
+
+  function __construct() {
+    // TODO: Implement __construct() method.
+    $this->discovery = new AnnotatedClassDiscovery('ctools', 'export_ui');
+    $this->factory = new DefaultFactory($this->discovery);
+  }
+
+  protected function processDefinition(&$definition, $plugin_id) {
+    ctools_include('export-ui');
+    ctools_export_ui_process($definition, array());
+    parent::processDefinition($definition, $plugin_id);
+  }
+
+
+}
diff --git a/plugins/export_ui/ctools_export_ui.class.php b/lib/Drupal/ctools/Plugin/ctools/export_ui/ExportUIPluginBase.php
similarity index 84%
rename from plugins/export_ui/ctools_export_ui.class.php
rename to lib/Drupal/ctools/Plugin/ctools/export_ui/ExportUIPluginBase.php
index 8cb22ba..4c200be 100644
--- a/plugins/export_ui/ctools_export_ui.class.php
+++ b/lib/Drupal/ctools/Plugin/ctools/export_ui/ExportUIPluginBase.php
@@ -1,9 +1,11 @@
 <?php
 
+namespace Drupal\ctools\Plugin\ctools\export_ui;
+
 /**
  * Base class for export UI.
  */
-class ctools_export_ui {
+class ExportUIPluginBase {
   var $plugin;
   var $name;
   var $options = array();
@@ -91,7 +93,7 @@ class ctools_export_ui {
    * string, and then additional checks as needed.
    *
    * @param $op
-   *   The 'op' of the menu item, which is defined by 'allowed operations'
+   *   The 'op' of the menu item, which is defined by 'allowed_operations'
    *   and embedded into the arguments in the menu item.
    * @param $item
    *   If an op that works on an item, then the item object, otherwise NULL.
@@ -105,17 +107,17 @@ class ctools_export_ui {
     }
 
     // More fine-grained access control:
-    if ($op == 'add' && !user_access($this->plugin['create access'])) {
+    if ($op == 'add' && !user_access($this->plugin['create_access'])) {
       return FALSE;
     }
 
     // More fine-grained access control:
-    if (($op == 'revert' || $op == 'delete') && !user_access($this->plugin['delete access'])) {
+    if (($op == 'revert' || $op == 'delete') && !user_access($this->plugin['delete_access'])) {
       return FALSE;
     }
 
     // If we need to do a token test, do it here.
-    if (!empty($this->plugin['allowed operations'][$op]['token']) && (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], $op))) {
+    if (!empty($this->plugin['allowed_operations'][$op]['token']) && (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], $op))) {
       return FALSE;
     }
 
@@ -469,7 +471,7 @@ class ctools_export_ui {
   function build_operations($item) {
     $plugin = $this->plugin;
     $schema = ctools_export_get_schema($plugin['schema']);
-    $operations = $plugin['allowed operations'];
+    $operations = $plugin['allowed_operations'];
     $operations['import'] = FALSE;
 
     if ($item->{$schema['export']['export type string']} == t('Normal')) {
@@ -644,7 +646,7 @@ class ctools_export_ui {
 
     // If a step not set, they are trying to create a new item. If a step
     // is set, they're in the process of creating an item.
-    if (!empty($this->plugin['use wizard']) && !empty($step)) {
+    if (!empty($this->plugin['use_wizard']) && !empty($step)) {
       $item = $this->edit_cache_get(NULL, 'add');
     }
     if (empty($item)) {
@@ -680,7 +682,7 @@ class ctools_export_ui {
     drupal_set_title($this->get_page_title('edit', $item));
 
     // Check to see if there is a cached item to get if we're using the wizard.
-    if (!empty($this->plugin['use wizard'])) {
+    if (!empty($this->plugin['use_wizard'])) {
       $cached = $this->edit_cache_get($item, 'edit');
       if (!empty($cached)) {
         $item = $cached;
@@ -717,7 +719,7 @@ class ctools_export_ui {
 
     // If a step not set, they are trying to create a new clone. If a step
     // is set, they're in the process of cloning an item.
-    if (!empty($this->plugin['use wizard']) && !empty($step)) {
+    if (!empty($this->plugin['use_wizard']) && !empty($step)) {
       $item = $this->edit_cache_get(NULL, 'clone');
     }
     if (empty($item)) {
@@ -764,7 +766,7 @@ class ctools_export_ui {
    * settings.
    */
   function edit_execute_form(&$form_state) {
-    if (!empty($this->plugin['use wizard'])) {
+    if (!empty($this->plugin['use_wizard'])) {
       return $this->edit_execute_form_wizard($form_state);
     }
     else {
@@ -863,7 +865,7 @@ class ctools_export_ui {
    * Execute the wizard for editing.
    *
    * For complex objects, sometimes a wizard is needed. This is normally
-   * activated by setting 'use wizard' => TRUE in the plugin definition
+   * activated by setting 'use_wizard' => TRUE in the plugin definition
    * and then creating a 'form info' array to feed the wizard the data
    * it needs.
    *
@@ -1042,7 +1044,7 @@ class ctools_export_ui {
       '#title' => t($schema['export']['key name']),
       '#type' => 'textfield',
       '#default_value' => $item->{$export_key},
-      '#description' => t('The unique ID for this @export.', array('@export' => $this->plugin['title singular'])),
+      '#description' => t('The unique ID for this @export.', array('@export' => $this->plugin['title_singular'])),
       '#required' => TRUE,
       '#maxlength' => 255,
     );
@@ -1274,7 +1276,7 @@ class ctools_export_ui {
     );
 
     $form['import'] = array(
-      '#title' => t('@plugin code', array('@plugin' => $this->plugin['title singular proper'])),
+      '#title' => t('@plugin code', array('@plugin' => $this->plugin['title_singular_proper'])),
       '#type' => 'textarea',
       '#rows' => 10,
       '#required' => TRUE,
@@ -1316,217 +1318,3 @@ class ctools_export_ui {
     // edit_form_submit() method.
   }
 }
-
-// -----------------------------------------------------------------------
-// Forms to be used with this class.
-//
-// Since Drupal's forms are completely procedural, these forms will
-// mostly just be pass-throughs back to the object.
-
-/**
- * Add all appropriate includes to forms so that caching the form
- * still loads the files that we need.
- */
-function _ctools_export_ui_add_form_files($form, &$form_state) {
-  ctools_form_include($form_state, 'export');
-  ctools_form_include($form_state, 'export-ui');
-
-  // Also make sure the plugin .inc file is loaded.
-  ctools_form_include_file($form_state, $form_state['object']->plugin['path'] . '/' . $form_state['object']->plugin['file']);
-}
-
-/**
- * Form callback to handle the filter/sort form when listing items.
- *
- * This simply loads the object defined in the plugin and hands it off.
- */
-function ctools_export_ui_list_form($form, $form_state) {
-  $form_state['object']->list_form($form, $form_state);
-  return $form;
-}
-
-/**
- * Validate handler for ctools_export_ui_list_form.
- */
-function ctools_export_ui_list_form_validate(&$form, &$form_state) {
-  $form_state['object']->list_form_validate($form, $form_state);
-}
-
-/**
- * Submit handler for ctools_export_ui_list_form.
- */
-function ctools_export_ui_list_form_submit(&$form, &$form_state) {
-  $form_state['object']->list_form_submit($form, $form_state);
-}
-
-/**
- * Form callback to edit an exportable item.
- *
- * This simply loads the object defined in the plugin and hands it off.
- */
-function ctools_export_ui_edit_item_form($form, &$form_state) {
-  // When called using #ajax via ajax_form_callback(), 'export' may
-  // not be included so include it here.
-  _ctools_export_ui_add_form_files($form, $form_state);
-
-  $form_state['object']->edit_form($form, $form_state);
-  return $form;
-}
-
-/**
- * Validate handler for ctools_export_ui_edit_item_form.
- */
-function ctools_export_ui_edit_item_form_validate(&$form, &$form_state) {
-  $form_state['object']->edit_form_validate($form, $form_state);
-}
-
-/**
- * Submit handler for ctools_export_ui_edit_item_form.
- */
-function ctools_export_ui_edit_item_form_submit(&$form, &$form_state) {
-  $form_state['object']->edit_form_submit($form, $form_state);
-}
-
-/**
- * Submit handler to delete for ctools_export_ui_edit_item_form
- *
- * @todo Put this on a callback in the object.
- */
-function ctools_export_ui_edit_item_form_delete(&$form, &$form_state) {
-  _ctools_export_ui_add_form_files($form, $form_state);
-
-  $export_key = $form_state['plugin']['export']['key'];
-  $path = $form_state['item']->export_type & EXPORT_IN_CODE ? 'revert' : 'delete';
-
-  drupal_goto(ctools_export_ui_plugin_menu_path($form_state['plugin'], $path, $form_state['item']->{$export_key}), array('cancel_path' => current_path()));
-}
-
-/**
- * Validate that an export item name is acceptable and unique during add.
- */
-function ctools_export_ui_edit_name_validate($element, &$form_state) {
-  $plugin = $form_state['plugin'];
-  // Check for string identifier sanity
-  if (!preg_match('!^[a-z0-9_]+$!', $element['#value'])) {
-    form_error($element, t('The export id can only consist of lowercase letters, underscores, and numbers.'));
-    return;
-  }
-
-  // Check for name collision
-  if (empty($form_state['item']->export_ui_allow_overwrite) && $exists = ctools_export_crud_load($plugin['schema'], $element['#value'])) {
-    form_error($element, t('A @plugin with this name already exists. Please choose another name or delete the existing item before creating a new one.', array('@plugin' => $plugin['title singular'])));
-  }
-}
-
-/**
- * Test for #machine_name type to see if an export exists.
- */
-function ctools_export_ui_edit_name_exists($name, $element, &$form_state) {
-  $plugin = $form_state['plugin'];
-
-  return (empty($form_state['item']->export_ui_allow_overwrite) && ctools_export_crud_load($plugin['schema'], $name));
-}
-
-/**
- * Delete/Revert confirm form.
- *
- * @todo -- call back into the object instead.
- */
-function ctools_export_ui_delete_confirm_form($form, &$form_state) {
-  _ctools_export_ui_add_form_files($form, $form_state);
-
-  $plugin = $form_state['plugin'];
-  $item = $form_state['item'];
-
-  $form = array();
-
-  $export_key = $plugin['export']['key'];
-  $question = str_replace('%title', check_plain($item->{$export_key}), $plugin['strings']['confirmation'][$form_state['op']]['question']);
-  $path = empty($_REQUEST['cancel_path']) ? ctools_export_ui_plugin_base_path($plugin) : $_REQUEST['cancel_path'];
-
-  $form = confirm_form($form,
-    $question,
-    $path,
-    $plugin['strings']['confirmation'][$form_state['op']]['information'],
-    $plugin['allowed operations'][$form_state['op']]['title'], t('Cancel')
-  );
-  return $form;
-}
-
-// --------------------------------------------------------------------------
-// Forms and callbacks for using the edit system with the wizard.
-
-/**
- * Form callback to edit an exportable item using the wizard
- *
- * This simply loads the object defined in the plugin and hands it off.
- */
-function ctools_export_ui_edit_item_wizard_form($form, &$form_state) {
-  _ctools_export_ui_add_form_files($form, $form_state);
-
-  $method = 'edit_form_' . $form_state['step'];
-  if (!method_exists($form_state['object'], $method)) {
-    $method = 'edit_form';
-  }
-
-  $form_state['object']->$method($form, $form_state);
-  return $form;
-}
-
-/**
- * Validate handler for ctools_export_ui_edit_item_wizard_form.
- */
-function ctools_export_ui_edit_item_wizard_form_validate(&$form, &$form_state) {
-  $method = 'edit_form_' . $form_state['step'] . '_validate';
-  if (!method_exists($form_state['object'], $method)) {
-    $method = 'edit_form_validate';
-  }
-
-  $form_state['object']->$method($form, $form_state);
-
-  // Additionally, if there were no errors from that, and we're finishing,
-  // perform a final validate to make sure everything is ok.
-  if (isset($form_state['clicked_button']['#wizard type']) && $form_state['clicked_button']['#wizard type'] == 'finish' && !form_get_errors()) {
-    $form_state['object']->edit_finish_validate($form, $form_state);
-  }
-}
-
-/**
- * Submit handler for ctools_export_ui_edit_item_wizard_form.
- */
-function ctools_export_ui_edit_item_wizard_form_submit(&$form, &$form_state) {
-  $method = 'edit_form_' . $form_state['step'] . '_submit';
-  if (!method_exists($form_state['object'], $method)) {
-    $method = 'edit_form_submit';
-  }
-
-  $form_state['object']->$method($form, $form_state);
-}
-
-/**
- * Wizard 'back' callback when using a wizard to edit an item.
- */
-function ctools_export_ui_wizard_back(&$form_state) {
-  $form_state['object']->edit_wizard_back($form_state);
-}
-
-/**
- * Wizard 'next' callback when using a wizard to edit an item.
- */
-function ctools_export_ui_wizard_next(&$form_state) {
-  $form_state['object']->edit_wizard_next($form_state);
-}
-
-/**
- * Wizard 'cancel' callback when using a wizard to edit an item.
- */
-function ctools_export_ui_wizard_cancel(&$form_state) {
-  $form_state['object']->edit_wizard_cancel($form_state);
-}
-
-/**
- * Wizard 'finish' callback when using a wizard to edit an item.
- */
-function ctools_export_ui_wizard_finish(&$form_state) {
-  $form_state['object']->edit_wizard_finish($form_state);
-}
diff --git a/lib/Drupal/ctools/Plugin/ctools/export_ui/Standard.php b/lib/Drupal/ctools/Plugin/ctools/export_ui/Standard.php
new file mode 100644
index 0000000..cf6bd76
--- /dev/null
+++ b/lib/Drupal/ctools/Plugin/ctools/export_ui/Standard.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\ctools\Plugin\ctools\export_ui\Standard.
+ */
+
+namespace Drupal\ctools\Plugin\ctools\export_ui;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * @Plugin(
+ *   id = "standard",
+ *   name = "standard",
+ *   module = "ctools",
+ *   has_menu = FALSE
+ * )
+ */
+class Standard extends ExportUIPluginBase {
+
+}
diff --git a/plugins/export_ui/ctools_export_ui.inc b/plugins/export_ui/ctools_export_ui.inc
deleted file mode 100644
index 4e0a849..0000000
--- a/plugins/export_ui/ctools_export_ui.inc
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * The default plugin exists only to provide the base class. Other plugins
- * which do not provide a class will get this class instead. Any classes
- * provided should use this class as their parent:
- *
- * @code
- *   'handler' => array(
- *     'class' => 'ctools_export_ui_mine',
- *     'parent' => 'ctools_export_ui',
- *   ),
- * @endcode
- *
- * Using the above notation will ensure that this plugin's is loaded before
- * the child plugin's class and avoid whitescreens.
- */
-$plugin = array(
-  // As this is the base class plugin, it shouldn't declare any menu items.
-  'has menu' => FALSE,
-  'handler' => array(
-    'class' => 'ctools_export_ui',
-  ),
-);
diff --git a/stylizer/plugins/export_ui/stylizer.inc b/stylizer/plugins/export_ui/stylizer.inc
index a1fc1d8..bbe56ac 100644
--- a/stylizer/plugins/export_ui/stylizer.inc
+++ b/stylizer/plugins/export_ui/stylizer.inc
@@ -7,13 +7,13 @@ $plugin = array(
   'menu' => array(
     'menu item' => 'stylizer',
     'menu title' => 'Stylizer',
-    'menu description' => 'Add, edit or delete stylizer styles.',
+    'menu_description' => 'Add, edit or delete stylizer styles.',
   ),
 
-  'title singular' => t('style'),
-  'title singular proper' => t('Style'),
-  'title plural' => t('styles'),
-  'title plural proper' => t('Styles'),
+  'title_singular' => t('style'),
+  'title_singular_proper' => t('Style'),
+  'title_plural' => t('styles'),
+  'title_plural_proper' => t('Styles'),
 
   'handler' => array(
     'class' => 'stylizer_ui',
@@ -25,7 +25,7 @@ $plugin = array(
     ),
   ),
 
-  'use wizard' => TRUE,
+  'use_wizard' => TRUE,
   'form info' => array(
     'add order' => array(
       'admin' => t('Administrative settings'),
