diff --git a/cache_actions.install b/cache_actions.install
index ebbf7f3..2f50417 100644
--- a/cache_actions.install
+++ b/cache_actions.install
@@ -1,13 +1,123 @@
-<?php
-/**
- * @file
- *   Installation tasks for cache actions.
- */
-
-/**
- * Implements hook_uninstall().
- */
-function cache_actions_uninstall() {
-  // Ensure the module specific variables are deleted.
-  variable_del('cache_actions_get_cache_bins');
-}
+<?php
+/**
+ * @file
+ *   Installation tasks for cache actions.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function cache_actions_uninstall() {
+  // Ensure the module specific variables are deleted.
+  variable_del('cache_actions_get_cache_bins');
+}
+
+/**
+ * Upgrade all old panels rules to the new format.
+ */
+function cache_actions_update_7201() {
+  $rules = entity_load('rules_config');
+  $displays = array();
+  foreach ($rules as $rule) {
+    if (in_array('cache_actions', $rule->dependencies())) {
+      foreach ($rule->actions() as $action) {
+        if ($action->getElementName() == 'cache_actions_action_clear_panels_pane_cache') {
+          foreach ($action->settings['panes'] as $key) {
+            $display = _cache_actions_get_display_from_key($key);
+            if (empty($display)) {
+              continue;
+            }
+            // Collect all display that we are manipulating here.
+            if (!in_array($display, $displays)) {
+              $displays[] = $display;
+            }
+            $pane = _cache_actions_get_pane_from_key($key);
+            $i = 1;
+            foreach ($display->content as $pane_id => $panel_pane) {
+              if (is_numeric($panel_pane->pid)) {
+                $pid = 'new-' . $i;
+              }
+              else {
+                $pid = $panel_pane->pid;
+              }
+              if ($pid == $pane && !empty($panel_pane->cache['method'])
+                && $panel_pane->cache['method'] == 'rules' && empty($panel_pane->cache['settings']['new'])) {
+                $cache_key = uniqid();
+                $display->content[$pane_id]->cache['settings']['cache_key'] = $cache_key;
+                $display->content[$pane_id]->cache['settings']['new'] = TRUE;
+                $action->settings['panes'][$cache_key] = $cache_key;
+                unset($action->settings['panes'][$key]);
+                $action->save();
+              }
+              $i++;
+            }
+          }
+        }
+      }
+    }
+  }
+  foreach ($displays as $display) {
+    panels_save_display($display);
+  }
+}
+
+/**
+ * Get a display out of a key specified in the UI.
+ *
+ * @param string $key
+ *   The key.
+ *
+ * @return panels_display
+ *   The related display.
+ */
+function _cache_actions_get_display_from_key($key) {
+  static $displays = array();
+  $info = explode(':', $key);
+  if (count($info) == 1) {
+    return FALSE;
+  }
+  if ($info[0] == 'task') {
+    list(, $handler, $task) = $info;
+    $subtask = $task;
+  }
+  else {
+    list(, $handler, $task, $subtask) = $info;
+  }
+  $key = $task . ':' . $handler . ':' . $subtask;
+  if (isset($displays[$key])) {
+    return $displays[$key];
+  }
+  $task = page_manager_get_task($task);
+  $handler = page_manager_load_task_handler($task, $subtask, $handler);
+  // Save the task handler to be sure we have this handler in the database.
+  page_manager_save_task_handler($handler);
+  // In-code handlers have the displays attached to them.
+  if (isset($handler->conf['display'])) {
+    $display = $handler->conf['display'];
+  }
+  elseif (isset($handler->conf['did'])) {
+    // Otherwise we're dealing with a database display.
+    $display = panels_load_display($handler->conf['did']);
+  }
+  $displays[$key] = $display;
+  return $display;
+}
+
+/**
+ * Return the pane pid from a cache key.
+ *
+ * @param string $key
+ *   The cache key to parse.
+ *
+ * @return string
+ *   The pane pid.
+ */
+function _cache_actions_get_pane_from_key($key) {
+  $info = explode(':', $key);
+  if ($info[0] == 'task') {
+    return $info[3];
+  }
+  else {
+    return $info[4];
+  }
+}
diff --git a/cache_actions.module b/cache_actions.module
index 9b106ae..83922a6 100644
--- a/cache_actions.module
+++ b/cache_actions.module
@@ -89,3 +89,29 @@ function cache_actions_get_cache_bins() {
   }
   return $cache_bins;
 }
+
+/**
+ * Implements hook_panels_display_save().
+ * Updates any rules where we might have updated our cache keys.
+ */
+function cache_actions_panels_display_save($display) {
+  if (isset($display->cache_key)) {
+    $changed_items = variable_get('cache_actions_' . $display->cache_key, array());
+    $rules = entity_load('rules_config');
+    foreach ($changed_items as $new_key => $old_key) {
+      foreach ($rules as $rule) {
+        if (in_array('cache_actions', $rule->dependencies())) {
+          foreach ($rule->actions() as $action) {
+            if (isset($action->settings['panes'][$old_key])) {
+              unset($action->settings['panes'][$old_key]);
+              $action->settings['panes'][$new_key] = $new_key;
+              $action->save();
+              $rule_changed = TRUE;
+            }
+          }
+        }
+      }
+    }
+    variable_del('cache_actions_' . $display->cache_key);
+  }
+}
diff --git a/cache_actions.rules.inc b/cache_actions.rules.inc
index 0fd84b9..822d3e1 100644
--- a/cache_actions.rules.inc
+++ b/cache_actions.rules.inc
@@ -111,7 +111,7 @@ function cache_actions_rules_action_info() {
         ),
       ),
       'group' => t('Cache Actions'),
-      'base' => 'cache_actions_action_clear_panels_pane_cache',
+      'base' => '_cache_actions_clear_panels_cache',
     );
   }
 
@@ -129,7 +129,7 @@ function cache_actions_rules_action_info() {
         ),
       ),
       'group' => t('Cache Actions'),
-      'base' => 'cache_actions_action_clear_panels_mini_pane_cache',
+      'base' => '_cache_actions_clear_panels_cache',
     );
   }
   return $actions;
@@ -163,7 +163,6 @@ function _cache_actions_get_panels_handlers() {
           // this handler.
           $plugin = page_manager_get_task_handler($handler->handler);
           $title = page_manager_get_handler_title($plugin, $handler, $task, $subtask['name']);
-          $key = 'subtask:' . $handler->name . ':' . $handler->task . ':' . $handler->subtask;
           // Fetch available panes.
           $handler_panes = _cache_actions_load_panes($handler, $title);
           foreach ($handler_panes as $pane_key => $handler_pane) {
@@ -172,8 +171,8 @@ function _cache_actions_get_panels_handlers() {
         }
       }
     }
-    // Otherwise let's use the task.
     else {
+      // Otherwise let's use the task.
       $handlers = page_manager_load_task_handlers($task);
       if (count($handlers)) {
         foreach ($handlers as $handler) {
@@ -185,7 +184,7 @@ function _cache_actions_get_panels_handlers() {
           // Fetch available panes.
           $handler_panes = _cache_actions_load_panes($handler, $title);
           foreach ($handler_panes as $pane_key => $handler_pane) {
-            $available_handlers[$handler->task . ': ' . $title][$key . ':' . $pane_key] = $handler_pane;
+            $available_handlers[$handler->task . ': ' . $title][$pane_key] = $handler_pane;
           }
         }
       }
@@ -196,17 +195,6 @@ function _cache_actions_get_panels_handlers() {
 }
 
 /**
- * Get page variants.
- *
- * @return array
- *   Page variants.
- */
-function _cache_actions_get_page_variants() {
-  $data = _cache_actions_get_panels_handlers();
-  return $data;
-}
-
-/**
  * Get Panel Panes.
  *
  * @return array
@@ -227,21 +215,13 @@ function _cache_actions_get_mini_panel_panes() {
   $available_panes = array();
   $mini_panels = panels_mini_load_all();
   foreach ($mini_panels as $mini_panel) {
-    $i = 1;
     foreach ($mini_panel->display->content as $pane) {
       // The panes must have rule-based caching on in order for invalidation
       // to work properly.
       if (isset($pane->cache['method']) && $pane->cache['method'] == 'rules') {
         $pane_title = panels_get_pane_title($pane);
-        if (is_numeric($pane->pid)) {
-          $pane_id = 'new-' . $i;
-        }
-        else {
-          $pane_id = $pane->pid;
-        }
-        $available_panes[$mini_panel->name][$mini_panel->name . ':' . $pane_id] = $pane_title;
+        $available_panes[$mini_panel->name][$pane->cache['settings']['cache_key']] = $pane_title;
       }
-      $i++;
     }
   }
   return $available_panes;
@@ -266,187 +246,28 @@ function _cache_actions_load_panes($handler) {
     $display = $handler->conf['display'];
   }
   if (isset($display->content)) {
-    // We are going to fake panel pane names for displays which are not in code.
-    $i = 1;
     foreach ($display->content as $pane) {
-      if (isset($pane->cache['method']) && $pane->cache['method'] == 'rules') {
-        // We can't satisfy a context here, so we only get the title if no
-        // context is set.
-        if (empty($pane->configuration['context'])) {
-          $pane_title = panels_get_pane_title($pane);
-        }
-        else {
-          $pane_title = $pane->subtype;
-        }
-        if (is_numeric($pane->pid)) {
-          $pane->pid = 'new-' . $i;
-        }
-        $available_panes[$pane->pid] = $pane_title;
+      if (isset($pane->cache['method']) && $pane->cache['method'] == 'rules'
+        && !empty($pane->cache['settings']['new']) && empty($pane->cache['settings']['substitute'])) {
+        $pane_title = panels_get_pane_title($pane);
+        $available_panes[$pane->cache['settings']['cache_key']] = $pane_title;
       }
-      $i++;
     }
   }
   return $available_panes;
 }
 
 /**
- * Get a display out of a key specified in the UI.
- *
- * @param string $key
- *   The key.
- *
- * @return panels_display
- *   The related display.
- */
-function _cache_actions_get_display_from_key($key) {
-  $info = explode(':', $key);
-  if ($info[0] == 'task') {
-    list(, $handler, $task) = $info;
-    $subtask = $task;
-  }
-  else {
-    list(, $handler, $task, $subtask) = $info;
-  }
-  $task = page_manager_get_task($task);
-  $handler = page_manager_load_task_handler($task, $subtask, $handler);
-  // In-code handlers have the displays attached to them.
-  if (isset($handler->conf['display'])) {
-    $display = $handler->conf['display'];
-  }
-  // Otherwise we're dealing with a database display.
-  elseif (isset($handler->conf['did'])) {
-    $display = panels_load_display($handler->conf['did']);
-  }
-  _cache_actions_get_cache_key($handler, $display);
-  return $display;
-}
-
-/**
- * Clear the cache of panes in a mini panel.
- *
- * @param array $panes
- *   The panes to clear.
- *
- * @return VOID|FALSE
- *   Returns false if the Page Manager is disabled.
- */
-function cache_actions_action_clear_panels_pane_cache($panes) {
-  if (module_exists('page_manager')) {
-    ctools_include('plugins', 'panels');
-    $displays = array();
-    if (is_array($panes)) {
-      foreach ($panes as $key) {
-        $display = _cache_actions_get_display_from_key($key);
-        $pane = _cache_actions_get_pane_from_key($key);
-        $i = 1;
-        foreach ($display->content as $panel_pane) {
-          if (is_numeric($panel_pane->pid)) {
-            $pid = 'new-' . $i;
-          }
-          else {
-            $pid = $panel_pane->pid;
-          }
-          if ($pid == $pane && !empty($panel_pane->cache['method'])) {
-            _cache_actions_clear_pane_cache($panel_pane, $display);
-          }
-          $i++;
-        }
-      }
-    }
-  }
-  return FALSE;
-}
-
-/**
- * Return the pane pid from a cache key.
+ * Flush cached panels panes
  *
- * @param string $key
- *   The cache key to parse.
- *
- * @return string
- *   The pane pid.
- */
-function _cache_actions_get_pane_from_key($key) {
-  $info = explode(':', $key);
-  if ($info[0] == 'task') {
-    return $info[3];
-  }
-  else {
-    return $info[4];
-  }
-}
-
-/**
- * Create a unique cache key in the same way as panels does for it's
- * internal cache.
- *
- * This is a sure way to get unique cache ids for both
- * in-code displays and database displays.
- *
- * @param stdClass $handler
- *   The panels handler.
- * @param panels_display $display
- *   The used panels display.
- */
-function _cache_actions_get_cache_key($handler, &$display) {
-  $task_name = page_manager_make_task_name($handler->task, $handler->subtask);
-  $display->cache_key = 'panel_context:' . $task_name . ':' . $handler->name;
-}
-
-/**
- * Clear the content of a pane.
- *
- * @param stdClass $pane
- *   The pane to clear.
- * @param panels_display $display
- *   The display it belongs to.
- */
-function _cache_actions_clear_pane_cache($pane, $display) {
-  // Clearing panes can't be used with any other plugin than the rules plugin.
-  if ($pane->cache['method'] == 'rules') {
-    $function = panels_plugin_get_function('cache', $pane->cache['method'], 'cache clear');
-    // Specify the pane to clear. This is specific for the rules plugin.
-    $display->clear_pane = $pane;
-    if ($function) {
-      $function($display);
-    }
-  }
-}
-
-/**
- * Clear the cache of panes in a mini panel.
+ * The flush uses wildcards.
  *
  * @param array $panes
- *   The panes to clear.
- *
- * @return VOID|FALSE
- *   Returns false if the Panels Mini is disabled.
+ *   List of pane caching ids to flush.
  */
-function cache_actions_action_clear_panels_mini_pane_cache($panes) {
-  if (module_exists('panels_mini')) {
-    ctools_include('plugins', 'panels');
-    foreach ($panes as $pane) {
-      list($mini, $pane_id) = explode(':', $pane);
-      $mini = panels_mini_load($mini);
-      if (is_object($mini)) {
-        // We need to add the owner name, since this is included when it is
-        // cached.
-        $i = 1;
-        $mini->display->owner->name = $mini->name;
-        foreach ($mini->display->content as $pane) {
-          if (is_numeric($pane->pid)) {
-            $pid = 'new-' . $i;
-          }
-          else {
-            $pid = $pane->pid;
-          }
-          if ($pane_id == $pid) {
-            _cache_actions_clear_pane_cache($pane, $mini->display);
-          }
-          $i++;
-        }
-      }
-    }
+function _cache_actions_clear_panels_cache($panes) {
+  foreach ($panes as $pane) {
+    cache_clear_all($pane, 'cache', TRUE);
   }
   return FALSE;
 }
diff --git a/plugins/cache/rules.inc b/plugins/cache/rules.inc
index 7c31b11..3615547 100644
--- a/plugins/cache/rules.inc
+++ b/plugins/cache/rules.inc
@@ -14,11 +14,13 @@ $plugin = array(
   'cache clear' => 'cache_actions_rules_cache_clear_cache',
   'cache clear pane' => 'cache_actions_rules_cache_clear_pane_cache',
   'settings form' => 'cache_actions_rules_cache_settings_form',
+  'settings form validate' => 'cache_actions_rules_cache_settings_form_validate',
   'settings form submit' => 'cache_actions_rules_cache_settings_form_submit',
   'defaults' => array(
     'granularity' => 'none',
     'language' => 1,
     'cache_key' => '',
+    'substitute' => 0,
   ),
 );
 
@@ -26,20 +28,32 @@ $plugin = array(
  * Get cached content.
  */
 function cache_actions_rules_cache_get_cache($conf, $display, $args, $contexts, $pane = NULL) {
-  $cid = cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pane);
-  $cache = cache_get($cid, 'cache');
-  if (!$cache) {
-    return FALSE;
+  if (!empty($conf['new'])) {
+    $cid = cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pane);
+    $cache = cache_get($cid, 'cache');
+    if (!$cache) {
+      return FALSE;
+    }
+    return $cache->data;
+  }
+  $message = 'The panel pane %pane is using the old cache actions caching mechanism,
+      and won\'t be cached until you resave it.';
+  $parameters = array('%pane' => $pane->subtype);
+  watchdog('cache_actions', $message, $parameters, WATCHDOG_WARNING);
+  // Be very verbose for people who can control panels.
+  if (user_access('use panels caching features') && user_access('administer panels layouts')) {
+    drupal_set_message(t($message, $parameters), 'warning');
   }
-  return $cache->data;
 }
 
 /**
  * Set cached content.
  */
 function cache_actions_rules_cache_set_cache($conf, $content, $display, $args, $contexts, $pane = NULL) {
-  $cid = cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pane);
-  cache_set($cid, $content);
+  if (!empty($conf['new'])) {
+    $cid = cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pane);
+    cache_set($cid, $content);
+  }
 }
 
 /**
@@ -79,32 +93,13 @@ function cache_actions_rules_cache_clear_cache($display) {
  * Figure out an id for our cache based upon input and settings.
  */
 function cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pane) {
-  $id = 'rc';
-  // Add some text if this is a pane, so that we don't clear all panes when
-  // we clear a panel pane.
-  if ($pane) {
-    $id .= ':p';
-  }
-  if (is_numeric($display->did) && $display->did) {
-    $id .= ':' . $display->did;
+  $id = $conf['cache_key'];
+  if (!empty($display->context) && !empty($conf['substitute'])) {
+    $id = ctools_context_keyword_substitute($id, array(), $display->context);
   }
-  else {
-    // Add the cache key if this is an in-code display.
-    $id .= ':' . $conf['cache_key'];
-  }
-  // If this is a mini panel then we have the owner property. Let's
-  // use the machine name for those.
-  if (isset($display->owner->name)) {
-    $id .= ':' . $display->owner->name;
-  }
-  if ($pane) {
-    $id .= ':' . $pane->pid;
-  }
-
   if (user_access('view pane admin links')) {
     $id .= ':adm';
   }
-
   switch ($conf['granularity']) {
     case 'args':
       foreach ($args as $arg) {
@@ -155,6 +150,8 @@ function cache_actions_rules_cache_get_id($conf, $display, $args, $contexts, $pa
  *   The pane pid.
  */
 function cache_actions_rules_cache_settings_form(&$conf, $display, $pid) {
+  $form = array();
+
   $form['granularity'] = array(
     '#title' => t('Granularity'),
     '#type' => 'select',
@@ -172,13 +169,103 @@ function cache_actions_rules_cache_settings_form(&$conf, $display, $pid) {
     '#default_value' => $conf['language'],
     '#description' => t('Select this if you want to cache content per language'),
   );
+  $form['advanced'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Advanced'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  // If we encounter an old value, we should convert it to a unique id instead.
+  if (!empty($conf['cache_key']) && $conf['cache_key'] == $display->cache_key) {
+    $conf['cache_key'] = uniqid();
+  }
+  $form['advanced']['cache_key'] = array(
+    '#type' => 'textfield',
+    '#required' => TRUE,
+    '#title' => t('Cache key'),
+    '#default_value' => empty($conf['cache_key']) ? uniqid() : $conf['cache_key'],
+    '#description' => t('This is the key that will be used.
+      The granularity and language settings will be appended after this key.
+      You can use substitutions here.'),
+  );
+  $form['advanced']['substitute'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use context keywords'),
+    '#description' => t('If checked, context keywords will be substituted in this content.
+      This is not compatible with the standard cache actions clear pane action!'),
+    '#default_value' => !empty($conf['substitute']),
+  );
+  $form['advanced']['contexts'] = array(
+    '#title' => t('Substitutions'),
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $rows = array();
 
-  // This is a hack to make sure that we have the cache key for the panel
-  // at all times when we need to invalidate the cache. When all caching options
-  // are implemented in Panels for Drupal 7, we should be able to remove this.
-  $form['cache_key'] = array(
+  foreach ($display->context as $context) {
+    foreach (ctools_context_get_converters('%' . check_plain($context->keyword) . ':', $context) as $keyword => $title) {
+      $rows[] = array(
+        check_plain($keyword),
+        t('@identifier: @title', array('@title' => $title, '@identifier' => $context->identifier)),
+      );
+    }
+  }
+  $header = array(t('Keyword'), t('Value'));
+  $form['advanced']['contexts']['context'] = array('#markup' => theme('table', array('header' => $header, 'rows' => $rows)));
+  // Store the old cache key so we can look up any rules that needs changing.
+  $form['old_cache_key'] = array(
     '#type' => 'value',
-    '#value' => $display->cache_key,
+    '#value' => $conf['cache_key'],
+  );
+  // Store the display cache key so we can use it in the submit callback.
+  $form['display_cache'] = array(
+    '#type' => 'value',
+    '#value' => $conf['display_cache'],
   );
   return $form;
 }
+
+/**
+ * Validates the cache settings.
+ */
+function cache_actions_rules_cache_settings_form_validate($form, $values) {
+  $args = func_get_args();
+  $display = $form['display']['#value'];
+  $pid = $form['pid']['#value'];
+  foreach ($display->content as $pane) {
+    if ($pane->cache['method'] == 'rules' && $pid != $pane->pid && $pane->cache['settings']['cache_key'] == $values['advanced']['cache_key']) {
+      form_set_error('cache_key', t('The cache key must be unique'));
+    }
+  }
+}
+
+/**
+ * Saves the cache settings.
+ *
+ * @param array $values
+ *   The values to store.
+ */
+function cache_actions_rules_cache_settings_form_submit(&$values) {
+  $values['cache_key'] = $values['advanced']['cache_key'];
+  $values['substitute'] = $values['advanced']['substitute'];
+  // Add an indicator that this is stored with the new caching mechanism.
+  $values['new'] = TRUE;
+
+  // Store cache key updates in a variable,
+  // so that we can update any rules that may be using the old cache key.
+  if (!empty($values['old_cache_key']) && $values['old_cache_key'] != $values['cache_key']) {
+    $key = 'cache_actions_' . $values['display_cache_key'];
+    $changed_items = variable_get($key, array());
+    // Store the oldest cache key for this session under the newest key.
+    if (isset($changed_items[$values['old_cache_key']])) {
+      $changed_items[$values['cache_key']] = $changed_items[$values['old_cache_key']];
+      unset($changed_items[$values['old_cache_key']]);
+    }
+    else {
+      $changed_items[$values['cache_key']] = $values['old_cache_key'];
+    }
+    variable_set($key, $changed_items);
+  }
+  unset($values['advanced']['cache_key'], $values['advanced']['substitute'], $values['old_cache_key'], $values['display_cache_key']);
+}
