Commit 690c7977 authored by catch's avatar catch Committed by tim.plunkett

Issue #1421844 by catch, bdragon, swentel, dawehner | thebuckst0p: Fixed...

Issue #1421844 by catch, bdragon, swentel, dawehner | thebuckst0p: Fixed views_fetch_data() cache item can reach over 10mb in size.
parent 09ce9d77
......@@ -6,62 +6,101 @@
*/
/**
* Fetch Views' data from the cache
* Fetch Views' data from the cache.
*
* @param $move
* @param string|null $table
* If null return views data for all tables, else
* @param bool $move
* Under certain circumstances it makes sense to not get the moved table, but the old one.
* One example is views_get_handler.
* @param bool $reset
* If $reset is TRUE, rebuild the internal cache.
*
* @return array
* An array of views data. If $table is NULL if will contains one info array
* for each table, else just one info array.
*
* @see hook_views_data
*/
function _views_fetch_data($table = NULL, $move = TRUE, $reset = FALSE) {
$cache = &drupal_static(__FUNCTION__ . '_cache');
$recursion_protection = &drupal_static(__FUNCTION__ . '_recursion_protected');
if (!isset($cache) || $reset) {
$start = microtime(TRUE);
// NOTE: This happens whether we retrieve them from cache or otherwise.
$data = views_cache_get('views_data', TRUE);
if (!empty($data->data)) {
$cache = $data->data;
$fully_loaded = &drupal_static(__FUNCTION__ . '_fully_loaded');
if ($reset) {
$cache = NULL;
$fully_loaded = FALSE;
}
if ($table) {
if (!isset($cache[$table])) {
$cid = 'views_data:' . $table;
$data = views_cache_get($cid, TRUE);
if (!empty($data->data)) {
$cache[$table] = $data->data;
}
else {
// No cache entry, rebuild.
$cache = _views_fetch_data_build();
$fully_loaded = TRUE;
}
}
if (empty($cache)) {
views_include_handlers();
$cache = module_invoke_all('views_data');
foreach (module_implements('views_data_alter') as $module) {
$function = $module . '_views_data_alter';
$function($cache);
if (isset($cache[$table])) {
if (isset($cache[$table]['moved to']) && $move) {
$moved_table = $cache[$table]['moved to'];
if (!empty($recursion_protection[$table])) {
// recursion detected!
return NULL;
}
$recursion_protection[$table] = TRUE;
$data = _views_fetch_data($moved_table);
$recursion_protection = array();
return $data;
}
_views_data_process_entity_types($cache);
views_cache_set('views_data', $cache, TRUE);
return $cache[$table];
}
}
else {
if (!$fully_loaded) {
$data = views_cache_get('views_data', TRUE);
if (!empty($data->data)) {
$cache = $data->data;
}
if (!$table) {
return $cache;
}
if (isset($cache[$table])) {
// Support old views_data entries conversion.
if (isset($cache[$table]['moved to']) && $move) {
$moved_table = $cache[$table]['moved to'];
if (!empty($recursion_protection[$table])) {
// recursion detected!
return NULL;
if (empty($cache)) {
$cache = _views_fetch_data_build();
}
$recursion_protection[$table] = TRUE;
$data = _views_fetch_data($moved_table);
$recursion_protection = array();
return $data;
}
else {
return $cache[$table];
$fully_loaded = TRUE;
}
return $cache;
}
// Return an empty array if there is no match.
return array();
}
/**
* Build, set the views data cache if empty and return the views data.
*
* @return array
* The views_data of all tables.
*/
function _views_fetch_data_build() {
views_include_handlers();
$cache = module_invoke_all('views_data');
foreach (module_implements('views_data_alter') as $module) {
$function = $module . '_views_data_alter';
$function($cache);
}
_views_data_process_entity_types($cache);
// Keep a record with all data.
views_cache_set('views_data', $cache, TRUE);
// Save data in seperate cache entries.
foreach ($cache as $key => $data) {
$cid = 'views_data:' . $key;
views_cache_set($cid, $data, TRUE);
}
return $cache;
}
/**
* Links tables having an 'entity type' specified to the respective generic entity-type tables.
*/
......
......@@ -73,10 +73,7 @@ function setUp() {
}
// Reset views data cache.
$cache = &drupal_static('_views_fetch_data' . '_cache');
$recursion_protection = &drupal_static('_views_fetch_data' . '_recursion_protected');
$cache = NULL;
$recursion_protection = NULL;
$this->clearViewsCaches();
}
/**
......
......@@ -65,10 +65,9 @@ function setUpInstances($bundle = 'page') {
*/
function clearViewsCaches() {
// Reset views data cache.
$cache = &drupal_static('_views_fetch_data' . '_cache');
$recursion_protection = &drupal_static('_views_fetch_data' . '_recursion_protected');
$cache = NULL;
$recursion_protection = NULL;
drupal_static_reset('_views_fetch_data_cache');
drupal_static_reset('_views_fetch_data_recursion_protected');
drupal_static_reset('_views_fetch_data_fully_loaded');
}
}
<?php
/**
* @file
* Definition of Drupal\views\Tests\ViewsDataTest.
*/
namespace Drupal\views\Tests;
/**
* Tests the fetching of views data.
*
* @see hook_views_data
*/
class ViewsDataTest extends ViewTestBase {
public static function getInfo() {
return array(
'name' => 'Table Data',
'description' => 'Tests the fetching of views data.',
'group' => 'Views',
);
}
protected function setUp() {
parent::setUp();
$this->enableViewsTestModule();
}
/**
* Tests the views_fetch_data function.
*
* @see views_fetch_data
*/
public function testViewsFetchData() {
$table_name = 'views_test_data';
$expected_data = $this->viewsData();
$data = views_fetch_data($table_name);
$this->assertEqual($data, $expected_data[$table_name], 'Make sure fetching views data by table works as expected.');
$data = views_fetch_data();
$this->assertTrue(isset($data[$table_name]), 'Make sure the views_test_data info appears in the total views data.');
$this->assertEqual($data[$table_name], $expected_data[$table_name], 'Make sure the views_test_data has the expected values.');
$data = views_fetch_data(NULL, TRUE, TRUE);
$this->assertTrue(isset($data[$table_name]), 'Make sure the views_fetch_data appears in the total views data with reset = TRUE.');
$this->assertEqual($data[$table_name], $expected_data[$table_name], 'Make sure the views_test_data has the expected values.');
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment