Compare commits

...

44 commits

Author SHA1 Message Date
rxu
6c5788af2b
Merge 10921ebc58 into 3cc7076513 2025-07-04 04:31:23 +00:00
rxu
10921ebc58
[ticket/17525] Fix migration failure on update
PHPBB-17525
2025-07-04 11:30:46 +07:00
Marc Alexander
3cc7076513
Merge pull request #6822 from iMattPro/ticket/17517
Ticket/17517 Update eslint and lint all phpbb JS files
2025-06-29 09:10:40 +02:00
Matt Friedman
158a561651
[ticket/17517] Update and refactor eslint implementation
PHPBB-17517
2025-06-26 18:25:05 -07:00
Marc Alexander
954bc07de1
Merge pull request #6835 from rxu/ticket/17529
[ticket/17529] Fix installer config.php availability checks
2025-06-25 17:43:39 +02:00
rxu
044536dffb
[ticket/17529] Remove unneeded wrapping curly braces
PHPBB-17529
2025-06-21 10:03:52 +07:00
rxu
6ccc6f0383
[ticket/17529] Fix installer config.php availability checks
PHPBB-17529
2025-06-20 22:00:05 +07:00
Marc Alexander
4f10e6e212 Merge branch '3.3.x' 2025-06-17 17:43:01 +00:00
Marc Alexander
3b03f3a8f9
Merge pull request #6833 from iMattPro/ticket/17519
[ticket/17519] Revert cron url escape back to html_attr
2025-06-17 19:42:42 +02:00
Matt Friedman
e47ba9e81d
[ticket/17519] Fix tests
PHPBB-17519
2025-06-17 09:19:40 -07:00
Matt Friedman
8d016bafa2
[ticket/17519] Revert cron url escape back to html_attr
PHPBB-17519
2025-06-17 07:59:04 -07:00
Marc Alexander
6d6f4fdeba Merge branch '3.3.x' 2025-06-17 12:04:46 +00:00
Marc Alexander
35221f8ba5
Merge pull request #6826 from danieltj27/ticket/17522
[ticket/17522] Add event to member list to modify template vars
2025-06-17 14:04:28 +02:00
Marc Alexander
03031e846d Merge branch '3.3.x' 2025-06-17 09:39:08 +00:00
Marc Alexander
9219c03b36
Merge pull request #6831 from rxu/ticket/17527
[ticket/17527] Add Twig extensions existence check while registering
2025-06-17 11:30:52 +02:00
Daniel James
72c3745868 [ticket/17522] Change event name and update var type
PHPBB-17522
2025-06-17 07:18:41 +01:00
rxu
579b4a8287
[ticket/17527] Add Twig extensions existence check while registering
PHPBB-17527
2025-06-16 22:25:59 +07:00
Marc Alexander
b8c49f9711
Merge branch '3.3.x' 2025-06-16 10:37:08 +02:00
Marc Alexander
2f43c1facd
[ticket/17399] Fix docblock and use space-ship operator
PHPBB-17399
2025-06-16 10:34:38 +02:00
Marc Alexander
9c49a2b86b
[ticket/17399] Fix declaration to be in line with PHP documentation
PHPBB-17399
2025-06-15 19:59:13 +02:00
Marc Alexander
d017eff8f1
Merge branch '3.3.x' 2025-06-15 09:10:57 +02:00
Marc Alexander
d4a3311b76
Merge pull request #6829 from battye/ticket/17399
[ticket/17399] Fix selected language bug in installer
2025-06-15 09:08:49 +02:00
Marc Alexander
bc470285fc
Merge pull request #6770 from rxu/ticket/15214
[ticket/15214] Add event & functionality for assigning template event priority
2025-06-15 08:59:31 +02:00
rxu
1d7543c778
[ticket/15214] Address code review issues, add equal priority events test
PHPBB3-15214
2025-06-15 01:35:31 +07:00
battye
8411da1819 [ticket/17399] Fix selected language in installer
This fixes a bug where a user could have other languages in the installer
but the language dropdown did not match the language shown.

PHPBB-17399
2025-06-14 14:35:18 +00:00
Daniel James
b6c42b3768 [ticket/17522] Switch array syntax to short code
PHPBB-17522
2025-06-06 11:50:49 +01:00
Daniel James
da2733a7d8 [ticket/17522] Change since from beta to release candidate
PHPBB-17522
2025-06-06 11:03:10 +01:00
Daniel James
b8204d24f9 [ticket/17522] Add event to member list to modify template vars
PHPBB-17522
2025-06-05 22:18:51 +01:00
rxu
ccbdfb49c7
[ticket/15214] Adjust core event name and docblock
PHPBB3-15214
2025-05-21 11:25:35 +07:00
rxu
43cf7b73bd
[ticket/15214] Adjust event node logic
PHPBB3-15214
2025-05-21 10:47:27 +07:00
rxu
3a5247d01b
[ticket/15214] Get event dispatcher from environment rather than as dependency
Also this will allow to significantly reduce unrelated tests changes.

PHPBB3-15214
2025-05-20 17:36:15 +07:00
rxu
5e0dc9ef2e
[ticket/15214] Fix rebasing and some other issues
PHPBB3-15214
2025-05-20 16:24:38 +07:00
rxu
8338ff9e56
[ticket/15214] Fix Windows tests
PHPBB3-15214
2025-05-20 16:24:37 +07:00
toxyy
84e7e34a66
[ticket/15214] Fix tests again
Adding per rxu's recommendation

PHPBB3-15214
2025-05-20 16:24:37 +07:00
rxu
18bae795f0
[ticket/15214] Fix Windows tests
Purge Twig compiled cache in Windows.
Set appropriate folder access control options to do that.

PHPBB3-15214
2025-05-20 16:24:36 +07:00
rxu
09fd86ffb0
[ticket/15214] Fix test foo/foo extension listener
PHPBB3-15214
2025-05-20 16:24:34 +07:00
rxu
4a00212f2d
[ticket/15214] Optimize event node code and add template event order tests
PHPBB3-15214
2025-05-20 16:24:34 +07:00
toxyy
cb47d78d26
[ticket/15214] Update block, restart tests
Make docblock look a bit cleaner and restart the tests

PHPBB3-15214
2025-05-20 16:24:33 +07:00
toxyy
0eb98d51e2
[ticket/15214] Provide usage example within event docblock
Adds similar usage examples like the event core.permissions has

PHPBB3-15214
2025-05-20 16:24:32 +07:00
toxyy
82a5e20f3e
[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-05-20 16:24:32 +07:00
toxyy
71fe9d60c4
[ticket/15214] Add fixes for various other tests
Add new dispatch parameter to the template\twig\extension calls

PHPBB3-15214
2025-05-20 16:24:31 +07:00
toxyy
59b482a222
[ticket/15214] Test fix for test_bbcode_firstpass
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-05-20 16:24:30 +07:00
toxyy
d934c8c4b7
[ticket/15214] Test fix for test_helper_url_no_rewrite
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-05-20 16:24:29 +07:00
toxyy
d07aeb00d8
[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-05-20 16:24:24 +07:00
44 changed files with 1774 additions and 916 deletions

4
.github/check-js.sh vendored
View file

@ -14,6 +14,6 @@ set +x
sudo npm install -g > /dev/null sudo npm install -g > /dev/null
npm ci > /dev/null npm ci > /dev/null
set -x set -x
node_modules/eslint/bin/eslint.js "phpBB/**/*.js" node_modules/eslint/bin/eslint.js "phpBB/**/*.js" --ignore-pattern "phpBB/ext/"
node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig" node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig" --ignore-pattern "phpBB/ext/"
node_modules/eslint/bin/eslint.js "gulpfile.js" node_modules/eslint/bin/eslint.js "gulpfile.js"

67
eslint.config.mjs Normal file
View file

@ -0,0 +1,67 @@
const { browser: browserGlobals, node: nodeGlobals, jquery: jqueryGlobals } = (await import('globals')).default;
// File patterns to ignore
const IGNORED_FILES = [
'phpBB/assets/javascript/cropper.js',
'phpBB/assets/javascript/hermite.js',
'phpBB/assets/javascript/jquery-cropper.js',
'phpBB/**/*.min.js',
'phpBB/vendor/**/*.js',
'phpBB/vendor-ext/**/*.js',
'phpBB/phpbb/**/*.js',
'phpBB/tests/**/*.js',
];
// ESLint rule configurations
const FORMATTING_RULES = {
'quotes': ['error', 'single'],
'comma-dangle': ['error', 'always-multiline'],
'block-spacing': 'error',
'array-bracket-spacing': ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'space-before-function-paren': ['error', 'never'],
'space-in-parens': 'off',
};
const CODE_QUALITY_RULES = {
'semi': ['error', 'always'],
'eqeqeq': ['error', 'always'],
'curly': ['error', 'multi-line'],
'no-var': 'error',
'prefer-const': 'error',
'no-console': 'off',
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
};
const DISABLED_STYLE_RULES = {
'multiline-comment-style': 'off',
'computed-property-spacing': 'off',
'capitalized-comments': 'off',
'no-lonely-if': 'off',
};
const mainConfig = {
files: ['**/*.js', '**/*.js.twig'],
linterOptions: {
reportUnusedDisableDirectives: false,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...browserGlobals,
...nodeGlobals,
...jqueryGlobals,
},
},
rules: {
...FORMATTING_RULES,
...CODE_QUALITY_RULES,
...DISABLED_STYLE_RULES,
},
};
export default [
{ ignores: IGNORED_FILES },
mainConfig,
];

1780
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,65 +6,6 @@
"directories": { "directories": {
"doc": "docs" "doc": "docs"
}, },
"eslintConfig": {
"extends": "xo",
"ignorePatterns": [
"phpBB/adm/style/admin.js",
"phpBB/adm/style/ajax.js",
"phpBB/adm/style/permissions.js",
"phpBB/adm/style/tooltip.js",
"phpBB/assets/javascript/core.js",
"phpBB/assets/javascript/cropper.js",
"phpBB/assets/javascript/editor.js",
"phpBB/assets/javascript/hermite.js",
"phpBB/assets/javascript/installer.js",
"phpBB/assets/javascript/jquery-cropper.js",
"phpBB/assets/javascript/plupload.js",
"phpBB/ext/**/*.js",
"phpBB/styles/prosilver/template/ajax.js",
"phpBB/styles/prosilver/template/forum_fn.js",
"phpBB/**/*.min.js",
"phpBB/vendor/**/*.js",
"phpBB/vendor-ext/**/*.js",
"phpBB/phpbb/**/*.js",
"phpBB/tests/**/*.js"
],
"rules": {
"quotes": [
"error",
"single"
],
"comma-dangle": [
"error",
"always-multiline"
],
"block-spacing": "error",
"array-bracket-spacing": [
"error",
"always"
],
"multiline-comment-style": "off",
"computed-property-spacing": "off",
"space-before-function-paren": [
"error",
"never"
],
"space-in-parens": "off",
"capitalized-comments": "off",
"object-curly-spacing": [
"error",
"always"
],
"no-lonely-if": "off",
"unicorn/prefer-module": "off"
},
"env": {
"es6": true,
"browser": true,
"node": true,
"jquery": true
}
},
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"not ie 11", "not ie 11",
@ -101,8 +42,8 @@
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.4", "autoprefixer": "^10.4.4",
"cssnano": "^5.1.7", "cssnano": "^5.1.7",
"eslint": "^8.13.0", "eslint": "^9.28.0",
"eslint-config-xo": "^0.40.0", "globals": "^16.2.0",
"gulp": "^5.0.0", "gulp": "^5.0.0",
"gulp-concat": "^2.6.1", "gulp-concat": "^2.6.1",
"gulp-postcss": "^9.0.1", "gulp-postcss": "^9.0.1",

View file

@ -1,4 +1,6 @@
/* global phpbb */ /* global phpbb */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
/** /**
* phpBB ACP functions * phpBB ACP functions
@ -10,7 +12,7 @@
function parse_document(container) function parse_document(container)
{ {
var test = document.createElement('div'), var test = document.createElement('div'),
oldBrowser = (typeof test.style.borderRadius == 'undefined'); oldBrowser = (typeof test.style.borderRadius === 'undefined');
test.remove(); test.remove();
@ -79,7 +81,7 @@ function parse_document(container)
dfn = cell.attr('data-dfn'), dfn = cell.attr('data-dfn'),
text = dfn ? dfn : $.trim(cell.text()); text = dfn ? dfn : $.trim(cell.text());
if (text == ' ') text = ''; if (text === ' ') text = '';
colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan; colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
for (i=0; i<colspan; i++) { for (i=0; i<colspan; i++) {
@ -108,7 +110,7 @@ function parse_document(container)
cells = row.children('td'), cells = row.children('td'),
column = 0; column = 0;
if (cells.length == 1) { if (cells.length === 1) {
row.addClass('big-column'); row.addClass('big-column');
return; return;
} }
@ -124,7 +126,7 @@ function parse_document(container)
if ((text.length && text !== '-') || cell.children().length) { if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) { if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column])); cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
} }
} }
else { else {
@ -156,7 +158,7 @@ function parse_document(container)
*/ */
container.find('fieldset dt > span:last-child').each(function() { container.find('fieldset dt > span:last-child').each(function() {
var $this = $(this); var $this = $(this);
if ($this.html() == '&nbsp;') { if ($this.html() === '&nbsp;') {
$this.addClass('responsive-hide'); $this.addClass('responsive-hide');
} }
}); });
@ -194,7 +196,7 @@ function parse_document(container)
links.each(function() { links.each(function() {
var link = $(this); var link = $(this);
maxHeight = Math.max(maxHeight, Math.max(link.outerHeight(true), link.parent().outerHeight(true))); maxHeight = Math.max(maxHeight, Math.max(link.outerHeight(true), link.parent().outerHeight(true)));
}) });
function check() { function check() {
var width = $body.width(), var width = $body.width(),
@ -273,7 +275,7 @@ function parse_document(container)
// Do not underline actions icons on hover (could not be done via CSS) // Do not underline actions icons on hover (could not be done via CSS)
$('.actions a:has(i.acp-icon)').mouseover(function() { $('.actions a:has(i.acp-icon)').mouseover(function() {
$(this).css("text-decoration", "none"); $(this).css('text-decoration', 'none');
}); });
// Live update BBCode font icon preview // Live update BBCode font icon preview

View file

@ -1,4 +1,5 @@
/* global phpbb, statsData */ /* global phpbb, statsData */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
@ -74,7 +75,7 @@ phpbb.prepareSendStats = function () {
var $sendStatisticsSuccess = $('<input />', { var $sendStatisticsSuccess = $('<input />', {
type: 'hidden', type: 'hidden',
name: 'send_statistics_response', name: 'send_statistics_response',
value: JSON.stringify(res) value: JSON.stringify(res),
}); });
$sendStatisticsSuccess.appendTo('p.submit-buttons'); $sendStatisticsSuccess.appendTo('p.submit-buttons');
@ -90,7 +91,7 @@ phpbb.prepareSendStats = function () {
data: statsData, data: statsData,
success: returnHandler, success: returnHandler,
error: errorHandler, error: errorHandler,
cache: false cache: false,
}).always(function() { }).always(function() {
if ($loadingIndicator && $loadingIndicator.is(':visible')) { if ($loadingIndicator && $loadingIndicator.is(':visible')) {
$loadingIndicator.fadeOut(phpbb.alertTime); $loadingIndicator.fadeOut(phpbb.alertTime);
@ -176,7 +177,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
namedCurve: 'P-256', namedCurve: 'P-256',
}, },
true, true,
['deriveKey', 'deriveBits'] [ 'deriveKey', 'deriveBits' ],
); );
const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey); const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
@ -187,7 +188,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
return { return {
privateKey: privateKeyString, privateKey: privateKeyString,
publicKey: publicKeyString publicKey: publicKeyString,
}; };
} catch (error) { } catch (error) {
console.error('Error generating keys with SubtleCrypto:', error); console.error('Error generating keys with SubtleCrypto:', error);
@ -203,8 +204,8 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
const privateKeyInput = document.querySelector('#webpush_vapid_private'); const privateKeyInput = document.querySelector('#webpush_vapid_private');
publicKeyInput.value = keyPair.publicKey; publicKeyInput.value = keyPair.publicKey;
privateKeyInput.value = keyPair.privateKey; privateKeyInput.value = keyPair.privateKey;
}) });
}) });
/** /**
* Handler for submitting permissions form in chunks * Handler for submitting permissions form in chunks
@ -286,14 +287,14 @@ function submitPermissions() {
$alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, '')); $alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, ''));
const $previousPageForm = $('<form>').attr({ const $previousPageForm = $('<form>').attr({
action: $alertBoxLink.attr('href'), action: $alertBoxLink.attr('href'),
method: 'post' method: 'post',
}); });
$.each(forumIds, function(key, value) { $.each(forumIds, function(key, value) {
$previousPageForm.append($('<input>').attr({ $previousPageForm.append($('<input>').attr({
type: 'text', type: 'text',
name: 'forum_id[]', name: 'forum_id[]',
value: value value: value,
})); }));
}); });
@ -314,14 +315,14 @@ function submitPermissions() {
// exceeding the maximum length of URLs // exceeding the maximum length of URLs
const $form = $('<form>').attr({ const $form = $('<form>').attr({
action: res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, ''), action: res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, ''),
method: 'post' method: 'post',
}); });
$.each(forumIds, function(key, value) { $.each(forumIds, function(key, value) {
$form.append($('<input>').attr({ $form.append($('<input>').attr({
type: 'text', type: 'text',
name: 'forum_id[]', name: 'forum_id[]',
value: value value: value,
})); }));
}); });
@ -365,7 +366,7 @@ function submitPermissions() {
'&' + $form.children('input[type=hidden]').serialize() + '&' + $form.children('input[type=hidden]').serialize() +
'&' + $form.find('input[type=checkbox][name^=inherit]').serialize(), '&' + $form.find('input[type=checkbox][name^=inherit]').serialize(),
success: handlePermissionReturn, success: handlePermissionReturn,
error: handlePermissionReturn error: handlePermissionReturn,
}); });
}); });
} }
@ -379,7 +380,7 @@ $('[data-ajax]').each(function() {
phpbb.ajaxify({ phpbb.ajaxify({
selector: this, selector: this,
refresh: $this.attr('data-refresh') !== undefined, refresh: $this.attr('data-refresh') !== undefined,
callback: fn callback: fn,
}); });
} }
}); });
@ -412,7 +413,7 @@ $(function() {
} else { } else {
dateoptionInput.value = this.value; dateoptionInput.value = this.value;
} }
}) });
} }
if ($('#acp_help_phpbb')) { if ($('#acp_help_phpbb')) {

View file

@ -1,4 +1,8 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-undef: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var: 0 */
/** /**
* Hide and show all checkboxes * Hide and show all checkboxes

View file

@ -1,4 +1,5 @@
/* global phpbb */ /* global phpbb */
/* eslint no-var: 0 */
/* /*
javascript for Bubble Tooltips by Alessandro Fulciniti javascript for Bubble Tooltips by Alessandro Fulciniti
@ -30,8 +31,8 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) {
hold = $('<span />', { hold = $('<span />', {
id: '_tooltip_container', id: '_tooltip_container',
css: { css: {
position: 'absolute' position: 'absolute',
} },
}); });
$('body').append(hold); $('body').append(hold);
@ -73,8 +74,8 @@ phpbb.prepareTooltips = function ($element, headText) {
$title = $('<span />', { $title = $('<span />', {
class: 'top', class: 'top',
css: { css: {
display: 'block' display: 'block',
} },
}) })
.append(document.createTextNode(headText)); .append(document.createTextNode(headText));
@ -82,15 +83,15 @@ phpbb.prepareTooltips = function ($element, headText) {
class: 'bottom', class: 'bottom',
html: text, html: text,
css: { css: {
display: 'block' display: 'block',
} },
}); });
$tooltip = $('<span />', { $tooltip = $('<span />', {
class: 'tooltip', class: 'tooltip',
css: { css: {
display: 'block' display: 'block',
} },
}) })
.append($title) .append($title)
.append($desc); .append($desc);
@ -135,12 +136,12 @@ phpbb.positionTooltip = function ($element) {
if ($('body').hasClass('rtl')) { if ($('body').hasClass('rtl')) {
$('#_tooltip_container').css({ $('#_tooltip_container').css({
top: offset.top + 30, top: offset.top + 30,
left: offset.left + 255 left: offset.left + 255,
}); });
} else { } else {
$('#_tooltip_container').css({ $('#_tooltip_container').css({
top: offset.top + 30, top: offset.top + 30,
left: offset.left - 205 left: offset.left - 205,
}); });
} }
}; };

View file

@ -1,4 +1,6 @@
/* global bbfontstyle */ /* global bbfontstyle */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
var phpbb = {}; var phpbb = {};
phpbb.alertTime = 100; phpbb.alertTime = 100;
@ -13,7 +15,7 @@ var keymap = {
ENTER: 13, ENTER: 13,
ESC: 27, ESC: 27,
ARROW_UP: 38, ARROW_UP: 38,
ARROW_DOWN: 40 ARROW_DOWN: 40,
}; };
var $dark = $('#darkenwrapper'); var $dark = $('#darkenwrapper');
@ -363,7 +365,7 @@ phpbb.ajaxify = function(options) {
type: 'POST', type: 'POST',
data: data + '&confirm=' + res.YES_VALUE + '&' + $('form', '#phpbb_confirm').serialize(), data: data + '&confirm=' + res.YES_VALUE + '&' + $('form', '#phpbb_confirm').serialize(),
success: returnHandler, success: returnHandler,
error: errorHandler error: errorHandler,
}); });
}, false); }, false);
} }
@ -383,7 +385,7 @@ phpbb.ajaxify = function(options) {
submit = $this.find('input[type="submit"][data-clicked]'); submit = $this.find('input[type="submit"][data-clicked]');
data.push({ data.push({
name: submit.attr('name'), name: submit.attr('name'),
value: submit.val() value: submit.val(),
}); });
} }
} else if (isText) { } else if (isText) {
@ -409,7 +411,7 @@ phpbb.ajaxify = function(options) {
data: data, data: data,
success: returnHandler, success: returnHandler,
error: errorHandler, error: errorHandler,
cache: false cache: false,
}); });
request.always(function() { request.always(function() {
@ -445,10 +447,10 @@ phpbb.ajaxify = function(options) {
phpbb.search = { phpbb.search = {
cache: { cache: {
data: [] data: [],
}, },
tpl: [], tpl: [],
container: [] container: [],
}; };
/** /**
@ -609,7 +611,7 @@ phpbb.search.filter = function(data, event, sendRequest) {
if (cache.results[keyword]) { if (cache.results[keyword]) {
var response = { var response = {
keyword: keyword, keyword: keyword,
results: cache.results[keyword] results: cache.results[keyword],
}; };
phpbb.search.handleResponse(response, $this, true); phpbb.search.handleResponse(response, $this, true);
proceed = false; proceed = false;
@ -1079,7 +1081,7 @@ phpbb.addAjaxCallback('toggle_link', function() {
$this.attr('href', toggleUrl); $this.attr('href', toggleUrl);
// Toggle Icon // Toggle Icon
$this.children().first().toggleClass('is-active').next().toggleClass('is-active') $this.children().first().toggleClass('is-active').next().toggleClass('is-active');
}); });
}); });
@ -1113,7 +1115,7 @@ phpbb.resizeTextArea = function($items, options) {
maxHeight: 500, maxHeight: 500,
heightDiff: 200, heightDiff: 200,
resizeCallback: function() {}, resizeCallback: function() {},
resetCallback: function() {} resetCallback: function() {},
}; };
if (phpbb.isTouch) { if (phpbb.isTouch) {
@ -1152,7 +1154,7 @@ phpbb.resizeTextArea = function($items, options) {
var maxHeight = Math.min( var maxHeight = Math.min(
Math.max(windowHeight - configuration.heightDiff, configuration.minHeight), Math.max(windowHeight - configuration.heightDiff, configuration.minHeight),
configuration.maxHeight configuration.maxHeight,
), ),
$item = $(item), $item = $(item),
height = parseInt($item.innerHeight(), 10), height = parseInt($item.innerHeight(), 10),
@ -1434,7 +1436,7 @@ phpbb.toggleDropdown = function(event_) {
marginLeft: 0, marginLeft: 0,
left: 0, left: 0,
marginRight: 0, marginRight: 0,
maxWidth: (windowWidth - 4) + 'px' maxWidth: (windowWidth - 4) + 'px',
}); });
var offset = $this.offset().left, var offset = $this.offset().left,
@ -1468,7 +1470,7 @@ phpbb.toggleDropdown = function(event_) {
var maxOffset = Math.min(contentWidth, fullFreeSpace) + 'px'; var maxOffset = Math.min(contentWidth, fullFreeSpace) + 'px';
options.dropdown.css({ options.dropdown.css({
width: maxOffset, width: maxOffset,
marginLeft: -maxOffset marginLeft: -maxOffset,
}); });
} }
} else { } else {
@ -1512,7 +1514,7 @@ phpbb.registerDropdown = function(toggle, dropdown, options) {
leftClass: 'dropdown-left', // Class to add to parent item when dropdown opens to left side leftClass: 'dropdown-left', // Class to add to parent item when dropdown opens to left side
rightClass: 'dropdown-right', // Class to add to parent item when dropdown opens to right side rightClass: 'dropdown-right', // Class to add to parent item when dropdown opens to right side
upClass: 'dropdown-up', // Class to add to parent item when dropdown opens above menu item upClass: 'dropdown-up', // Class to add to parent item when dropdown opens above menu item
downClass: 'dropdown-down' // Class to add to parent item when dropdown opens below menu item downClass: 'dropdown-down', // Class to add to parent item when dropdown opens below menu item
}; };
if (options) { if (options) {
ops = $.extend(ops, options); ops = $.extend(ops, options);
@ -1716,7 +1718,7 @@ phpbb.registerPageDropdowns = function() {
$contents = $this.find('.dropdown'), $contents = $this.find('.dropdown'),
options = { options = {
direction: 'auto', direction: 'auto',
verticalDirection: 'auto' verticalDirection: 'auto',
}, },
data; data;
@ -1795,7 +1797,7 @@ phpbb.getEditorTextArea = function(formName, textareaName) {
} }
return doc.forms[formName].elements[textareaName]; return doc.forms[formName].elements[textareaName];
} };
phpbb.recaptcha = { phpbb.recaptcha = {
button: null, button: null,
@ -1826,7 +1828,7 @@ phpbb.recaptcha = {
if (phpbb.recaptcha.v3.length) { if (phpbb.recaptcha.v3.length) {
grecaptcha.execute( grecaptcha.execute(
phpbb.recaptcha.v3.data('recaptcha-v3'), phpbb.recaptcha.v3.data('recaptcha-v3'),
{action: phpbb.recaptcha.v3.val()} { action: phpbb.recaptcha.v3.val() },
).then(function(token) { ).then(function(token) {
// Place the token inside the form // Place the token inside the form
phpbb.recaptcha.token.val(token); phpbb.recaptcha.token.val(token);
@ -1860,7 +1862,7 @@ phpbb.recaptcha = {
phpbb.recaptcha.form.submit(); phpbb.recaptcha.form.submit();
} }
} },
}; };
// reCAPTCHA v2 doesn't accept callback functions nested inside objects // reCAPTCHA v2 doesn't accept callback functions nested inside objects

View file

@ -1,4 +1,8 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-undef: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var: 0 */
/** /**
* bbCode control by subBlue design [ www.subBlue.com ] * bbCode control by subBlue design [ www.subBlue.com ]
@ -100,7 +104,7 @@ function bbfontstyle(bbopen, bbclose) {
// IE // IE
else if (document.selection) { else if (document.selection) {
var range = textarea.createTextRange(); var range = textarea.createTextRange();
range.move("character", new_pos); range.move('character', new_pos);
range.select(); range.select();
storeCaret(textarea); storeCaret(textarea);
} }
@ -271,7 +275,7 @@ function formatAttributeValue(str) {
// Return as-is if it contains none of: space, ' " \ or ] // Return as-is if it contains none of: space, ' " \ or ]
return str; return str;
} }
var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'", var singleQuoted = '\'' + str.replace(/[\\']/g, '\\$&') + '\'',
doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"'; doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"';
return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted; return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted;

View file

@ -2,6 +2,9 @@
* Installer's AJAX frontend handler * Installer's AJAX frontend handler
*/ */
/* eslint no-prototype-builtins: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict'; 'use strict';
@ -361,8 +364,8 @@
addMessage('error', addMessage('error',
[ { [ {
title: installLang.title, title: installLang.title,
description: installLang.msg description: installLang.msg,
}] } ],
); );
} }
} }

View file

@ -1,4 +1,7 @@
/* global phpbb, plupload, attachInline */ /* global phpbb, plupload, attachInline */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
plupload.addI18n(phpbb.plupload.i18n); plupload.addI18n(phpbb.plupload.i18n);
phpbb.plupload.ids = []; phpbb.plupload.ids = [];
@ -21,7 +24,7 @@ phpbb.plupload.initialize = function() {
// Only execute if Plupload initialized successfully. // Only execute if Plupload initialized successfully.
phpbb.plupload.uploader.bind('Init', function() { phpbb.plupload.uploader.bind('Init', function() {
phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0]; phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0];
let $attachRowTemplate = $('#attach-row-tpl'); const $attachRowTemplate = $('#attach-row-tpl');
$attachRowTemplate.removeClass('attach-row-tpl'); $attachRowTemplate.removeClass('attach-row-tpl');
phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML; phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML;
@ -300,7 +303,7 @@ phpbb.plupload.deleteFile = function(row, attachId) {
$.ajax(phpbb.plupload.config.url, { $.ajax(phpbb.plupload.config.url, {
type: 'POST', type: 'POST',
data: $.extend(fields, phpbb.plupload.getSerializedData()), data: $.extend(fields, phpbb.plupload.getSerializedData()),
headers: phpbb.plupload.config.headers headers: phpbb.plupload.config.headers,
}) })
.always(always) .always(always)
.done(done); .done(done);
@ -452,7 +455,7 @@ phpbb.plupload.fileError = function(file, error) {
.addClass('file-error') .addClass('file-error')
.attr({ .attr({
'data-error-title': phpbb.plupload.lang.ERROR, 'data-error-title': phpbb.plupload.lang.ERROR,
'data-error-message': error 'data-error-message': error,
}); });
}; };
@ -469,14 +472,14 @@ phpbb.plupload.initialize();
plupload.addFileFilter('mime_types_max_file_size', function(types, file, callback) { plupload.addFileFilter('mime_types_max_file_size', function(types, file, callback) {
if (file.size !== 'undefined') { if (file.size !== 'undefined') {
$(types).each(function(i, type) { $(types).each(function(i, type) {
let extensions = [], const extensions = [],
extsArray = type.extensions.split(','); extsArray = type.extensions.split(',');
$(extsArray).each(function(i, extension) { $(extsArray).each(function(i, extension) {
/^\s*\*\s*$/.test(extension) ? extensions.push("\\.*") : extensions.push("\\." + extension.replace(new RegExp("[" + "/^$.*+?|()[]{}\\".replace(/./g, "\\$&") + "]", "g"), "\\$&")); /^\s*\*\s*$/.test(extension) ? extensions.push('\\.*') : extensions.push('\\.' + extension.replace(new RegExp('[' + '/^$.*+?|()[]{}\\'.replace(/./g, '\\$&') + ']', 'g'), '\\$&'));
}); });
let regex = new RegExp("(" + extensions.join("|") + ")$", "i"); const regex = new RegExp('(' + extensions.join('|') + ')$', 'i');
if (regex.test(file.name)) { if (regex.test(file.name)) {
if (type.max_file_size !== 'undefined' && type.max_file_size) { if (type.max_file_size !== 'undefined' && type.max_file_size) {
@ -484,7 +487,7 @@ plupload.addFileFilter('mime_types_max_file_size', function(types, file, callbac
phpbb.plupload.uploader.trigger('Error', { phpbb.plupload.uploader.trigger('Error', {
code: plupload.FILE_SIZE_ERROR, code: plupload.FILE_SIZE_ERROR,
message: plupload.translate('File size error.'), message: plupload.translate('File size error.'),
file: file file: file,
}); });
callback(false); callback(false);
@ -587,9 +590,9 @@ phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) {
up.trigger('FileUploaded', file, { up.trigger('FileUploaded', file, {
response: JSON.stringify({ response: JSON.stringify({
error: { error: {
message: 'Error parsing server response.' message: 'Error parsing server response.',
} },
}) }),
}); });
} }
@ -603,9 +606,9 @@ phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) {
up.trigger('FileUploaded', file, { up.trigger('FileUploaded', file, {
response: JSON.stringify({ response: JSON.stringify({
error: { error: {
message: json.error.message message: json.error.message,
} },
}) }),
}); });
} }
}); });

View file

@ -1681,6 +1681,18 @@ switch ($mode)
$memberrow = array_merge($memberrow, $cp_row['row']); $memberrow = array_merge($memberrow, $cp_row['row']);
} }
/**
* Modify the memberrow data before template variables are assigned.
*
* @event core.memberlist_modify_memberrow
* @var int user_id The current user ID.
* @var array row Array of raw user data.
* @var array memberrow Array of member template variables.
* @since 3.3.16-RC1
*/
$vars = ['user_id', 'row', 'memberrow'];
extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_memberrow', compact($vars)));
$template->assign_block_vars('memberrow', $memberrow); $template->assign_block_vars('memberrow', $memberrow);
if (isset($cp_row['blockrow']) && count($cp_row['blockrow'])) if (isset($cp_row['blockrow']) && count($cp_row['blockrow']))

View file

@ -22,7 +22,12 @@ class rename_duplicated_index_names extends migration
/** /**
* @var array * @var array
*/ */
protected $table_keys = []; protected static $table_keys;
/**
* @var array
*/
protected static $rename_index;
public static function depends_on() public static function depends_on()
{ {
@ -33,14 +38,15 @@ class rename_duplicated_index_names extends migration
public function update_schema() public function update_schema()
{ {
$rename_index = []; if (!isset(self::$rename_index))
if (empty($this->table_keys)) {
if (!isset(self::$table_keys))
{ {
$this->get_tables_index_names(); $this->get_tables_index_names();
} }
$short_table_names = table_helper::map_short_table_names(array_keys($this->table_keys), $this->table_prefix); $short_table_names = table_helper::map_short_table_names(array_keys(self::$table_keys), $this->table_prefix);
foreach ($this->table_keys as $table_name => $key_names) foreach (self::$table_keys as $table_name => $key_names)
{ {
$prefixless_table_name = doctrine_dbtools::remove_prefix($table_name, $this->table_prefix); $prefixless_table_name = doctrine_dbtools::remove_prefix($table_name, $this->table_prefix);
foreach ($key_names as $key_name) foreach ($key_names as $key_name)
@ -60,12 +66,13 @@ class rename_duplicated_index_names extends migration
} }
$key_name_new = $short_table_names[$table_name] . '_' . $cleaned_key_name; $key_name_new = $short_table_names[$table_name] . '_' . $cleaned_key_name;
$rename_index[$table_name][$key_name] = $key_name_new; self::$rename_index[$table_name][$key_name] = $key_name_new;
}
} }
} }
return [ return [
'rename_index' => $rename_index, 'rename_index' => self::$rename_index,
]; ];
} }
@ -121,7 +128,7 @@ class rename_duplicated_index_names extends migration
if (!empty($indices)) if (!empty($indices))
{ {
$this->table_keys[$table_name] = $indices; self::$table_keys[$table_name] = $indices;
} }
} }
} }
@ -131,7 +138,7 @@ class rename_duplicated_index_names extends migration
{ {
if (isset($table_data['KEYS'])) if (isset($table_data['KEYS']))
{ {
$this->table_keys[$table_name] = array_keys($table_data['KEYS']); self::$table_keys[$table_name] = array_keys($table_data['KEYS']);
} }
} }
} }

View file

@ -72,6 +72,8 @@ abstract class migration implements migration_interface
$this->php_ext = $php_ext; $this->php_ext = $php_ext;
$this->errors = array(); $this->errors = array();
$this->db_tools->set_table_prefix($this->table_prefix);
} }
/** /**

View file

@ -339,6 +339,14 @@ class helper
protected function render_language_select($selected_language = null) protected function render_language_select($selected_language = null)
{ {
$langs = $this->lang_helper->get_available_languages(); $langs = $this->lang_helper->get_available_languages();
// The first language will be selected by default. Unless a user has consciously included
// other languages in the installation process, it will be British English anyway.
if ($selected_language === null && count($langs))
{
$selected_language = $langs[0]['iso'];
}
foreach ($langs as $lang) foreach ($langs as $lang)
{ {
$this->template->assign_block_vars('language_select_item', array( $this->template->assign_block_vars('language_select_item', array(

View file

@ -145,7 +145,12 @@ class check_filesystem extends \phpbb\install\task_base
// Try to create file if it does not exists // Try to create file if it does not exists
if (!file_exists($path)) if (!file_exists($path))
{ {
$fp = @fopen($path, 'w'); if (!is_resource($fp = @fopen($path, 'w')))
{
$exists = $writable = false;
}
else
{
@fclose($fp); @fclose($fp);
try try
{ {
@ -155,21 +160,14 @@ class check_filesystem extends \phpbb\install\task_base
$exists = true; $exists = true;
} }
catch (\phpbb\filesystem\exception\filesystem_exception $e) catch (\phpbb\filesystem\exception\filesystem_exception $e)
{
// Do nothing
}
}
if (file_exists($path))
{
if (!$this->filesystem->is_writable($path))
{ {
$writable = false; $writable = false;
} }
} }
else }
else if (!$this->filesystem->is_writable($path))
{ {
$exists = $writable = false; $writable = false;
} }
$this->set_test_passed(($exists && $writable) || $failable); $this->set_test_passed(($exists && $writable) || $failable);

View file

@ -65,6 +65,8 @@ class language_file_helper
$available_languages[] = $this->get_language_data_from_json($data); $available_languages[] = $this->get_language_data_from_json($data);
} }
usort($available_languages, [$this, 'sort_by_local_name']);
return $available_languages; return $available_languages;
} }
@ -123,4 +125,16 @@ class language_file_helper
'turnstile_lang' => $data['extra']['turnstile-lang'] ?? '', 'turnstile_lang' => $data['extra']['turnstile-lang'] ?? '',
]; ];
} }
/**
* Sorts the languages by their name instead of iso code
*
* @param mixed $a First language data
* @param mixed $b Second language data
* @return int
*/
private static function sort_by_local_name(mixed $a, mixed $b): int
{
return $a['local_name'] <=> $b['local_name'];
}
} }

View file

@ -161,6 +161,16 @@ 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

@ -24,9 +24,13 @@ class event extends \Twig\Node\Node
/** @var \phpbb\template\twig\environment */ /** @var \phpbb\template\twig\environment */
protected $environment; protected $environment;
public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) /** @var array */
protected $template_event_priority_array;
public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null, $template_event_priority_array = [])
{ {
$this->environment = $environment; $this->environment = $environment;
$this->template_event_priority_array = $template_event_priority_array;
parent::__construct(array('expr' => $expr), array(), $lineno, $tag); parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
} }
@ -42,10 +46,20 @@ class event extends \Twig\Node\Node
$location = $this->listener_directory . $this->getNode('expr')->getAttribute('name'); $location = $this->listener_directory . $this->getNode('expr')->getAttribute('name');
$template_event_listeners = [];
// Group and sort extension template events in according to their priority (0 by default if not set)
foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path) foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path)
{ {
$ext_namespace = str_replace('/', '_', $ext_namespace); $ext_namespace = str_replace('/', '_', $ext_namespace);
$priority_key = intval($this->template_event_priority_array[$ext_namespace][$location] ?? 0);
$template_event_listeners[$priority_key][] = $ext_namespace;
}
krsort($template_event_listeners);
$template_event_listeners = array_merge(...$template_event_listeners);
foreach ($template_event_listeners as $ext_namespace)
{
if ($this->environment->isDebug()) if ($this->environment->isDebug())
{ {
// If debug mode is enabled, lets check for new/removed EVENT // If debug mode is enabled, lets check for new/removed EVENT
@ -54,8 +68,7 @@ class event extends \Twig\Node\Node
// purge the cache when a new event template file is added) // purge the cache when a new event template file is added)
$compiler $compiler
->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n") ->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n")
->indent() ->indent();
;
} }
if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html')) if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html'))
@ -66,16 +79,14 @@ class event extends \Twig\Node\Node
// We set the namespace lookup order to be this extension first, then the main path // We set the namespace lookup order to be this extension first, then the main path
->write("\$this->env->setNamespaceLookUpOrder(array('{$ext_namespace}', '__main__'));\n") ->write("\$this->env->setNamespaceLookUpOrder(array('{$ext_namespace}', '__main__'));\n")
->write("\$this->env->loadTemplate(\$this->env->getTemplateClass('@{$ext_namespace}/{$location}.html'), '@{$ext_namespace}/{$location}.html')->display(\$context);\n") ->write("\$this->env->loadTemplate(\$this->env->getTemplateClass('@{$ext_namespace}/{$location}.html'), '@{$ext_namespace}/{$location}.html')->display(\$context);\n")
->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n") ->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n");
;
} }
if ($this->environment->isDebug()) if ($this->environment->isDebug())
{ {
$compiler $compiler
->outdent() ->outdent()
->write("}\n\n") ->write("}\n\n");
;
} }
} }
} }

View file

@ -18,6 +18,9 @@ class event extends \Twig\TokenParser\AbstractTokenParser
/** @var \phpbb\template\twig\environment */ /** @var \phpbb\template\twig\environment */
protected $environment; protected $environment;
/** @var array */
protected $template_event_priority_array;
/** /**
* Constructor * Constructor
* *
@ -26,6 +29,25 @@ class event extends \Twig\TokenParser\AbstractTokenParser
public function __construct(\phpbb\template\twig\environment $environment) public function __construct(\phpbb\template\twig\environment $environment)
{ {
$this->environment = $environment; $this->environment = $environment;
$phpbb_dispatcher = $this->environment->get_phpbb_dispatcher();
$template_event_priority_array = [];
/**
* Allows assigning priority to template event listeners
*
* @event core.twig_event_tokenparser_constructor
* @var array template_event_priority_array Array with template event priority assignments per extension namespace
*
* @since 4.0.0-a1
*/
if ($phpbb_dispatcher)
{
$vars = ['template_event_priority_array'];
extract($phpbb_dispatcher->trigger_event('core.twig_event_tokenparser_constructor', compact($vars)));
}
$this->template_event_priority_array = $template_event_priority_array;
unset($template_event_priority_array);
} }
/** /**
@ -42,7 +64,7 @@ class event extends \Twig\TokenParser\AbstractTokenParser
$stream = $this->parser->getStream(); $stream = $this->parser->getStream();
$stream->expect(\Twig\Token::BLOCK_END_TYPE); $stream->expect(\Twig\Token::BLOCK_END_TYPE);
return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag()); return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag(), $this->template_event_priority_array);
} }
/** /**

View file

@ -87,9 +87,12 @@ class twig extends \phpbb\template\base
$this->loader = $twig_environment->getLoader(); $this->loader = $twig_environment->getLoader();
foreach ($extensions as $extension) foreach ($extensions as $extension)
{
if (!$this->twig->hasExtension(get_class($extension)))
{ {
$this->twig->addExtension($extension); $this->twig->addExtension($extension);
} }
}
// Add admin namespace // Add admin namespace
if ($this->path_helper->get_adm_relative_path() !== null if ($this->path_helper->get_adm_relative_path() !== null

View file

@ -4,4 +4,4 @@
to hide visually and `aria-hidden="true"` to hide from screen-readers; using to hide visually and `aria-hidden="true"` to hide from screen-readers; using
`hidden` or `display: none` would prevent the task from running. `hidden` or `display: none` would prevent the task from running.
#} #}
<img class="sr-only" aria-hidden="true" src="{{ CRON_TASK_URL|e('url') }}" width="1" height="1" alt=""> <img class="sr-only" aria-hidden="true" src="{{ CRON_TASK_URL|e('html_attr') }}" width="1" height="1" alt="">

View file

@ -1,4 +1,6 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
@ -11,7 +13,7 @@ phpbb.addAjaxCallback('mark_forums_read', function(res) {
var iconsArray = { var iconsArray = {
forum_unread: 'forum_read', forum_unread: 'forum_read',
forum_unread_subforum: 'forum_read_subforum', forum_unread_subforum: 'forum_read_subforum',
forum_unread_locked: 'forum_read_locked' forum_unread_locked: 'forum_read_locked',
}; };
$('li.row').find('dl[class*="forum_unread"]').each(function() { $('li.row').find('dl[class*="forum_unread"]').each(function() {
@ -52,7 +54,7 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
global_unread: 'global_read', global_unread: 'global_read',
announce_unread: 'announce_read', announce_unread: 'announce_read',
sticky_unread: 'sticky_read', sticky_unread: 'sticky_read',
topic_unread: 'topic_read' topic_unread: 'topic_read',
}; };
var iconsState = [ '', '_hot', '_hot_mine', '_locked', '_locked_mine', '_mine' ]; var iconsState = [ '', '_hot', '_hot_mine', '_locked', '_locked_mine', '_mine' ];
var unreadClassSelectors; var unreadClassSelectors;
@ -332,7 +334,7 @@ $('[data-ajax]').each(function() {
selector: this, selector: this,
refresh: $this.attr('data-refresh') !== undefined, refresh: $this.attr('data-refresh') !== undefined,
filter: filter, filter: filter,
callback: fn callback: fn,
}); });
} }
}); });
@ -367,7 +369,7 @@ $('.display_post').click(function(e) {
$('.display_post_review').on('click', function(e) { $('.display_post_review').on('click', function(e) {
e.preventDefault(); e.preventDefault();
let $displayPostLink = $(this); const $displayPostLink = $(this);
$displayPostLink.closest('.post-ignore').removeClass('post-ignore'); $displayPostLink.closest('.post-ignore').removeClass('post-ignore');
$displayPostLink.hide(); $displayPostLink.hide();
}); });

View file

@ -1,4 +1,7 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var:0 */
/** /**
* phpBB forum functions * phpBB forum functions
@ -496,7 +499,7 @@ function parseDocument($container) {
// Find all headers, get contents // Find all headers, get contents
$list.prev('.topiclist').find('li.header dd').not('.mark').each(function() { $list.prev('.topiclist').find('li.header dd').not('.mark').each(function() {
headers.push($("<div>").text($(this).text()).html()); headers.push($('<div>').text($(this).text()).html());
headersLength++; headersLength++;
}); });
@ -600,7 +603,7 @@ function parseDocument($container) {
if ((text.length && text !== '-') || cell.children().length) { if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) { if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column])); cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
} }
} else { } else {
cell.addClass('empty'); cell.addClass('empty');
@ -687,7 +690,7 @@ function parseDocument($container) {
var $tabLink = $item.find('a.responsive-tab-link'); var $tabLink = $item.find('a.responsive-tab-link');
phpbb.registerDropdown($tabLink, $item.find('.dropdown'), { phpbb.registerDropdown($tabLink, $item.find('.dropdown'), {
visibleClass: 'activetab' visibleClass: 'activetab',
}); });
check(true); check(true);

View file

@ -60,7 +60,7 @@ class phpbb_cron_wrapper_test extends phpbb_template_template_test_case
$this->template $this->template
); );
$this->assertEquals('<img class="sr-only" aria-hidden="true" src="app.php%2Fcron%2Ffoo%3Ff%3D5" width="1" height="1" alt="">', str_replace(["\n", "\t"], '', $this->wrapper->get_html_tag())); $this->assertEquals('<img class="sr-only" aria-hidden="true" src="app.php&#x2F;cron&#x2F;foo&#x3F;f&#x3D;5" width="1" height="1" alt="">', str_replace(["\n", "\t"], '', $this->wrapper->get_html_tag()));
} }
public function test_is_parametrized_false() public function test_is_parametrized_false()

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_controller_test extends phpbb_functional_test_case class phpbb_functional_extension_controller_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_global_lang_test extends phpbb_functional_test_case class phpbb_functional_extension_global_lang_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -17,8 +17,6 @@ require_once __DIR__ . '/../../phpBB/includes/acp/acp_modules.php';
*/ */
class phpbb_functional_extension_module_test extends phpbb_functional_test_case class phpbb_functional_extension_module_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_permission_lang_test extends phpbb_functional_test_case class phpbb_functional_extension_permission_lang_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -0,0 +1,105 @@
<?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.
*
*/
/**
* @group functional
*/
class phpbb_functional_extension_template_event_order_test extends phpbb_functional_test_case
{
static private $helper;
static protected $fixtures = [
'./',
];
static public function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
self::$helper = new phpbb_test_case_helpers(__CLASS__);
self::$helper->copy_ext_fixtures(__DIR__ . '/fixtures/ext/', self::$fixtures);
}
static public function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
self::$helper->restore_original_ext_dir();
}
protected function setUp(): void
{
parent::setUp();
$this->purge_cache();
}
protected function tearDown(): void
{
$this->uninstall_ext('foo/bar');
$this->uninstall_ext('foo/foo');
parent::tearDown();
}
protected static function setup_extensions()
{
return ['foo/bar', 'foo/foo'];
}
/**
* Check extensions template event listener prioritizing
*/
public function test_different_template_event_priority()
{
global $phpbb_root_path;
$crawler = self::request('GET', 'index.php');
$quick_links_menu = $crawler->filter('ul[role="menu"]')->eq(0);
$quick_links_menu_nodes_count = (int) $quick_links_menu->filter('li')->count();
// Ensure foo/foo template event goes before foo/bar one
$this->assertStringContainsString('FOO_FOO_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 4)->filter('span')->text());
$this->assertStringContainsString('FOO_BAR_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 3)->filter('span')->text());
// Change template events order to default, put foo/bar event before foo/foo one
$this->disable_ext('foo/bar');
$this->disable_ext('foo/foo');
$this->assertTrue(copy(__DIR__ . '/fixtures/ext/foo/bar/event/template_event_order_higher.php', $phpbb_root_path . 'ext/foo/bar/event/template_event_order.php'));
$this->assertTrue(copy(__DIR__ . '/fixtures/ext/foo/foo/event/template_event_order_lower.php', $phpbb_root_path . 'ext/foo/foo/event/template_event_order.php'));
$this->install_ext('foo/bar');
$this->install_ext('foo/foo');
$crawler = self::request('GET', 'index.php');
$quick_links_menu = $crawler->filter('ul[role="menu"]')->eq(0);
$quick_links_menu_nodes_count = (int) $quick_links_menu->filter('li')->count();
// Ensure foo/foo template event goes before foo/bar one
$this->assertStringContainsString('FOO_BAR_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 4)->filter('span')->text());
$this->assertStringContainsString('FOO_FOO_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 3)->filter('span')->text());
}
/**
* Check extensions template event listener equal (default - 0) priority rendering
* Should render in the order of reading listener files from the filesystem
*/
public function test_same_template_event_priority()
{
global $phpbb_root_path;
$crawler = self::request('GET', 'index.php');
// Ensure foo/bar template event goes before foo/foo one (assuming they have been read from the filesystem in alphabetical order)
$this->assertStringContainsString('FOO_BAR_FORUMLIST_BODY_BEFORE', $crawler->filter('p[id*="forumlist_body_before"]')->eq(0)->text());
$this->assertStringContainsString('FOO_FOO_FORUMLIST_BODY_BEFORE', $crawler->filter('p[id*="forumlist_body_before"]')->eq(1)->text());
}
}

View file

@ -14,7 +14,13 @@ services:
class: foo\bar\event\permission class: foo\bar\event\permission
tags: tags:
- { name: event.listener } - { name: event.listener }
foo_bar.listener.user_setup: foo_bar.listener.user_setup:
class: foo\bar\event\user_setup class: foo\bar\event\user_setup
tags: tags:
- { name: event.listener } - { name: event.listener }
foo_bar.listener.template_event_order:
class: foo\bar\event\template_event_order
tags:
- { name: event.listener }

View file

@ -0,0 +1,38 @@
<?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 foo\bar\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_bar'] = [
'event/navbar_header_quick_links_after' => -1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1,38 @@
<?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 foo\bar\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_bar'] = [
'event/navbar_header_quick_links_after' => 1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1 @@
<p id="foo_bar_forumlist_body_before">{{ lang('FOO_BAR_FORUMLIST_BODY_BEFORE') }}</p>

View file

@ -0,0 +1 @@
<li><span>{{ lang('FOO_BAR_QUICK_LINK') }}</span></li>

View file

@ -1,3 +1,8 @@
services: services:
foo_foo.controller: foo_foo.controller:
class: foo\foo\controller\controller class: foo\foo\controller\controller
foo_foo.listener.template_event_order:
class: foo\foo\event\template_event_order
tags:
- { name: event.listener }

View file

@ -0,0 +1,38 @@
<?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 foo\foo\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_foo'] = [
'event/navbar_header_quick_links_after' => 1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1,38 @@
<?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 foo\foo\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_foo'] = [
'event/navbar_header_quick_links_after' => -1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1 @@
<p id="foo_foo_forumlist_body_before">{{ lang('FOO_FOO_FORUMLIST_BODY_BEFORE') }}</p>

View file

@ -0,0 +1 @@
<li><span>{{ lang('FOO_FOO_QUICK_LINK') }}</span></li>

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_metadata_manager_test extends phpbb_functional_test_case class phpbb_functional_metadata_manager_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -645,7 +645,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$meta_refresh = $crawler->filter('meta[http-equiv="refresh"]'); $meta_refresh = $crawler->filter('meta[http-equiv="refresh"]');
// Wait for extension to be fully enabled // Wait for extension to be fully disabled
while (count($meta_refresh)) while (count($meta_refresh))
{ {
preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match); preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match);