This commit is contained in:
rxu 2025-05-05 09:59:06 +00:00 committed by GitHub
commit 5fd622f318
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 169 additions and 12 deletions

View file

@ -76,10 +76,16 @@ class base
}
}
// If the sort direction differs from the direction in the cache, then reverse the ids array
// If the sort direction differs from the direction in the cache, then recalculate array keys
if ($reverse_ids)
{
$stored_ids = array_reverse($stored_ids);
$keys = array_keys($stored_ids);
array_walk($keys, function (&$value, $key) use ($result_count)
{
$value = ($value >= 0) ? $result_count - $value - 1 : $value;
}
);
$stored_ids = array_combine($keys, $stored_ids);
}
for ($i = $start, $n = $start + $per_page; ($i < $n) && ($i < $result_count); $i++)
@ -130,6 +136,8 @@ class base
}
$store_ids = array_slice($id_ary, 0, $length);
$id_range = range($start, $start + $length - 1);
$store_ids = array_combine($id_range, $store_ids);
// create a new resultset if there is none for this search_key yet
// or add the ids to the existing resultset
@ -164,29 +172,26 @@ class base
$db->sql_query($sql);
$store = array(-1 => $result_count, -2 => $sort_dir);
$id_range = range($start, $start + $length - 1);
}
else
{
// we use one set of results for both sort directions so we have to calculate the indizes
// for the reversed array and we also have to reverse the ids themselves
// for the reversed array
if ($store[-2] != $sort_dir)
{
$store_ids = array_reverse($store_ids);
$id_range = range($store[-1] - $start - $length, $store[-1] - $start - 1);
}
else
{
$id_range = range($start, $start + $length - 1);
$keys = array_keys($store_ids);
array_walk($keys, function (&$value, $key) use ($store) {
$value = $store[-1] - $value - 1;
});
$store_ids = array_combine($keys, $store_ids);
}
}
$store_ids = array_combine($id_range, $store_ids);
// append the ids
if (is_array($store_ids))
{
$store += $store_ids;
ksort($store);
// if the cache is too big
if (count($store) - 2 > 20 * $config['search_block_size'])

View file

@ -221,6 +221,158 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($topic_multiple_results_count2['topic_id']);
}
public function test_caching_search_results()
{
global $phpbb_root_path;
// Sphinx search doesn't use phpBB search results caching
if (strpos($this->search_backend, 'fulltext_sphinx'))
{
$this->markTestSkipped("Sphinx search doesn't use phpBB search results caching");
}
$this->purge_cache();
$this->login();
$this->admin_login();
$crawler = self::request('GET', 'search.php?author_id=2&sr=posts');
$posts_found_text = $crawler->filter('.searchresults-title')->text();
// Get total user's post count
preg_match('!(\d+)!', $posts_found_text, $matches);
$posts_count = (int) $matches[1];
$this->assertStringContainsString("Search found $posts_count matches", $posts_found_text, $this->search_backend);
// Set this value to cache less results than total count
$sql = 'UPDATE ' . CONFIG_TABLE . '
SET config_value = ' . floor($posts_count / 3) . "
WHERE config_name = '" . $this->db->sql_escape('search_block_size') . "'";
$this->db->sql_query($sql);
// Temporarily set posts_per_page to the value allowing to get several pages (4+)
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
$form = $crawler->selectButton('Submit')->form();
$values = $form->getValues();
$current_posts_per_page = $values['config[posts_per_page]'];
$values['config[posts_per_page]'] = floor($posts_count / 10);
$form->setValues($values);
$crawler = self::submit($form);
$this->assertEquals(1, $crawler->filter('.successbox')->count(), $this->search_backend);
// Now actually test caching search results
$this->purge_cache();
// Default sort direction is 'd' (descending), browse the 1st page
$crawler = self::request('GET', 'search.php?author_id=2&sr=posts');
$pagination = $crawler->filter('.pagination')->eq(0);
$posts_found_text = $pagination->text();
$this->assertStringContainsString("Search found $posts_count matches", $posts_found_text, $this->search_backend);
// Filter all search result page links on the 1st page
$pagination = $pagination->filter('li > a')->reduce(
function ($node, $i)
{
return ($node->attr('class') == 'button');
}
);
// Get last page number
$last_page = (int) $pagination->last()->text();
// Browse the last search page
$crawler = self::$client->click($pagination->selectLink($last_page)->link());
$pagination = $crawler->filter('.pagination')->eq(0);
// Filter all search result page links on the last page
$pagination = $pagination->filter('li > a')->reduce(
function ($node, $i)
{
return ($node->attr('class') == 'button');
}
);
// Now change sort direction to ascending
$form = $crawler->selectButton('sort')->form();
$values = $form->getValues();
$values['sd'] = 'a';
$form->setValues($values);
$crawler = self::submit($form);
$pagination = $crawler->filter('.pagination')->eq(0);
// Filter all search result page links on the 1st page with new sort direction
$pagination = $pagination->filter('li > a')->reduce(
function ($node, $i)
{
return ($node->attr('class') == 'button');
}
);
// Browse the rest of search results pages with new sort direction
foreach (range(2, $last_page) as $page_number)
{
$crawler = self::$client->click($pagination->selectLink($page_number)->link());
$pagination = $crawler->filter('.pagination')->eq(0);
$pagination = $pagination->filter('li > a')->reduce(
function ($node, $i)
{
return ($node->attr('class') == 'button');
}
);
}
// Get search results cache varname
$finder = new \Symfony\Component\Finder\Finder();
$finder
->name('data_search_results_*.php')
->files()
->in($phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT);
$iterator = $finder->getIterator();
$iterator->rewind();
$cache_filename = $iterator->current();
$cache_varname = substr($cache_filename->getBasename('.php'), 4);
// Get cached post ids data
$cache = $this->get_cache_driver();
$post_ids_cached = $cache->get($cache_varname);
$post_ids_cached_backup = $post_ids_cached;
// Cached data still should have initial 'd' sort direction
$this->assertTrue($post_ids_cached[-2] === 'd', $this->search_backend);
// Cached search results count should be more than or equal to displayed one
$this->assertGreaterThanOrEqual($posts_count, $post_ids_cached[-1], $this->search_backend);
/* Check post ids cached data. Array shouldn't change after removing duplicates and re-sorting.
* That means it shouldn't have any duplicates and it should be properly ordered already
*/
unset($post_ids_cached[-2], $post_ids_cached[-1]);
unset($post_ids_cached_backup[-2], $post_ids_cached_backup[-1]);
$post_ids_cached = array_unique($post_ids_cached);
rsort($post_ids_cached);
$this->assertEquals($post_ids_cached_backup, $post_ids_cached, $this->search_backend);
// Restore this value to default
$sql = 'UPDATE ' . CONFIG_TABLE . '
SET config_value = ' . floor($posts_count / 3) . "
WHERE config_name = '" . $this->db->sql_escape('search_block_size') . "'";
$this->db->sql_query($sql);
$crawler = self::submit($form);
$this->assertEquals(1, $crawler->filter('.successbox')->count(), $this->search_backend);
// Restore posts_per_page value
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
$form = $crawler->selectButton('Submit')->form();
$values = $form->getValues();
$values['config[posts_per_page]'] = $current_posts_per_page;
$form->setValues($values);
$crawler = self::submit($form);
$this->assertEquals(1, $crawler->filter('.successbox')->count(), $this->search_backend);
}
protected function create_search_index($backend = null)
{
$this->add_lang('acp/search');