@@ -229,6 +229,159 @@ public function test_search_backend()
229229 $ this ->delete_topic ($ topic_multiple_results_count2 ['topic_id ' ]);
230230 }
231231
232+ public function test_caching_search_results ()
233+ {
234+ global $ phpbb_root_path ;
235+
236+ // Sphinx search doesn't use phpBB search results caching
237+ if (strpos ($ this ->search_backend , 'fulltext_sphinx ' ))
238+ {
239+ $ this ->markTestSkipped ("Sphinx search doesn't use phpBB search results caching " );
240+ }
241+
242+ $ this ->purge_cache ();
243+ $ this ->login ();
244+ $ this ->admin_login ();
245+
246+ $ crawler = self ::request ('GET ' , 'search.php?author_id=2&sr=posts ' );
247+ $ posts_found_text = $ crawler ->filter ('.searchresults-title ' )->text ();
248+
249+ // Get total user's post count
250+ preg_match ('!(\d+)! ' , $ posts_found_text , $ matches );
251+ $ posts_count = (int ) $ matches [1 ];
252+
253+ $ this ->assertStringContainsString ("Search found $ posts_count matches " , $ posts_found_text , $ this ->search_backend );
254+
255+ // Set this value to cache less results than total count
256+ $ sql = 'UPDATE ' . CONFIG_TABLE . '
257+ SET config_value = ' . floor ($ posts_count / 3 ) . "
258+ WHERE config_name = ' " . $ this ->db ->sql_escape ('search_block_size ' ) . "' " ;
259+ $ this ->db ->sql_query ($ sql );
260+
261+ // Temporarily set posts_per_page to the value allowing to get several pages (4+)
262+ $ crawler = self ::request ('GET ' , 'adm/index.php?sid= ' . $ this ->sid . '&i=acp_board&mode=post ' );
263+ $ form = $ crawler ->selectButton ('Submit ' )->form ();
264+ $ values = $ form ->getValues ();
265+ $ current_posts_per_page = $ values ['config[posts_per_page] ' ];
266+ $ values ['config[posts_per_page] ' ] = floor ($ posts_count / 10 );
267+ $ form ->setValues ($ values );
268+ $ crawler = self ::submit ($ form );
269+ $ this ->assertEquals (1 , $ crawler ->filter ('.successbox ' )->count (), $ this ->search_backend );
270+
271+ // Now actually test caching search results
272+ $ this ->purge_cache ();
273+
274+ // Default sort direction is 'd' (descending), browse the 1st page
275+ $ crawler = self ::request ('GET ' , 'search.php?author_id=2&sr=posts ' );
276+ $ pagination = $ crawler ->filter ('.pagination ' )->eq (0 );
277+ $ posts_found_text = $ pagination ->text ();
278+
279+ $ this ->assertStringContainsString ("Search found $ posts_count matches " , $ posts_found_text , $ this ->search_backend );
280+
281+ // Filter all search result page links on the 1st page
282+ $ pagination = $ pagination ->filter ('li > a ' )->reduce (
283+ function ($ node , $ i )
284+ {
285+ return ($ node ->attr ('class ' ) == 'button ' );
286+ }
287+ );
288+
289+ // Get last page number
290+ $ last_page = (int ) $ pagination ->last ()->text ();
291+
292+ // Browse the last search page
293+ $ crawler = self ::$ client ->click ($ pagination ->selectLink ($ last_page )->link ());
294+ $ pagination = $ crawler ->filter ('.pagination ' )->eq (0 );
295+
296+ // Filter all search result page links on the last page
297+ $ pagination = $ pagination ->filter ('li > a ' )->reduce (
298+ function ($ node , $ i )
299+ {
300+ return ($ node ->attr ('class ' ) == 'button ' );
301+ }
302+ );
303+
304+ // Now change sort direction to ascending
305+ $ form = $ crawler ->selectButton ('sort ' )->form ();
306+ $ values = $ form ->getValues ();
307+ $ values ['sd ' ] = 'a ' ;
308+ $ form ->setValues ($ values );
309+ $ crawler = self ::submit ($ form );
310+
311+ $ pagination = $ crawler ->filter ('.pagination ' )->eq (0 );
312+
313+ // Filter all search result page links on the 1st page with new sort direction
314+ $ pagination = $ pagination ->filter ('li > a ' )->reduce (
315+ function ($ node , $ i )
316+ {
317+ return ($ node ->attr ('class ' ) == 'button ' );
318+ }
319+ );
320+
321+ // Browse the rest of search results pages with new sort direction
322+ $ pages = range (2 , $ last_page );
323+ foreach ($ pages as $ page_number )
324+ {
325+ $ crawler = self ::$ client ->click ($ pagination ->selectLink ($ page_number )->link ());
326+ $ pagination = $ crawler ->filter ('.pagination ' )->eq (0 );
327+ $ pagination = $ pagination ->filter ('li > a ' )->reduce (
328+ function ($ node , $ i )
329+ {
330+ return ($ node ->attr ('class ' ) == 'button ' );
331+ }
332+ );
333+ }
334+
335+ // Get search results cache varname
336+ $ finder = new \Symfony \Component \Finder \Finder ();
337+ $ finder
338+ ->name ('data_search_results_*.php ' )
339+ ->files ()
340+ ->in ($ phpbb_root_path . 'cache/ ' . PHPBB_ENVIRONMENT );
341+ $ iterator = $ finder ->getIterator ();
342+ $ iterator ->rewind ();
343+ $ cache_filename = $ iterator ->current ();
344+ $ cache_varname = substr ($ cache_filename ->getBasename ('.php ' ), 4 );
345+
346+ // Get cached post ids data
347+ $ cache = $ this ->get_cache_driver ();
348+ $ post_ids_cached = $ cache ->get ($ cache_varname );
349+
350+ $ cached_results_count = count ($ post_ids_cached ) - 2 ; // Don't count '-1' and '-2' indexes
351+
352+ $ post_ids_cached_backup = $ post_ids_cached ;
353+
354+ // Cached data still should have initial 'd' sort direction
355+ $ this ->assertTrue ($ post_ids_cached [-2 ] === 'd ' , $ this ->search_backend );
356+
357+ // Cached search results count should be equal to displayed on search results page
358+ $ this ->assertEquals ($ posts_count , $ post_ids_cached [-1 ], $ this ->search_backend );
359+
360+ // Actual cached data array count should be equal to displayed on search results page too
361+ $ this ->assertEquals ($ posts_count , $ cached_results_count , $ this ->search_backend );
362+
363+ // Cached data array shouldn't change after removing duplicates. That is, it shouldn't have any duplicates.
364+ unset($ post_ids_cached [-2 ], $ post_ids_cached [-1 ]);
365+ unset($ post_ids_cached_backup [-2 ], $ post_ids_cached_backup [-1 ]);
366+ $ post_ids_cached = array_unique ($ post_ids_cached );
367+ $ this ->assertEquals ($ post_ids_cached_backup , $ post_ids_cached , $ this ->search_backend );
368+
369+ // Restore this value to default
370+ $ sql = 'UPDATE ' . CONFIG_TABLE . "
371+ SET config_value = 250
372+ WHERE config_name = ' " . $ this ->db ->sql_escape ('search_block_size ' ) . "' " ;
373+ $ this ->db ->sql_query ($ sql );
374+
375+ // Restore posts_per_page value
376+ $ crawler = self ::request ('GET ' , 'adm/index.php?sid= ' . $ this ->sid . '&i=acp_board&mode=post ' );
377+ $ form = $ crawler ->selectButton ('Submit ' )->form ();
378+ $ values = $ form ->getValues ();
379+ $ values ['config[posts_per_page] ' ] = $ current_posts_per_page ;
380+ $ form ->setValues ($ values );
381+ $ crawler = self ::submit ($ form );
382+ $ this ->assertEquals (1 , $ crawler ->filter ('.successbox ' )->count (), $ this ->search_backend );
383+ }
384+
232385 protected function create_search_index ($ backend = null )
233386 {
234387 $ this ->add_lang ('acp/search ' );
0 commit comments