diff --git a/blockcache_alter/blockcache_alter.info b/blockcache_alter/blockcache_alter.info
index 1de0313..dcb8b7c 100644
--- a/blockcache_alter/blockcache_alter.info
+++ b/blockcache_alter/blockcache_alter.info
@@ -1,7 +1,12 @@
 name = Block Cache Alter
 description = "Alter the cache settings per block."
 core = 7.x
-package = Performance and scalability
+package = Performance and Scalability
+
+files[] = blockcache_alter.module
+files[] = blockcache_alter.install
+files[] = blockcache_alter.js
+configure = admin/config/development/performance/blockcache_alter
 
 ; Information added by drupal.org packaging script on 2013-09-30
 version = "7.x-1.0+4-dev"
diff --git a/blockcache_alter/blockcache_alter.module b/blockcache_alter/blockcache_alter.module
index 17c62f4..d52019a 100644
--- a/blockcache_alter/blockcache_alter.module
+++ b/blockcache_alter/blockcache_alter.module
@@ -6,6 +6,61 @@
  */
 
 /**
+ * Implementation of hook_menu().
+ */
+function blockcache_alter_menu() {
+  $items = array();
+  $items['admin/config/development/performance/default'] = array(
+    'title'             => 'Performance',
+    'type'              => MENU_DEFAULT_LOCAL_TASK,
+    'file path'         => drupal_get_path('module', 'system'),
+    'weight'            => -5,
+  );
+  $items['admin/config/development/performance/blockcache_alter'] = array(
+    'type'              => MENU_LOCAL_TASK,
+    'title'             => 'Blockcache Alter',
+    'description'       => 'Debug settings for Blockcache Alter',
+    'page callback'     => 'drupal_get_form',
+    'page arguments'    => array('blockcache_alter_admin_settings'),
+    'access arguments'  => array('administer site configuration'),
+  );
+  return $items;
+}
+
+/**
+ * Menu callback, settings page for blockcache alter
+ */
+function blockcache_alter_admin_settings() {
+
+  $status = _blockcache_alter_core_patch();
+
+  $form['bca_corepatch'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Core patch ?'),
+    '#description' => t('Check this box if you applied the core patch that comes with this module. This will extend the caching settings fieldset on the block configuration page. Note: if you did not apply the patch but check the box, the additional functionality simply won\'t work at all.<br /><strong>Current status: you have @status applied a blockcache alter patch.</strong>', array('@status' => $status)),
+    '#default_value' => variable_get('bca_corepatch', 0),
+  );
+  $form['bca_debug'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Show debug information ?'),
+    '#description' => t('Debug info: shows helpful debugging whenever blocks are rendered, whether they are pulled form cache or not, and when block caches are refreshed.'),
+    '#default_value' => variable_get('bca_debug', 0),
+  );
+  $form['bca_user1'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Cache blocks for user 1 (uid 1) ?'),
+    '#description' => t('This enables block caching for the primary Drupal user (uid 1).  Can lead to unexpected results on production websites!'),
+    '#default_value' => variable_get('bca_user1', 0),
+  );
+  return system_settings_form($form);
+}
+
+function blockcache_alter_init() {
+  // Add some funky hide and show javascript.
+  drupal_add_js(drupal_get_path('module', 'blockcache_alter') . '/blockcache_alter.js');
+}
+
+/**
  * Implementation of hook_form_alter().
  */
 function blockcache_alter_form_alter(&$form, $form_state, $form_id) {
@@ -13,6 +68,9 @@ function blockcache_alter_form_alter(&$form, $form_state, $form_id) {
   // Add caching fieldset to the block configure page.
   if ($form_id == 'block_admin_configure') {
 
+    // Core patch applied or not.
+    $core_patch = variable_get('bca_corepatch', 0);
+
     // Blockcache options.
     $block_cache_options = array(
       DRUPAL_NO_CACHE => t('Do not cache'),
@@ -24,6 +82,12 @@ function blockcache_alter_form_alter(&$form, $form_state, $form_id) {
       DRUPAL_CACHE_PER_USER | DRUPAL_CACHE_PER_PAGE => t('Per user per page'),
     );
 
+    // Cache clear actions.
+    $cache_clear_actions = array(
+      '1' => t('Clear caching for this block only'),
+      '2' => t('Clear all cache (block and page)'),
+    );
+
     // Retrieve current cache setting for this block.
     $default_value = db_select('block', 'b')
       ->fields('b', array('cache'))
@@ -47,11 +111,109 @@ function blockcache_alter_form_alter(&$form, $form_state, $form_id) {
       '#description' => t('Select the appropriate cache setting for this block.'),
       '#options' => $block_cache_options,
       '#default_value' => $default_value,
+      '#attributes' => array('onChange' => 'javascript:BlockCacheAlterCheck(); return false;'),
     );
 
+    // Cache clearing option after saving this block.
+    $display = ($default_value == DRUPAL_NO_CACHE) ? 'none' : 'block';
+    $form['cache']['cache_block_clear'] = array(
+      '#type' => 'radios',
+      '#title' => t('Clear cache'),
+      '#prefix' => '<div id="blockcache_alter_wrapper" style="display: '. $display .';">',
+      '#description' => t('Select the appropriate cache clearing action after saving this block.'),
+      '#options' => $cache_clear_actions,
+      '#default_value' => 1,
+    );
+    if ($core_patch != TRUE) {
+      $form['cache']['cache_block_clear']['#suffix'] = '</div>';
+    }
+
+    // Show options underneath onl if core patch is applied.
+    if ($core_patch == TRUE) {
+
+      // Blockcache fieldset.
+      $form['cache']['option_1'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Cache refresh option 1: Cache lifetime'),
+        '#description' => t('Set a minimum cache lifetime (in seconds). Leave 0 or empty to use the second option.')
+      );
+
+      // Blockcache lifetime.
+      $form['cache']['option_1']['bc_life'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Cache lifetime'),
+        '#size' => 10,
+        '#default_value' => variable_get('bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value'], ''),
+      );
+
+      // Blockcache fieldset.
+      $form['cache']['option_2'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Cache refresh option 2: Drupal actions'),
+        '#description' => t('Refresh on certain actions in the Drupal system. When choosing node or comment action, you also need to specify on which node types it should refresh. Note that clicking any of these checkboxes will not have any effect if a minimum lifetime is set in option 1.'),
+      );
+
+      // Blockcache refresh.
+      $options = array(
+        'node' => t('A node is added/updated/deleted'),
+        'comment' => t('A comment is added/updated/deleted'),
+        'user' => t('A user is added/updated/deleted'),
+        'login' => t('A user logs in our out'),
+      );
+      // Nodequeue support.
+      if (module_exists('nodequeue') && $form['module']['#value'] == 'views' && strstr($form['delta']['#value'], 'nodequeue') !== FALSE) {
+        $options['nodequeue'] = t('A node is added or removed from a nodequeue');
+      }
+      $form['cache']['option_2']['bc_refresh'] = array(
+        '#prefix' => '<div style="float: left;">',
+        '#suffix' => '</div>',
+        '#type' => 'checkboxes',
+        '#title' => t('Refresh when'),
+        '#options' => $options,
+        '#default_value' => variable_get('bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value'], array()),
+      );
+
+      // Associate with node types.
+      $node_types = array();
+      $types = node_type_get_types();
+      foreach ($types as $type) {
+        $node_types[$type->type] = $type->name;
+      }
+
+      $form['cache']['option_2']['bc_relate'] = array(
+        '#prefix' => '<div style="float: left; margin-left: 15px;">',
+        '#suffix' => '</div><div style="clear: both;"></div>',
+        '#type' => 'checkboxes',
+        '#title' => t('Relation'),
+        '#options' => $node_types,
+        '#default_value' => variable_get('bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value'], array()),
+      );
+
+      // End div.
+      $form['cache']['enddiv'] = array(
+        '#type' => 'hidden',
+        '#suffix' => '</div>',
+      );
+
+    }
+
     // Add own submit handler.
     $form['#submit'][] = 'blockcache_alter_save_settings';
   }
+  // Alter the performance settings page: remove the #disabled key from the block_cache form completely
+  // and add a warning message instead to warn the user that block caching won't work when one
+  // at least on module implements node_grants and blockcache_alter_no_node_grants is not applied.
+  // Note, again, we don't check which patch is applied, that's up to the developer.
+  if ($form_id == 'system_performance_settings') {
+    $node_grants = $form['caching']['block_cache']['#disabled'];
+    $form['caching']['block_cache']['#disabled'] = FALSE;
+    if ($node_grants == TRUE) {
+      $form['caching']['block_cache']['#description'] = t('WARNING: There are modules implementing node grants. If you want block caching to work, you need to apply the "blockcache_alter.patch"');
+    }
+    else {
+      $form['caching']['block_cache']['#description'] = '';
+    }
+  }
 }
 
 /**
@@ -88,6 +250,37 @@ function blockcache_alter_save_settings($form, &$form_state) {
       drupal_write_record('blockcache_alter', $block);
     }
   }
+
+  // Core patch applied or not.
+  $core_patch = variable_get('bca_corepatch', 0);
+
+  // Cache clearing
+  switch ($form_state['values']['cache_block_clear']) {
+    case '1':
+      cache_clear_all($form_state['values']['module'] .':'. $form_state['values']['delta'], 'cache_block', TRUE);
+      break;
+
+    case '2':
+      cache_clear_all();
+      break;
+  }
+
+  // Store extra variables if core patch is applied.
+  if ($core_patch == TRUE) {
+    // Remove old variables to avoid clutter in the variable table.
+    variable_del('bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value']);
+    variable_del('bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value']);
+    variable_del('bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value']);
+
+    // Remember block expire time or refresh actions for the future.
+    if (!empty($form_state['values']['bc_life'])) {
+      variable_set('bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_life']);
+    }
+    else {
+      variable_set('bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_refresh']);
+      variable_set('bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_relate']);
+    }
+  }
 }
 
 /**
@@ -110,3 +303,174 @@ function blockcache_alter_block_info_alter(&$blocks, $theme, $code_blocks) {
     }
   }
 }
+
+/**
+ * Helper function to check if a blockcache alter patch is found.
+ * Note: it doesn't check which patch is applied.
+ */
+function _blockcache_alter_core_patch() {
+  $status = 'not';
+  $block_file = drupal_get_filename('module', 'block');
+  $block_contents = file_get_contents($block_file);
+  if (strpos($block_contents, 'bca_debug') !== FALSE) {
+    $status = '';
+  }
+  return $status;
+}
+
+/**
+ * Helper function to check if this block should be refreshed or not.
+ *
+ * @param stdClass $cache A complete cache object.
+ * @param int $time The current timestamp.
+ * @return FALSE or TRUE
+ */
+function _blockcache_alter_check_expire($cache, $time) {
+  if ($cache->expire == CACHE_PERMANENT) {
+    return TRUE;
+  }
+  if ($cache->expire > $time) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implementation of hook_node_insert().
+ */
+function blockcache_alter_node_insert($node) {
+  _blockcache_alter_cleanup('node', $node->type);
+  return;
+}
+
+/**
+ * Implementation of hook_node_update().
+ */
+function blockcache_alter_node_update($node) {
+  _blockcache_alter_cleanup('node', $node->type);
+  return;
+}
+
+/**
+ * Implementation of hook_node_delete().
+ */
+function blockcache_alter_node_delete($node) {
+  _blockcache_alter_cleanup('node', $node->type);
+  return;
+}
+
+/**
+ * Implementation of hook_comment_insert().
+ */
+function blockcache_alter_comment_insert($comment) {
+  $thiscnode = node_load($comment->nid);
+  $nodetype = $thiscnode->type;
+  _blockcache_alter_cleanup('comment', $nodetype);
+  return;
+}
+
+/**
+ * Implementation of hook_comment_update().
+ */
+function blockcache_alter_comment_update($comment) {
+  $thiscnode = node_load($comment->nid);
+  $nodetype = $thiscnode->type;
+  _blockcache_alter_cleanup('comment', $nodetype);
+  return;
+}
+
+/**
+ * Implementation of hook_comment_delete().
+ */
+function blockcache_alter_comment_delete($comment) {
+  $thiscnode = node_load($comment->nid);
+  $nodetype = $thiscnode->type;
+  _blockcache_alter_cleanup('comment', $nodetype);
+  return;
+}
+
+/**
+ * Implementation of hook_user_insert().
+ */
+function blockcache_alter_user_insert(&$edit, $account, $category) {
+  _blockcache_alter_cleanup('user', 'user_actions');
+  return;
+}
+
+/**
+ * Implementation of hook_user_update().
+ */
+function blockcache_alter_user_update(&$edit, $account, $category) {
+  _blockcache_alter_cleanup('user', 'user_actions');
+  return;
+}
+
+/**
+ * Implementation of hook_user_delete().
+ */
+function blockcache_alter_user_delete(&$edit, $account, $category) {
+  _blockcache_alter_cleanup('user', 'user_actions');
+  return;
+}
+
+/**
+ * Implementation of hook_user_login().
+ */
+function blockcache_alter_user_login(&$edit, $account) {
+  _blockcache_alter_cleanup('login', 'user_actions');
+  return;
+}
+
+/**
+ * Implementation of hook_user_logout().
+ */
+function blockcache_alter_user_logout(&$edit, $account) {
+  _blockcache_alter_cleanup('login', 'user_actions');
+  return;
+}
+
+/**
+ * Cleanup cached blocks if necessary.
+ *
+ * @param string $type operation type.
+ * @param string $relatednodetype Related node type (if available)
+ */
+function _blockcache_alter_cleanup($type, $relatednodetype = FALSE) {
+  $info = array();
+  $debug = variable_get('bca_debug', FALSE) && user_access('administer site configuration');
+  $modules = variable_get('blockcache_alter_include_modules', array());
+  if (!empty($modules)) {
+    $query = "SELECT module, delta FROM {block} WHERE (status = '1' OR module IN (:modules)) AND cache <> '-1'";
+    $result = db_query($query, $modules);
+  }
+  else {
+    $query = "SELECT module, delta FROM {block} WHERE status = '1' AND cache <> '-1'";
+    $result = db_query($query);
+  }
+  foreach ($result as $r) {
+    if (module_exists($r->module)) {
+      $refresh = variable_get('bc_refresh_'. $r->module .'_'. $r->delta, array());
+      if (isset($refresh[$type]) && $refresh[$type] === $type) {
+        $relate = variable_get('bc_relate_'. $r->module .'_'. $r->delta, array());
+        if ($relatednodetype == 'user_actions' || (is_array($relate) && $relate[$relatednodetype] === $relatednodetype)) {
+          cache_clear_all($r->module .':'. $r->delta, 'cache_block', TRUE);
+          if ($debug) {
+            $info[] = t('<br /> - module: %mod, delta: %delta', array('%mod' => $r->module, '%delta' => $r->delta));
+          }
+        }
+      }
+    }
+  }
+
+  // Let other modules cleanup more.
+  $hook = 'blockcache_alter_cleanup';
+  foreach (module_implements($hook) as $module) {
+    $function = $module . '_' . $hook;
+    $function($type, $relatednodetype, $info);
+  }
+
+  // Implode and put together a LIKE query.
+  if ($debug && !empty($info)) {
+    drupal_set_message(t("DEBUG: Block re-cached: ". implode('&nbsp;', $info)));
+  }
+}
