Compare commits

..

14 commits

Author SHA1 Message Date
rxu
f99776d198
Merge 67afc0a1e2 into b7db1b0844 2025-05-03 11:41:25 +07:00
rxu
67afc0a1e2
[ticket/15214] Fix rebasing and some other issues
PHPBB3-15214
2025-01-10 22:01:51 +07:00
rxu
0a31489ed2
[ticket/15214] Fix Windows tests
PHPBB3-15214
2025-01-10 16:09:00 +07:00
toxyy
cb5b9823f9
[ticket/15214] Fix tests again
Adding per rxu's recommendation

PHPBB3-15214
2025-01-10 16:09:00 +07:00
rxu
059ad4a9b7
[ticket/15214] Fix Windows tests
Purge Twig compiled cache in Windows.
Set appropriate folder access control options to do that.

PHPBB3-15214
2025-01-10 16:08:59 +07:00
rxu
74f1f01a91
[ticket/15214] Fix test foo/foo extension listener
PHPBB3-15214
2025-01-10 16:08:58 +07:00
rxu
7330b0c792
[ticket/15214] Optimize event node code and add template event order tests
PHPBB3-15214
2025-01-10 16:08:56 +07:00
toxyy
127b775317
[ticket/15214] Update block, restart tests
Make docblock look a bit cleaner and restart the tests

PHPBB3-15214
2025-01-10 16:08:56 +07:00
toxyy
5b16729934
[ticket/15214] Provide usage example within event docblock
Adds similar usage examples like the event core.permissions has

PHPBB3-15214
2025-01-10 16:08:55 +07:00
toxyy
7345106f11
[ticket/15214] Replace arrow functions with anonymous functions
Arrow functions aren't added until PHP 7.4, so we can't use them yet.
Anonymous functions have been added since PHP 5.3

PHPBB3-15214
2025-01-10 16:08:54 +07:00
toxyy
b6265792d1
[ticket/15214] Add fixes for various other tests
Add new dispatch parameter to the template\twig\extension calls

PHPBB3-15214
2025-01-10 16:08:53 +07:00
toxyy
e34da0b33d
[ticket/15214] Test fix for test_bbcode_firstpass
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-01-10 16:08:53 +07:00
toxyy
5608f00f62
[ticket/15214] Test fix for test_helper_url_no_rewrite
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-01-10 16:08:52 +07:00
toxyy
827f744ca4
[ticket/15214] Add event & functionality for assigning template event priority
Event added to allow template events to be assigned priority per extension,
event location chosen so that it only fires once.
Twig node event class refactored to allow template event priority assignment,
compile calls are deferred until all locations are processed
per extension namespace.
Priority precedence mirrors Symfony priority, with higher numbers
being placed at the beginning of the array.
Duplicate priority assignment will currently have the later events
compiled before the others.

PHPBB3-15214
2025-01-10 16:08:37 +07:00
44 changed files with 166 additions and 545 deletions

View file

@ -1,116 +0,0 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\Sniffs\CodeLayout;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
/**
* Checks that union type declarations follows the coding guidelines.
*/
class UnionTypesCheckSniff implements Sniff
{
/**
* {@inheritdoc}
*/
public function register()
{
return [
T_FUNCTION,
T_CLASS,
];
}
/**
* {@inheritdoc}
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['type'] === 'T_FUNCTION')
{
$method_params = $phpcsFile->getMethodParameters($stackPtr);
$method_params_array = array_column($method_params, 'type_hint', 'token');
foreach ($method_params_array as $stack_pointer => $type_hint)
{
$this->check_union_type($phpcsFile, $stack_pointer, $type_hint);
}
$method_properties = $phpcsFile->getMethodProperties($stackPtr);
$this->check_union_type($phpcsFile, $stackPtr, $method_properties['return_type']);
}
else if ($tokens[$stackPtr]['type'] === 'T_CLASS')
{
$class_token = $tokens[$stackPtr];
$class_closer_pointer = $class_token['scope_closer'];
$first_method_pointer = $phpcsFile->findNext(T_FUNCTION, $stackPtr);
$class_members_declarations_end_pointer = $first_method_pointer ?: $class_closer_pointer;
$stack_pointer = $stackPtr;
while(($class_member_pointer = $phpcsFile->findNext(T_VARIABLE, $stack_pointer)) !== false && ($class_member_pointer < $class_members_declarations_end_pointer))
{
$properties = $phpcsFile->getMemberProperties($class_member_pointer);
$this->check_union_type($phpcsFile, $class_member_pointer, $properties['type']);
$stack_pointer = $class_member_pointer + 1;
}
}
}
public function check_union_type(File $phpcsFile, $stack_pointer, $type_hint)
{
if (empty($type_hint))
{
return;
}
if (!strpos($type_hint, '|') && $type_hint[0] == '?') // Check nullable shortcut syntax
{
$type = substr($type_hint, 1);
$error = 'Nullable shortcut syntax must not be used. Use union type instead: %1$s|null; found %2$s';
$data = [$type, $type_hint];
$phpcsFile->addError($error, $stack_pointer, 'ShortNullableSyntax', $data);
}
else if ((count($types_array = explode('|', $type_hint))) > 1) // Check union type layout
{
$types_array_null_less = $types_array;
// Check 'null' to be the last element
$null_position = array_search('null', $types_array);
if ($null_position !== false && $null_position != array_key_last($types_array))
{
$error = 'The "null" type hint must be the last of the union type elements; found %s';
$data = [implode('|', $types_array)];
$phpcsFile->addError($error, $stack_pointer, 'NullAlwaysLast', $data);
}
// Check types excepting 'null' to follow alphabetical order
if ($null_position !== false)
{
array_splice($types_array_null_less, $null_position, 1);
}
if (count($types_array_null_less) > 1)
{
$types_array_null_less_sorted = $types_array_null_less;
sort($types_array_null_less_sorted);
if (!empty(array_diff_assoc($types_array_null_less, $types_array_null_less_sorted)))
{
$error = 'Union type elements must be sorted alphabetically excepting the "null" type hint must be the last if any; found %s';
$data = [implode('|', $types_array)];
$phpcsFile->addError($error, $stack_pointer, 'AlphabeticalSort', $data);
}
}
}
}
}

View file

@ -11,8 +11,6 @@
* *
*/ */
namespace phpbb\Sniffs\Commenting;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
@ -23,7 +21,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
* @package code_sniffer * @package code_sniffer
* @author Manuel Pichler <mapi@phpundercontrol.org> * @author Manuel Pichler <mapi@phpundercontrol.org>
*/ */
class FileCommentSniff implements Sniff class phpbb_Sniffs_Commenting_FileCommentSniff implements Sniff
{ {
/** /**
* Returns an array of tokens this test wants to listen for. * Returns an array of tokens this test wants to listen for.

View file

@ -11,8 +11,6 @@
* *
*/ */
namespace phpbb\Sniffs\ControlStructures;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
@ -20,7 +18,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
* Checks that the opening brace of a control structures is on the line after. * Checks that the opening brace of a control structures is on the line after.
* From Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff * From Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff
*/ */
class OpeningBraceBsdAllmanSniff implements Sniff class phpbb_Sniffs_ControlStructures_OpeningBraceBsdAllmanSniff implements Sniff
{ {
/** /**
* Registers the tokens that this sniff wants to listen for. * Registers the tokens that this sniff wants to listen for.

View file

@ -10,7 +10,6 @@
* the docs/CREDITS.txt file. * the docs/CREDITS.txt file.
* *
*/ */
namespace phpbb\Sniffs\ControlStructures;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
@ -19,7 +18,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
* Checks that there is exactly one space between the keyword and the opening * Checks that there is exactly one space between the keyword and the opening
* parenthesis of a control structures. * parenthesis of a control structures.
*/ */
class OpeningParenthesisSniff implements Sniff class phpbb_Sniffs_ControlStructures_OpeningParenthesisSniff implements Sniff
{ {
/** /**
* Registers the tokens that this sniff wants to listen for. * Registers the tokens that this sniff wants to listen for.

View file

@ -11,8 +11,6 @@
* *
*/ */
namespace phpbb\Sniffs\ControlStructures;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
@ -20,7 +18,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
* Checks that the visibility qualifiers are placed after the static keyword * Checks that the visibility qualifiers are placed after the static keyword
* according to the coding guidelines * according to the coding guidelines
*/ */
class StaticKeywordSniff implements Sniff class phpbb_Sniffs_ControlStructures_StaticKeywordSniff implements Sniff
{ {
/** /**
* Registers the tokens that this sniff wants to listen for. * Registers the tokens that this sniff wants to listen for.

View file

@ -11,15 +11,13 @@
* *
*/ */
namespace phpbb\Sniffs\Namespaces;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
/** /**
* Checks that each use statement is used. * Checks that each use statement is used.
*/ */
class UnusedUseSniff implements Sniff class phpbb_Sniffs_Namespaces_UnusedUseSniff implements Sniff
{ {
const FIND = [ const FIND = [
T_NS_SEPARATOR, T_NS_SEPARATOR,

View file

@ -17,6 +17,9 @@
<!-- There MUST not be more than one statement per line. --> <!-- There MUST not be more than one statement per line. -->
<rule ref="Generic.Formatting.DisallowMultipleStatements" /> <rule ref="Generic.Formatting.DisallowMultipleStatements" />
<!-- Call-time pass-by-reference MUST not be used. -->
<rule ref="Generic.Functions.CallTimePassByReference.NotAllowed" />
<!-- Filenames MUST be lowercase. --> <!-- Filenames MUST be lowercase. -->
<rule ref="Generic.Files.LowercasedFilename" /> <rule ref="Generic.Files.LowercasedFilename" />

View file

@ -45,8 +45,4 @@
<!-- There MUST NOT be unused use statements. --> <!-- There MUST NOT be unused use statements. -->
<rule ref="./phpbb/Sniffs/Namespaces/UnusedUseSniff.php" /> <rule ref="./phpbb/Sniffs/Namespaces/UnusedUseSniff.php" />
<!-- The null type SHALL be the last union type element, other types SHALL follow alphabetical order.
No nullable type shortcut syntax should be used. -->
<rule ref="./phpbb/Sniffs/CodeLayout/UnionTypesCheckSniff.php" />
</ruleset> </ruleset>

10
phpBB/composer.lock generated
View file

@ -9459,16 +9459,16 @@
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
"version": "3.13.0", "version": "3.12.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
"reference": "65ff2489553b83b4597e89c3b8b721487011d186" "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186", "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa",
"reference": "65ff2489553b83b4597e89c3b8b721487011d186", "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9539,7 +9539,7 @@
"type": "thanks_dev" "type": "thanks_dev"
} }
], ],
"time": "2025-05-11T03:36:00+00:00" "time": "2025-04-13T04:10:18+00:00"
}, },
{ {
"name": "symfony/browser-kit", "name": "symfony/browser-kit",

View file

@ -40,6 +40,7 @@ services:
- '@template_context' - '@template_context'
- '@template.twig.environment' - '@template.twig.environment'
- '@language' - '@language'
- '@dispatcher'
tags: tags:
- { name: twig.extension } - { name: twig.extension }

View file

@ -1746,33 +1746,29 @@ overall_header_body_before
overall_header_breadcrumb_append overall_header_breadcrumb_append
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-a1 * Since: 3.1.0-a1
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add links to the list of breadcrumbs in the header * Purpose: Add links to the list of breadcrumbs in the header
overall_header_breadcrumb_prepend overall_header_breadcrumb_prepend
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-RC3 * Since: 3.1.0-RC3
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add links to the list of breadcrumbs in the header (after site-home, but before board-index) * Purpose: Add links to the list of breadcrumbs in the header (after site-home, but before board-index)
overall_header_breadcrumbs_after overall_header_breadcrumbs_after
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-RC3 * Since: 3.1.0-RC3
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add content after the breadcrumbs (outside of the breadcrumbs container) * Purpose: Add content after the breadcrumbs (outside of the breadcrumbs container)
overall_header_breadcrumbs_before overall_header_breadcrumbs_before
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-RC3 * Since: 3.1.0-RC3
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add content before the breadcrumbs (outside of the breadcrumbs container) * Purpose: Add content before the breadcrumbs (outside of the breadcrumbs container)
overall_header_content_before overall_header_content_before
@ -1834,17 +1830,15 @@ overall_header_navigation_prepend
overall_header_navlink_append overall_header_navlink_append
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-b3 * Since: 3.1.0-b3
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add content after each individual navlink (breadcrumb) * Purpose: Add content after each individual navlink (breadcrumb)
overall_header_navlink_prepend overall_header_navlink_prepend
=== ===
* Locations: * Locations:
+ styles/prosilver/template/breadcrumbs.html + styles/prosilver/template/navbar_header.html
* Since: 3.1.0-b3 * Since: 3.1.0-b3
* Changed: 4.0.0-a1 Moved to breadcrumbs.html
* Purpose: Add content before each individual navlink (breadcrumb) * Purpose: Add content before each individual navlink (breadcrumb)
overall_header_page_body_before overall_header_page_body_before

View file

@ -475,41 +475,6 @@ class acp_profile
$cp->vars[$key] = $var; $cp->vars[$key] = $var;
} }
// step 3 - all arrays
if ($action == 'edit')
{
// Get language entries
$sql = 'SELECT *
FROM ' . PROFILE_FIELDS_LANG_TABLE . '
WHERE lang_id <> ' . $this->edit_lang_id . "
AND field_id = $field_id
ORDER BY option_id ASC";
$result = $db->sql_query($sql);
$l_lang_options = [];
while ($row = $db->sql_fetchrow($result))
{
$l_lang_options[$row['lang_id']][$row['option_id']] = $row['lang_value'];
}
$db->sql_freeresult($result);
$sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value
FROM ' . PROFILE_LANG_TABLE . '
WHERE lang_id <> ' . $this->edit_lang_id . "
AND field_id = $field_id
ORDER BY lang_id ASC";
$result = $db->sql_query($sql);
$l_lang_name = $l_lang_explain = $l_lang_default_value = [];
while ($row = $db->sql_fetchrow($result))
{
$l_lang_name[$row['lang_id']] = $row['lang_name'];
$l_lang_explain[$row['lang_id']] = $row['lang_explain'];
$l_lang_default_value[$row['lang_id']] = $row['lang_default_value'];
}
$db->sql_freeresult($result);
}
foreach ($exclude[3] as $key) foreach ($exclude[3] as $key)
{ {
$cp->vars[$key] = $request->variable($key, array(0 => ''), true); $cp->vars[$key] = $request->variable($key, array(0 => ''), true);

View file

@ -70,12 +70,12 @@ class request implements request_interface
foreach ($this->super_globals as $const => $super_global) foreach ($this->super_globals as $const => $super_global)
{ {
$this->input[$const] = isset($GLOBALS[$super_global]) ? (array) $GLOBALS[$super_global] : array(); $this->input[$const] = isset($GLOBALS[$super_global]) ? $GLOBALS[$super_global] : array();
} }
// simulate request_order = GP // simulate request_order = GP
$this->original_request = (array) $this->input[request_interface::REQUEST]; $this->original_request = $this->input[request_interface::REQUEST];
$this->input[request_interface::REQUEST] = (array) $this->input[request_interface::POST] + (array) $this->input[request_interface::GET]; $this->input[request_interface::REQUEST] = $this->input[request_interface::POST] + $this->input[request_interface::GET];
if ($disable_super_globals) if ($disable_super_globals)
{ {

View file

@ -33,7 +33,7 @@ class loader_resolver implements LoaderResolverInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function resolve($resource, $type = null): \Symfony\Component\Config\Loader\LoaderInterface|false public function resolve($resource, $type = null): false|\Symfony\Component\Config\Loader\LoaderInterface
{ {
/** @var \Symfony\Component\Config\Loader\LoaderInterface $loader */ /** @var \Symfony\Component\Config\Loader\LoaderInterface $loader */
foreach ($this->loaders as $loader) foreach ($this->loaders as $loader)

View file

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

View file

@ -550,6 +550,7 @@ class fulltext_mysql extends base implements search_backend_interface
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
// if the total result count is not cached yet, retrieve it from the db // if the total result count is not cached yet, retrieve it from the db
if (!$result_count && count($id_ary)) if (!$result_count && count($id_ary))
{ {
@ -575,9 +576,9 @@ class fulltext_mysql extends base implements search_backend_interface
$id_ary[] = (int) $row[$field]; $id_ary[] = (int) $row[$field];
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
}
$id_ary = array_unique($id_ary); $id_ary = array_unique($id_ary);
}
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
@ -757,8 +758,6 @@ class fulltext_mysql extends base implements search_backend_interface
// Build the query for really selecting the post_ids // Build the query for really selecting the post_ids
if ($type == 'posts') if ($type == 'posts')
{ {
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
$sql = "SELECT $sql_select $sql = "SELECT $sql_select
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . " FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
WHERE $sql_author WHERE $sql_author
@ -822,9 +821,9 @@ class fulltext_mysql extends base implements search_backend_interface
$id_ary[] = (int) $row[$field]; $id_ary[] = (int) $row[$field];
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
}
$id_ary = array_unique($id_ary); $id_ary = array_unique($id_ary);
}
if (count($id_ary)) if (count($id_ary))
{ {

View file

@ -1004,8 +1004,6 @@ class fulltext_native extends base implements search_backend_interface
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
} }
$id_ary = array_unique($id_ary);
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this->save_ids($search_key, $this->search_query, $author_ary, $total_results, $id_ary, $start, $sort_dir); $this->save_ids($search_key, $this->search_query, $author_ary, $total_results, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, (int) $per_page); $id_ary = array_slice($id_ary, 0, (int) $per_page);
@ -1227,8 +1225,6 @@ class fulltext_native extends base implements search_backend_interface
// Build the query for really selecting the post_ids // Build the query for really selecting the post_ids
if ($type == 'posts') if ($type == 'posts')
{ {
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
$sql = "SELECT $select $sql = "SELECT $select
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t' : '') . " FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t' : '') . "
WHERE $sql_author WHERE $sql_author
@ -1293,8 +1289,6 @@ class fulltext_native extends base implements search_backend_interface
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
} }
$id_ary = array_unique($id_ary);
if (count($id_ary)) if (count($id_ary))
{ {
$this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir); $this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir);

View file

@ -478,6 +478,8 @@ class fulltext_postgres extends base implements search_backend_interface
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
// if the total result count is not cached yet, retrieve it from the db // if the total result count is not cached yet, retrieve it from the db
if (!$result_count) if (!$result_count)
{ {
@ -507,9 +509,9 @@ class fulltext_postgres extends base implements search_backend_interface
$id_ary[] = $row[$field]; $id_ary[] = $row[$field];
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
}
$id_ary = array_unique($id_ary); $id_ary = array_unique($id_ary);
}
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
@ -681,8 +683,6 @@ class fulltext_postgres extends base implements search_backend_interface
// Build the query for really selecting the post_ids // Build the query for really selecting the post_ids
if ($type == 'posts') if ($type == 'posts')
{ {
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
$sql = "SELECT p.post_id $sql = "SELECT p.post_id
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . " FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
WHERE $sql_author WHERE $sql_author
@ -775,9 +775,9 @@ class fulltext_postgres extends base implements search_backend_interface
$id_ary[] = (int) $row[$field]; $id_ary[] = (int) $row[$field];
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
}
$id_ary = array_unique($id_ary); $id_ary = array_unique($id_ary);
}
if (count($id_ary)) if (count($id_ary))
{ {

View file

@ -161,16 +161,6 @@ class environment extends \Twig\Environment
return $this->assets_bag; return $this->assets_bag;
} }
/**
* Gets the event dispatcher instance
*
* @return dispatcher_interface
*/
public function get_phpbb_dispatcher()
{
return $this->phpbb_dispatcher;
}
/** /**
* Get the namespace look up order * Get the namespace look up order
* *

View file

@ -28,18 +28,23 @@ class extension extends \Twig\Extension\AbstractExtension
/** @var \phpbb\language\language */ /** @var \phpbb\language\language */
protected $language; protected $language;
/** @var \phpbb\event\dispatcher_interface */
protected $phpbb_dispatcher;
/** /**
* Constructor * Constructor
* *
* @param \phpbb\template\context $context * @param \phpbb\template\context $context
* @param \phpbb\template\twig\environment $environment * @param \phpbb\template\twig\environment $environment
* @param \phpbb\language\language $language * @param \phpbb\language\language $language
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher
*/ */
public function __construct(\phpbb\template\context $context, \phpbb\template\twig\environment $environment, $language) public function __construct(\phpbb\template\context $context, \phpbb\template\twig\environment $environment, $language, \phpbb\event\dispatcher_interface $phpbb_dispatcher)
{ {
$this->context = $context; $this->context = $context;
$this->environment = $environment; $this->environment = $environment;
$this->language = $language; $this->language = $language;
$this->phpbb_dispatcher = $phpbb_dispatcher;
} }
/** /**
@ -64,7 +69,7 @@ class extension extends \Twig\Extension\AbstractExtension
new \phpbb\template\twig\tokenparser\includeparser, new \phpbb\template\twig\tokenparser\includeparser,
new \phpbb\template\twig\tokenparser\includejs, new \phpbb\template\twig\tokenparser\includejs,
new \phpbb\template\twig\tokenparser\includecss, new \phpbb\template\twig\tokenparser\includecss,
new \phpbb\template\twig\tokenparser\event($this->environment), new \phpbb\template\twig\tokenparser\event($this->environment, $this->phpbb_dispatcher),
); );
} }

View file

@ -29,10 +29,10 @@ class event extends \Twig\TokenParser\AbstractTokenParser
* *
* @param \phpbb\template\twig\environment $environment * @param \phpbb\template\twig\environment $environment
*/ */
public function __construct(\phpbb\template\twig\environment $environment) public function __construct(\phpbb\template\twig\environment $environment, \phpbb\event\dispatcher_interface $phpbb_dispatcher = null)
{ {
$this->environment = $environment; $this->environment = $environment;
$this->phpbb_dispatcher = $this->environment->get_phpbb_dispatcher(); $this->phpbb_dispatcher = $phpbb_dispatcher;
$template_event_priority_array = []; $template_event_priority_array = [];
/** /**

View file

@ -1,53 +0,0 @@
<ul id="nav-breadcrumbs" class="nav-breadcrumbs linklist navlinks" role="menubar">
{% set MICRODATA = 'itemtype="https://schema.org/ListItem" itemprop="itemListElement" itemscope' %}
{% set navlink_position = 1 %}
{% EVENT overall_header_breadcrumbs_before %}
<li class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
{% if U_SITE_HOME %}
<span class="crumb" {{ MICRODATA }}>
{% apply spaceless %}
<a itemprop="item" href="{{ U_SITE_HOME }}" data-navbar-reference="home">
{{ Icon('font', 'home', '', true, 'fas o-icon-baseline') }}
<span itemprop="name">{{ L_SITE_HOME }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% endif %}
{% EVENT overall_header_breadcrumb_prepend %}
<span class="crumb" {{ MICRODATA }}>
{% apply spaceless %}
<a itemprop="item" href="{{ U_INDEX }}" accesskey="h" data-navbar-reference="index">
{% if not U_SITE_HOME %}{{ Icon('font', 'home', '', true, 'fas o-icon-baseline') }}{% endif %}
<span itemprop="name">{{ L_INDEX }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% for navlink in navlinks %}
{% set NAVLINK_NAME = navlink.BREADCRUMB_NAME | default(navlink.FORUM_NAME) %}
{% set NAVLINK_LINK = navlink.U_BREADCRUMB | default(navlink.U_VIEW_FORUM) %}
{% EVENT overall_header_navlink_prepend %}
<span class="crumb" {{ MICRODATA }}{% if navlink.MICRODATA %} {{ navlink.MICRODATA }}{% endif %}>
{% apply spaceless %}
<a itemprop="item" href="{{ NAVLINK_LINK }}">
<span itemprop="name">{{ NAVLINK_NAME }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% EVENT overall_header_navlink_append %}
{% endfor %}
{% EVENT overall_header_breadcrumb_append %}
</li>
{% EVENT overall_header_breadcrumbs_after %}
</ul>

View file

@ -44,7 +44,7 @@
<!-- END faq_block --> <!-- END faq_block -->
<div class="to-top-button"> <div class="to-top-button">
<a href="#faqlinks" title="{{ lang('BACK_TO_TOP') }}"> <a href="#faqlinks">
{{ Icon('font', 'chevron-up', '', false) }} {{ Icon('font', 'chevron-up', '', false) }}
</a> </a>
</div> </div>

View file

@ -203,5 +203,68 @@
{% endif %} {% endif %}
</ul> </ul>
<ul id="nav-breadcrumbs" class="nav-breadcrumbs linklist navlinks" role="menubar">
{% set MICRODATA = 'itemtype="https://schema.org/ListItem" itemprop="itemListElement" itemscope' %}
{% set navlink_position = 1 %}
{% EVENT overall_header_breadcrumbs_before %}
<li class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
{% if U_SITE_HOME %}
<span class="crumb" {{ MICRODATA }}>
{% apply spaceless %}
<a itemprop="item" href="{{ U_SITE_HOME }}" data-navbar-reference="home">
{{ Icon('font', 'home', '', true, 'fas o-icon-baseline') }}
<span itemprop="name">{{ L_SITE_HOME }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% endif %}
{% EVENT overall_header_breadcrumb_prepend %}
<span class="crumb" {{ MICRODATA }}>
{% apply spaceless %}
<a itemprop="item" href="{{ U_INDEX }}" accesskey="h" data-navbar-reference="index">
{% if not U_SITE_HOME %}{{ Icon('font', 'home', '', true, 'fas o-icon-baseline') }}{% endif %}
<span itemprop="name">{{ L_INDEX }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% for navlink in navlinks %}
{% set NAVLINK_NAME = navlink.BREADCRUMB_NAME | default(navlink.FORUM_NAME) %}
{% set NAVLINK_LINK = navlink.U_BREADCRUMB | default(navlink.U_VIEW_FORUM) %}
{% EVENT overall_header_navlink_prepend %}
<span class="crumb" {{ MICRODATA }}{% if navlink.MICRODATA %} {{ navlink.MICRODATA }}{% endif %}>
{% apply spaceless %}
<a itemprop="item" href="{{ NAVLINK_LINK }}">
<span itemprop="name">{{ NAVLINK_NAME }}</span>
</a>
{% endapply %}
<meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}">
</span>
{% EVENT overall_header_navlink_append %}
{% endfor %}
{% EVENT overall_header_breadcrumb_append %}
</li>
{% EVENT overall_header_breadcrumbs_after %}
{% if S_DISPLAY_SEARCH and not S_IN_SEARCH %}
<li class="rightside responsive-search">
<a href="{{ U_SEARCH }}" title="{{ lang('SEARCH_ADV_EXPLAIN') }}" role="menuitem">
{{ Icon('font', 'search', lang('SEARCH'), true) }}
</a>
</li>
{% endif %}
</ul>
</div> </div>
</div> </div>

View file

@ -68,7 +68,7 @@
<!-- EVENT overall_header_stylesheets_after --> <!-- EVENT overall_header_stylesheets_after -->
{% if NOTIFICATIONS_WEBPUSH_ENABLE %} {% if NOTIFICATIONS_WEBPUSH_ENABLE %}
{% include 'ucp_notifications_webpush.html' %} {% include('ucp_notifications_webpush.html') %}
{% endif %} {% endif %}
</head> </head>
@ -79,11 +79,7 @@
<div id="wrap" class="wrap"> <div id="wrap" class="wrap">
<a id="top" class="top-anchor" accesskey="t"></a> <a id="top" class="top-anchor" accesskey="t"></a>
<div id="page-header"> <div id="page-header">
<!-- EVENT overall_header_navbar_before -->
<div class="headerbar" role="banner"> <div class="headerbar" role="banner">
{% include 'navbar_header.html' %}
<!-- EVENT overall_header_headerbar_before --> <!-- EVENT overall_header_headerbar_before -->
<div class="inner"> <div class="inner">
@ -121,10 +117,10 @@
</div> </div>
<!-- EVENT overall_header_headerbar_after --> <!-- EVENT overall_header_headerbar_after -->
</div> </div>
<!-- EVENT overall_header_navbar_before -->
<!-- INCLUDE navbar_header.html -->
</div> </div>
{% include 'breadcrumbs.html' %}
<!-- EVENT overall_header_page_body_before --> <!-- EVENT overall_header_page_body_before -->
<a id="start_here" class="anchor"></a> <a id="start_here" class="anchor"></a>

View file

@ -423,6 +423,9 @@
<!-- EVENT viewtopic_body_postrow_back2top_before --> <!-- EVENT viewtopic_body_postrow_back2top_before -->
<div class="back2top"> <div class="back2top">
<!-- EVENT viewtopic_body_postrow_back2top_prepend --> <!-- EVENT viewtopic_body_postrow_back2top_prepend -->
<a href="#top" class="top" title="{L_BACK_TO_TOP}">
{{ Icon('font', 'circle-chevron-up', lang('BACK_TO_TOP'), false, 'fas c-top-icon') }}
</a>
<!-- EVENT viewtopic_body_postrow_back2top_append --> <!-- EVENT viewtopic_body_postrow_back2top_append -->
</div> </div>
<!-- EVENT viewtopic_body_postrow_back2top_after --> <!-- EVENT viewtopic_body_postrow_back2top_after -->
@ -493,12 +496,6 @@
<!-- ENDIF --> <!-- ENDIF -->
</div> </div>
<div class="to-top-button">
<a href="#top" title="{{ lang('BACK_TO_TOP') }}">
{{ Icon('font', 'chevron-up', '', false) }}
</a>
</div>
<!-- EVENT viewtopic_body_footer_before --> <!-- EVENT viewtopic_body_footer_before -->
<!-- INCLUDE jumpbox.html --> <!-- INCLUDE jumpbox.html -->

View file

@ -99,19 +99,18 @@ th a:hover {
} }
/* round cornered boxes and backgrounds */ /* round cornered boxes and backgrounds */
.headerbar, .headerbar {
.headerbar h1 { color: #ffffff;
color: #eaf8ff;
} }
.headerbar, .headerbar,
.forumbg { .forumbg {
background-color: #4688ce; background-color: #13a4ec;
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.forabg { .forabg {
background-color: #4688ce; background-color: #13a4ec;
background-repeat: repeat-x; background-repeat: repeat-x;
} }
@ -119,18 +118,6 @@ th a:hover {
background-color: #c9dee8; background-color: #c9dee8;
} }
.headerbar .navbar a {
color: #eaf8ff;
}
.headerbar .navbar .dropdown a {
color: #0f4d8a;
}
.header-profile {
text-shadow: 0 0 1.75rem #eaf8ff;
}
.panel { .panel {
background-color: #f0f3f5; background-color: #f0f3f5;
color: #29303d; color: #29303d;
@ -827,10 +814,6 @@ dd.profile-warnings {
/* icon images */ /* icon images */
.site_logo { background-image: url("./images/site_logo.svg"); } .site_logo { background-image: url("./images/site_logo.svg"); }
.c-hero-logo-img g {
fill: #eaf8ff;
}
/* colours and backgrounds for cp.css */ /* colours and backgrounds for cp.css */
/* main cp box */ /* main cp box */
@ -1126,7 +1109,6 @@ input.disabled {
.dropdown-extended .dropdown-extended-item { .dropdown-extended .dropdown-extended-item {
border-top-color: #bdbdbd; border-top-color: #bdbdbd;
color: #47536b;
} }
.dropdown-extended .dropdown-extended-item:hover { .dropdown-extended .dropdown-extended-item:hover {

View file

@ -17,7 +17,7 @@ body {
line-height: normal; line-height: normal;
word-wrap: break-word; word-wrap: break-word;
margin: 0; margin: 0;
padding: 0 0 12px; padding: 12px 0;
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
} }
@ -151,13 +151,12 @@ a:hover {
/* Main blocks /* Main blocks
---------------------------------------- */ ---------------------------------------- */
.wrap { .wrap {
border: solid transparent; border: 1px solid transparent;
border-width: 0 1px 1px; border-radius: 8px;
border-radius: 0 0 8px 8px;
min-width: 625px; min-width: 625px;
max-width: 1152px; max-width: 1152px;
margin: 0 auto; margin: 0 auto;
padding: 0 15px 15px; padding: 15px;
} }
.page-body { .page-body {
@ -201,7 +200,7 @@ a:hover {
/* Round cornered boxes and backgrounds /* Round cornered boxes and backgrounds
---------------------------------------- */ ---------------------------------------- */
.headerbar { .headerbar {
border-radius: 0 0 7px 7px; border-radius: 7px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
@ -213,11 +212,6 @@ a:hover {
padding: 3px 10px; padding: 3px 10px;
} }
.headerbar .navbar {
background: none;
padding: calc(var(--ps-line-height) * 0.25) 5px calc(var(--ps-line-height) * 0.5);
}
.forabg { .forabg {
border-radius: 7px; border-radius: 7px;
clear: both; clear: both;
@ -346,10 +340,6 @@ ul.linklist .dropdown-up .dropdown {
bottom: 18px; bottom: 18px;
} }
ul.nav-breadcrumbs {
margin: calc(var(--ps-line-height) * 0.75) 0;
}
/* Bulletin icons for list items /* Bulletin icons for list items
---------------------------------------- */ ---------------------------------------- */
ul.linklist.bulletin > li:before { ul.linklist.bulletin > li:before {

View file

@ -465,7 +465,7 @@ p.author {
clear: left; clear: left;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
margin: calc(var(--ps-font-small) * 1.4) 0; margin-top: calc(var(--ps-font-small) * 1.4);
padding-top: 2px; padding-top: 2px;
} }

View file

@ -328,6 +328,7 @@
vertical-align: bottom; vertical-align: bottom;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
max-width: 100px;
} }
/* Pagination /* Pagination

View file

@ -190,7 +190,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case
'autoescape' => false, 'autoescape' => false,
] ]
); );
$twig_extension = new \phpbb\template\twig\extension($context, $twig, $this->language); $twig_extension = new \phpbb\template\twig\extension($context, $twig, $this->language, $phpbb_dispatcher);
$phpbb_container->set('template.twig.extensions.phpbb', $twig_extension); $phpbb_container->set('template.twig.extensions.phpbb', $twig_extension);
$twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container); $twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container);

View file

@ -119,6 +119,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_database_test_
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$context = new \phpbb\template\context(); $context = new \phpbb\template\context();
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$this->dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$this->config, $this->config,
@ -127,7 +128,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_database_test_
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $this->dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -135,7 +136,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_database_test_
'autoescape' => false, 'autoescape' => false,
) )
); );
$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user))); $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $this->dispatcher)));
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->extension_manager = new phpbb_mock_extension_manager( $this->extension_manager = new phpbb_mock_extension_manager(

View file

@ -87,7 +87,7 @@ class phpbb_email_parsing_test extends phpbb_test_case
'autoescape' => false, 'autoescape' => false,
) )
); );
$twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang); $twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang, $dispatcher);
$phpbb_container->set('template.twig.extensions.phpbb', $twig_extension); $phpbb_container->set('template.twig.extensions.phpbb', $twig_extension);
$twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container); $twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container);

View file

@ -117,7 +117,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$lang = new \phpbb\language\language($lang_loader); $lang = new \phpbb\language\language($lang_loader);
$this->user = new \phpbb\user($lang, '\phpbb\datetime'); $this->user = new \phpbb\user($lang, '\phpbb\datetime');
$this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user))); $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $phpbb_dispatcher)));
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
} }

View file

@ -69,32 +69,4 @@ class phpbb_functional_acp_profile_field_test extends phpbb_functional_test_case
$this->assertContainsLang('ADDED_PROFILE_FIELD', $crawler->text()); $this->assertContainsLang('ADDED_PROFILE_FIELD', $crawler->text());
} }
public function test_edit_profile_fields()
{
// Custom profile fields page
$crawler = self::request('GET', 'adm/index.php?i=acp_profile&mode=profile&sid=' . $this->sid);
// Get all profile fields edit URLs
$edits = $crawler->filter('td.actions a')
->reduce(
function ($node, $i) {
$url = $node->attr('href');
return ((bool) strpos($url, 'action=edit'));
})
->each(
function ($node, $i) {
$url = $node->attr('href');
return ($url);
});
foreach ($edits as $edit_url)
{
$crawler = self::request('GET', 'adm/' . $edit_url . '&sid=' . $this->sid);
$form = $crawler->selectButton('Save')->form();
$crawler= self::submit($form);
$this->assertContainsLang('CHANGED_PROFILE_FIELD', $crawler->text());
}
}
} }

View file

@ -229,159 +229,6 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($topic_multiple_results_count2['topic_id']); $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
$pages = range(2, $last_page);
foreach ($pages 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);
$cached_results_count = count($post_ids_cached) - 2; // Don't count '-1' and '-2' indexes
$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 equal to displayed on search results page
$this->assertEquals($posts_count, $post_ids_cached[-1], $this->search_backend);
// Actual cached data array count should be equal to displayed on search results page too
$this->assertEquals($posts_count, $cached_results_count, $this->search_backend);
// Cached data array shouldn't change after removing duplicates. That is, it shouldn't have any duplicates.
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);
$this->assertEquals($post_ids_cached_backup, $post_ids_cached, $this->search_backend);
// Restore this value to default
$sql = 'UPDATE ' . CONFIG_TABLE . "
SET config_value = 250
WHERE config_name = '" . $this->db->sql_escape('search_block_size') . "'";
$this->db->sql_query($sql);
// 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) protected function create_search_index($backend = null)
{ {
$this->add_lang('acp/search'); $this->add_lang('acp/search');

View file

@ -102,6 +102,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
$loader = new \phpbb\template\twig\loader([]); $loader = new \phpbb\template\twig\loader([]);
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -110,7 +111,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
[ [
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -126,7 +127,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
$cache_path, $cache_path,
$this->user, $this->user,
[ [
new \phpbb\template\twig\extension($context, $twig, $this->lang), new \phpbb\template\twig\extension($context, $twig, $this->lang, $dispatcher),
new \phpbb\template\twig\extension\avatar($avatar_helper), new \phpbb\template\twig\extension\avatar($avatar_helper),
new \phpbb\template\twig\extension\config($config), new \phpbb\template\twig\extension\config($config),
new \phpbb\template\twig\extension\icon($this->user), new \phpbb\template\twig\extension\icon($this->user),

View file

@ -60,6 +60,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -68,7 +69,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case
$cache_path, $cache_path,
$this->extension_manager, $this->extension_manager,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -76,7 +77,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case
'autoescape' => false, 'autoescape' => false,
) )
); );
$this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user)), $this->extension_manager); $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $dispatcher)), $this->extension_manager);
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template_path = $this->test_path . '/templates'; $this->template_path = $this->test_path . '/templates';

View file

@ -154,6 +154,7 @@ Zeta test event in all',
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -162,7 +163,7 @@ Zeta test event in all',
$cache_path, $cache_path,
$this->extension_manager, $this->extension_manager,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -170,7 +171,7 @@ Zeta test event in all',
'autoescape' => false, 'autoescape' => false,
) )
); );
$this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user)), $this->extension_manager); $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $dispatcher)), $this->extension_manager);
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path)); $this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path));

View file

@ -46,6 +46,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -54,7 +55,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -69,7 +70,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
$twig, $twig,
$cache_path, $cache_path,
$this->user, $this->user,
array(new \phpbb\template\twig\extension($context, $twig, $this->user)), array(new \phpbb\template\twig\extension($context, $twig, $this->user, $dispatcher)),
new phpbb_mock_extension_manager( new phpbb_mock_extension_manager(
__DIR__ . '/', __DIR__ . '/',
array( array(

View file

@ -97,6 +97,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -105,7 +106,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -113,7 +114,8 @@ class phpbb_template_template_test_case extends phpbb_test_case
'autoescape' => false, 'autoescape' => false,
) )
); );
$this->template = new phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $lang)));
$this->template = new phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $lang, $dispatcher)));
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style('tests', $this->template_path); $this->template->set_custom_style('tests', $this->template_path);
} }

View file

@ -47,6 +47,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -55,7 +56,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
array( array(
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -63,7 +64,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
'autoescape' => false, 'autoescape' => false,
) )
); );
$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user))); $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $dispatcher)));
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path)); $this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path));
} }

View file

@ -65,6 +65,7 @@ class twig_test extends \phpbb_test_case
$loader = new \phpbb\template\twig\loader(''); $loader = new \phpbb\template\twig\loader('');
$log = new \phpbb\log\dummy(); $log = new \phpbb\log\dummy();
$assets_bag = new \phpbb\template\assets_bag(); $assets_bag = new \phpbb\template\assets_bag();
$dispatcher = new \phpbb\event\dispatcher();
$twig = new \phpbb\template\twig\environment( $twig = new \phpbb\template\twig\environment(
$assets_bag, $assets_bag,
$config, $config,
@ -73,7 +74,7 @@ class twig_test extends \phpbb_test_case
$cache_path, $cache_path,
null, null,
$loader, $loader,
new \phpbb\event\dispatcher(), $dispatcher,
[ [
'cache' => false, 'cache' => false,
'debug' => false, 'debug' => false,
@ -81,7 +82,7 @@ class twig_test extends \phpbb_test_case
'autoescape' => false, 'autoescape' => false,
] ]
); );
$this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user))); $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $twig, $this->user, $dispatcher)));
$twig->setLexer(new \phpbb\template\twig\lexer($twig)); $twig->setLexer(new \phpbb\template\twig\lexer($twig));
} }

View file

@ -407,7 +407,7 @@ class phpbb_functional_test_case extends phpbb_test_case
'autoescape' => false, 'autoescape' => false,
] ]
); );
$twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang); $twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang, $phpbb_dispatcher);
$container->set('template.twig.extensions.phpbb', $twig_extension); $container->set('template.twig.extensions.phpbb', $twig_extension);
$twig_extensions_collection = new \phpbb\di\service_collection($container); $twig_extensions_collection = new \phpbb\di\service_collection($container);