? 271833-taxonomy-filter-depth_1.patch ? 384286-1.expose-has-new-content.patch ? 436398-4-aggregator_category.patch ? 454754-11.views_comment_where_pgsql.patch ? 456104-1.form-validation-build.earl_.patch ? 461144-trim.patch ? TODO.txt ? Views 3 TODO.txt ? ajax-summary-links-attachments_0.patch ? api-tables.html_.patch ? api.txt ? book.txt ? doc ? filter_format_3.patch ? force-url-input-ltr-cvs.patch ? netbeans ? row_class_name-1.patch ? sa-629-check-plain-checkboxes.patch ? sec.patch ? set_where_group.diff ? subtle-form-fixes.patch ? test.php ? updated-cache.patch ? views-354270_0.patch ? views-377896_0.patch ? views-386098_0.patch ? views-440676-4.patch ? views-463634-empty_field_name.patch ? views-content-316556-37_0.patch ? views-drupal_alter-missing_argument_0.patch ? views-export-info_file.patch ? views-fix-line-endings_0.diff ? views-handler_user_language_0.patch ? views-more-text-2.patch ? views-rss-time.patch ? views_2_caching.patch ? views_argument_breadcrumbs.patch ? views_breadcrumb_pathfix.patch ? views_caching_4.patch ? views_filesize_format_0.patch ? views_node_access.patch ? views_taxonomy_parent_tid_argument.patch Index: includes/view.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/views/includes/view.inc,v retrieving revision 1.157 diff -u -p -r1.157 view.inc --- includes/view.inc 3 Jun 2009 00:01:01 -0000 1.157 +++ includes/view.inc 3 Jun 2009 22:36:11 -0000 @@ -803,6 +803,10 @@ class view extends views_db_object { vpr('Used cached output'); } else { + if ($cache) { + $cache->cache_start(); + } + // Initialize the style plugin. $this->init_style(); Index: plugins/views_plugin_cache.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/views/plugins/views_plugin_cache.inc,v retrieving revision 1.1 diff -u -p -r1.1 views_plugin_cache.inc --- plugins/views_plugin_cache.inc 2 Jun 2009 20:22:20 -0000 1.1 +++ plugins/views_plugin_cache.inc 3 Jun 2009 22:36:11 -0000 @@ -8,6 +8,16 @@ */ class views_plugin_cache extends views_plugin { /** + * Contains all data that should be written/read from cache. + */ + var $storage = array(); + + /** + * What table to store data in. + */ + var $table = 'cache_views_data'; + + /** * Initialize the plugin. * * @param $view @@ -21,7 +31,7 @@ class views_plugin_cache extends views_p $this->options = array(); if (is_object($display->handler)) { - // Note: The below is read only. + // Note: The below is read only. $this->options = $display->handler->get_option('cache'); } } @@ -33,21 +43,6 @@ class views_plugin_cache extends views_p function option_defaults(&$options) { } /** - * Provide the default form for setting options. - */ - function options_form(&$form, &$form_state) { } - - /** - * Provide the default form form for validating options - */ - function options_validate(&$form, &$form_state) { } - - /** - * Provide the default form form for submitting options - */ - function options_submit(&$form, &$form_state) { } - - /** * Return a string to display as the clickable title for the * access control. */ @@ -56,41 +51,122 @@ class views_plugin_cache extends views_p } /** + * Determine the expiration time of the cache type, or NULL if no expire. + * + * Plugins must override this to implement expiration. + * + * @param $type + * The cache type, either 'query', 'result' or 'output'. + */ + function cache_expire($type) { } + + /** * Save data to the cache. + * + * A plugin should override this to provide specialized caching behavior. */ - function cache_set($type, $data = NULL) { } + function cache_set($type) { + switch ($type) { + case 'query': + // Not supported currently, but this is certainly where we'd put it. + break; + case 'results': + $data = array( + 'result' => $this->view->result, + 'total_rows' => $this->view->total_rows, + 'pager' => $this->view->pager, + ); + cache_set($this->get_results_key(), $data, $this->table); + break; + case 'output': + $this->gather_headers(); + $this->storage['output'] = $this->view->display_handler->output; + cache_set($this->get_output_key(), $this->storage, $this->table); + break; + } + } + /** * Retrieve data from the cache. + * + * A plugin should override this to provide specialized caching behavior. */ function cache_get($type) { - return FALSE; + $cutoff = $this->cache_expire($type); + switch ($type) { + case 'query': + // Not supported currently, but this is certainly where we'd put it. + return FALSE; + case 'results': + // Values to set: $view->result, $view->total_rows, $view->execute_time, + // $view->pager['current_page']. + if ($cache = cache_get($this->get_results_key(), $this->table)) { + if (!$cutoff || $cache->created > $cutoff) { + $this->view->result = $cache->data['result']; + $this->view->total_rows = $cache->data['total_rows']; + $this->view->pager = $cache->data['pager']; + $this->view->execute_time = 0; + return TRUE; + } + } + return FALSE; + case 'output': + if ($cache = cache_get($this->get_output_key(), $this->table)) { + if (!$cutoff || $cache->created > $cutoff) { + $this->storage = $cache->data; + $this->view->display_handler->output = $cache->data['output']; + $this->restore_headers(); + return TRUE; + } + } + return FALSE; + } } /** - * Clear out cached data for the view. + * Clear out cached data for a view. + * + * We're just going to nuke anything related to the view, regardless of display, + * to be sure that we catch everything. Maybe that's a bad idea. */ - function cache_flush() { } - + function cache_flush() { + cache_clear_all($this->view->name . ':', $this->table, TRUE); + } + /** + * Start caching javascript, css and other out of band info. + * + * This takes a snapshot of the current system state so that we don't + * duplicate it. Later on, when gather_headers() is run, this information + * will be removed so that we don't hold onto it. + */ + function cache_start() { + $this->storage['head'] = drupal_set_html_head(); + $this->storage['css'] = drupal_add_css(); + + foreach (array('header', 'footer') as $scope) { + $this->storage['js'][$scope] = drupal_add_js(NULL, NULL, $scope); + } + } /** - * Set out-of-band-data for caching. Copied from Panels. + * Gather out of band data, compare it to what we started with and store the difference. */ function gather_headers() { // Simple replacement for head - $this->head = str_replace($this->head, '', drupal_set_html_head()); + $this->storage['head'] = str_replace($this->storage['head'], '', drupal_set_html_head()); // Slightly less simple for CSS: $css = drupal_add_css(); - $start = $this->css; - $this->css = array(); + $start = $this->storage['css']; + $this->storage['css'] = array(); foreach ($css as $media => $medias) { foreach ($medias as $type => $types) { foreach ($types as $path => $preprocess) { if (!isset($start[$media][$type][$path])) { - $this->css[] = array($path, $type, $media, $preprocess); + $this->storage['css'][] = array($path, $type, $media, $preprocess); } } } @@ -102,8 +178,8 @@ class views_plugin_cache extends views_p $js[$scope] = drupal_add_js(NULL, NULL, $scope); } - $start = $this->js; - $this->js = array(); + $start = $this->storage['js']; + $this->storage['js'] = array(); foreach ($js as $scope => $scopes) { foreach ($scopes as $type => $types) { @@ -111,15 +187,15 @@ class views_plugin_cache extends views_p if (!isset($start[$scope][$type][$id])) { switch ($type) { case 'setting': - $this->js[] = array($info, $type, $scope); + $this->storage['js'][] = array($info, $type, $scope); break; case 'inline': - $this->js[] = array($info['code'], $type, $scope, $info['defer']); + $this->storage['js'][] = array($info['code'], $type, $scope, $info['defer']); break; default: - $this->js[] = array($id, $type, $scope, $info['defer'], $info['cache']); + $this->storage['js'][] = array($id, $type, $scope, $info['defer'], $info['cache']); } } } @@ -131,18 +207,48 @@ class views_plugin_cache extends views_p * Restore out of band data saved to cache. Copied from Panels. */ function restore_headers() { - if (!empty($this->head)) { - drupal_set_html_head($this->head); + if (!empty($this->storage['head'])) { + drupal_set_html_head($this->storage['head']); } - if (!empty($this->css)) { - foreach ($this->css as $args) { + if (!empty($this->storage['css'])) { + foreach ($this->storage['css'] as $args) { call_user_func_array('drupal_add_css', $args); } } - if (!empty($this->js)) { - foreach ($this->js as $args) { + if (!empty($this->storage['js'])) { + foreach ($this->storage['js'] as $args) { call_user_func_array('drupal_add_js', $args); } } } + + function get_results_key() { + if (!isset($this->_results_key)) { + $key_data = array( + 'build_info' => $this->view->build_info, + ); + foreach (array('exposed_info', 'page', 'sort', 'order') as $key) { + if (isset($_GET[$key])) { + $key_data[$key] = $_GET[$key]; + } + } + + $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data)); + } + + return $this->_results_key; + } + + function get_output_key() { + if (!isset($this->_output_key)) { + $key_data = array( + 'result' => $this->view->result, + ); + + $this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . md5(serialize($key_data)); + } + + return $this->_output_key; + } + } Index: plugins/views_plugin_cache_none.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/views/plugins/views_plugin_cache_none.inc,v retrieving revision 1.1 diff -u -p -r1.1 views_plugin_cache_none.inc --- plugins/views_plugin_cache_none.inc 2 Jun 2009 20:22:20 -0000 1.1 +++ plugins/views_plugin_cache_none.inc 3 Jun 2009 22:36:11 -0000 @@ -5,7 +5,15 @@ * Caching plugin that provides no caching at all. */ class views_plugin_cache_none extends views_plugin_cache { + function cache_start() { /* do nothing */ } + function summary_title() { return t('None'); } + + function cache_get($type) { + return FALSE; + } + + function cache_set($type) { } } Index: plugins/views_plugin_cache_time.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/views/plugins/views_plugin_cache_time.inc,v retrieving revision 1.1 diff -u -p -r1.1 views_plugin_cache_time.inc --- plugins/views_plugin_cache_time.inc 2 Jun 2009 20:22:20 -0000 1.1 +++ plugins/views_plugin_cache_time.inc 3 Jun 2009 22:36:11 -0000 @@ -5,42 +5,16 @@ * Simple caching of query results for Views displays. */ class views_plugin_cache_time extends views_plugin_cache { - /** - * Initialize the plugin. - * - * @param $view - * The view object. - * @param $display - * The display handler. - */ - function init(&$view, &$display) { - $this->view = &$view; - $this->display = &$display; - $this->options = array(); - - if (is_object($display->handler)) { - // Note: The below is read only. - $this->options = $display->handler->get_option('cache'); - } - } - - /** - * Retrieve the default options when this is a new access - * control plugin - */ function option_defaults(&$options) { $options['results_lifespan'] = 3600; $options['output_lifespan'] = 3600; } - /** - * Provide the default form for setting options. - */ function options_form(&$form, &$form_state) { $options = array(60, 300, 1800, 3600, 21600, 518400); $options = drupal_map_assoc($options, 'format_interval'); $options = array(-1 => t('Never cache')) + $options; - + $form['results_lifespan'] = array( '#type' => 'select', '#title' => t('Query results'), @@ -57,126 +31,17 @@ class views_plugin_cache_time extends vi ); } - /** - * Provide the default form form for validating options - */ - function options_validate(&$form, &$form_state) { } - - /** - * Provide the default form form for submitting options - */ - function options_submit(&$form, &$form_state) { } - - /** - * Return a string to display as the clickable title for the - * access control. - */ function summary_title() { - return format_interval($this->options['results_lifespan'], 1) .'/'. format_interval($this->options['output_lifespan'], 1); + return format_interval($this->options['results_lifespan'], 1) . '/' . format_interval($this->options['output_lifespan'], 1); } - /** - * Save data to the cache. - */ - function cache_set($type) { - if ($lifespan = $this->options[$type .'_lifespan']) { + function cache_expire($type) { + if ($lifespan = $this->options[$type . '_lifespan']) { $cutoff = time() - $lifespan; } else { return FALSE; } - - switch ($type) { - case 'query': - // Not supported currently, but this is certainly where we'd put it. - break; - case 'results': - $data = array( - 'result' => $this->view->result, - 'total_rows' => $this->view->total_rows, - 'pager' => $this->view->pager, - ); - cache_set($this->_results_key(), $data, 'cache_views_data'); - break; - case 'output': - $this->gather_headers(); - $data = array( - 'head' => $this->head, - 'css' => $this->css, - 'js' => $this->js, - 'output' => $this->view->display_handler->output, - ); - cache_set($this->_output_key(), $data, 'cache_views_data'); - break; - } } - /** - * Retrieve data from the cache. - */ - function cache_get($type) { - if ($lifespan = $this->options[$type .'_lifespan']) { - $cutoff = time() - $lifespan; - } - else { - return FALSE; - } - - switch ($type) { - case 'query': - // Not supported currently, but this is certainly where we'd put it. - return FALSE; - case 'results': - // Values to set: $view->result, $view->total_rows, $view->execute_time, - // $view->pager['current_page']. - if ($cache = cache_get($this->_results_key(), 'cache_views_data')) { - if ($cache->created > $cutoff) { - $this->view->result = $cache->data['result']; - $this->view->total_rows = $cache->data['total_rows']; - $this->view->pager = $cache->data['pager']; - $this->view->execute_time = 0; - return TRUE; - } - } - return FALSE; - case 'output': - if ($cache = cache_get($this->_output_key(), 'cache_views_data')) { - if ($cache->created > $cutoff) { - $this->view->display_handler->output = $cache->data['output']; - $this->head = $cache->data['head']; - $this->css = $cache->data['css']; - $this->js = $cache->data['js']; - $this->restore_headers(); - return TRUE; - } - } - return FALSE; - } - } - - /** - * Clear out cached data for a view. - * - * We're jsut going to nuke anything related to the view, regardless of display, - * to be sure that we catch everything. Maybe that's a bad idea. - */ - function cache_flush() { - cache_clear_all($this->view->name .':', 'cache_views_data', TRUE); - } - - function _results_key() { - $key_data = array( - 'build_info' => $this->view->build_info, - 'exposed_info' => $this->view->exposed_info, - 'page' => $_GET['page'], - ); - return $this->view->name .':'. $this->display->id .':results:'. md5(serialize($key_data)); - } - - function _output_key() { - $key_data = array( - 'result' => $this->view->result, - ); - return $this->view->name .':'. $this->display->id .':output:'. md5(serialize($key_data)); - } }