Compare commits

...

94 commits

Author SHA1 Message Date
rxu
967a7349da
[ticket/17524] Try not to hit MSSQL index key length limitations
900 bytes for a clustered index. 1,700 bytes for a nonclustered index.
For SQL Server 2014 (12.x) and earlier, all versions supported 900 bytes
for all index types.

PHPBB-17524
2025-07-06 01:39:58 +07:00
rxu
ffcd71ac87
[ticket/17524] Add test assertions
PHPBB-17524
2025-07-06 01:39:57 +07:00
rxu
c47e5d34df
[ticket/17524] Add index migrator tests
PHPBB-17524
2025-07-06 01:39:57 +07:00
rxu
418aa469d7
[ticket/17524] Add index data getter to db tools
PHPBB-17524
2025-07-06 01:39:56 +07:00
rxu
aef616381e
[ticket/17524] Add possibility to use index key length in migrations
PHPBB-17524
2025-07-06 01:39:16 +07:00
Marc Alexander
4367bc8d11
Merge pull request #6830 from rxu/ticket/17525
[ticket/17525] Correctly handle Doctrine DB tools exceptions, enrich error info
2025-07-05 09:31:52 +02:00
rxu
aa3f266b8c
[ticket/17525] Address the PR review comments
PHPBB-17525
2025-07-05 12:51:40 +07:00
rxu
10921ebc58
[ticket/17525] Fix migration failure on update
PHPBB-17525
2025-07-04 11:30:46 +07:00
rxu
5eaabb1c39
[ticket/17525] Fix handling index name prefix logic for renaming
PHPBB-17525
2025-07-04 01:25:04 +07:00
rxu
b5c3befa87
[ticket/17525] Fix handling index name prefix logic for renaming
PHPBB-17525
2025-07-02 11:01:49 +07:00
rxu
669af8f3aa
[ticket/17525] Automatically handle index name prefixes
PHPBB-17525
2025-07-01 23:32:36 +07:00
rxu
8e0ec1edd2
[ticket/17525] Automatically handle index name prefixes
PHPBB-17525
2025-07-01 21:01:09 +07:00
rxu
e9157f4d10
[ticket/17525] Fix tests
PHPBB-17525
2025-07-01 16:53:29 +07:00
rxu
4274faa715
[ticket/17525] Provide Doctrine connection via dbtools
PHPBB-17525
2025-07-01 15:53:19 +07:00
rxu
1cadb3818a
[ticket/17525] Provide Doctrine connection object for migrations
PHPBB-17525
2025-07-01 14:27:38 +07:00
rxu
58b3e5dee0
[ticket/17525] Migration to rename actual database indexes if any
Also generate short table names rather than use hardcoded map

PHPBB-17525
2025-07-01 00:11:36 +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
rxu
4da8591dd8
[ticket/17525] Run index renaming migration the last in migrations queue
PHPBB-17525
2025-06-27 22:10:27 +07:00
Matt Friedman
158a561651
[ticket/17517] Update and refactor eslint implementation
PHPBB-17517
2025-06-26 18:25:05 -07:00
rxu
5e9d616f57
[ticket/17525] Map Sphinx table, add more test assertions
PHPBB-17525
2025-06-25 23:48:45 +07:00
rxu
de1f6329ff
[ticket/17525] Fix tests
PHPBB-17525
2025-06-25 22:44:08 +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
75c5fe9459
[ticket/17525] Add index names test for generated database schema
PHPBB-17525
2025-06-25 22:24:50 +07:00
rxu
a229797cd7
[ticket/17525] Add database schema getter
PHPBB-17525
2025-06-25 21:02:30 +07:00
rxu
1339a31c23
[ticket/17525] Rename all indexes to make names unique
With this reNAMING schema, max index name length is 23.

PHPBB-17525
2025-06-25 17:42:36 +07: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
rxu
45a69eca14
[ticket/17525] Rename migration to reflect its purpose
PHPBB-17525
2025-06-17 14:09:34 +07:00
Daniel James
72c3745868 [ticket/17522] Change event name and update var type
PHPBB-17522
2025-06-17 07:18:41 +01:00
rxu
84d195ac21
[ticket/17525] Add migration renaming index test
PHPBB-17525
2025-06-17 12:27:47 +07:00
rxu
78dcb0c862
[ticket/17525] Avoid more index name duplication
PHPBB-17525
2025-06-17 09:32:19 +07:00
rxu
7b0b95250c
[ticket/17525] Avoid more index name duplication
Many more tables have indexes with the same names which can cause issues
on SQLite/Postgres. Also, add an option for migrations to rename indexes.

PHPBB-17525
2025-06-17 00:46:17 +07: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
rxu
0e0214a71d
[ticket/17525] Avoid index name duplication (auth_role_id)
phpbb_acl_groups and phpbb_acl_users have indexes
with the same names (auth_role_id) which can cause issues on SQLite/Postgres

PHPBB-17525
2025-06-15 15:51:59 +07: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
8d1f8af7c6
[ticket/17525] Correctly handle Doctrine DB tools exceptions, enrich error info
PHPBB-17525
2025-06-15 13:03:55 +07: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
Marc Alexander
e34e1759c7 Merge branch '3.3.x' 2025-06-14 07:00:39 +00:00
Marc Alexander
8f8a93fa71
Merge pull request #6818 from rxu/ticket/17515
[ticket/17515] Add template event before PM text - 3.3.x
2025-06-14 08:51:41 +02:00
Marc Alexander
f1d8255aca
Merge pull request #6819 from rxu/ticket/17515-master
[ticket/17515] Add template event before PM text - master
2025-06-14 08:51:36 +02:00
Marc Alexander
851de03961
Merge pull request #6821 from rxu/ticket/17509
[ticket/17509] Bump DBMS supported versions
2025-06-14 08:50:03 +02:00
Marc Alexander
0a86130f7f
Merge pull request #6817 from iMattPro/ticket/17513
[ticket/17513] Wrap async logic inside event.waitUntil in push worker
2025-06-14 08:46:57 +02:00
Marc Alexander
083ae1102b Merge branch '3.3.x' 2025-06-13 18:52:53 +00:00
Marc Alexander
c726382d84
Merge pull request #6824 from iMattPro/ticket/17519
[ticket/17519] Correctly encode cron task urls
2025-06-13 20:41:22 +02:00
Marc Alexander
db19a4a578
Merge pull request #6828 from marc1706/ticket/17519-master
[ticket/17519] Correctly encode cron task urls -- master version
2025-06-13 20:41:18 +02:00
Marc Alexander
0b3897b8c3
[ticket/17519] Adapt wrapper test for master
PHPBB-17519
2025-06-12 21:38:55 +02:00
Marc Alexander
b2d48b679f
Merge branch 'ticket/17519' into ticket/17519-master 2025-06-12 21:15:38 +02:00
Marc Alexander
5deeea025f
[ticket/17519] Add unit tests for task wrapper
PHPBB-17519
2025-06-12 21:00:24 +02:00
Marc Alexander
d3bb7e5bd3
Merge pull request #6823 from CHItA/ticket/17516
[ticket/17516] Remove dependency on topological sort library
2025-06-11 17:25:52 +02: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
Matt Friedman
6947dc8c92 [ticket/17519] Correctly encode cron task urls
PHPBB-17519
2025-06-03 04:21:24 +00:00
Máté Bartus
b9df5bbbf0 [ticket/17516] Remove dependency on topological sort library
PHPBB-17516
2025-06-01 12:06:58 +01:00
rxu
f23af6f485
[ticket/17509] Add MariaDB version requirement check
PHPBB-17509
2025-05-30 11:54:32 +07:00
rxu
b8e5caedbf
[ticket/17509] Fix tests
PHPBB-17509
2025-05-30 11:20:25 +07:00
rxu
50e7103080
[ticket/17509] Output db tools error test
PHPBB-17509
2025-05-29 23:15:47 +07:00
rxu
d8bbe3e58c
[ticket/17509] Upgrade Doctrine dbal to the v.3.9
PHPBB-17509
2025-05-29 22:13:32 +07:00
rxu
bf2c22354a
[ticket/17509] Add installer DBMS version checks
PHPBB-17509
2025-05-29 20:27:47 +07:00
rxu
215d1bf1eb
[ticket/17509] Bump DBMS supported versions
PHPBB-17509
2025-05-29 17:45:32 +07:00
rxu
759f061656
Merge branch 'ticket/17515' into ticket/17515-master 2025-05-22 14:02:28 +07:00
rxu
ddc7f1df34
[ticket/17515] Add template event before PM text
PHPBB-17515
2025-05-22 13:29:47 +07: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
Matt Friedman
6b6b5ffc28
[ticket/17513] Fix JS linting
PHPBB-17513
2025-05-20 12:11:39 -07:00
Matt Friedman
4f66ec8758
[ticket/17513] Wrap async logic inside event.waitUntil in push worker
PHPBB-17513
2025-05-20 10:23:00 -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
82 changed files with 2819 additions and 1114 deletions

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

@ -14,6 +14,6 @@ set +x
sudo npm install -g > /dev/null
npm ci > /dev/null
set -x
node_modules/eslint/bin/eslint.js "phpBB/**/*.js"
node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig"
node_modules/eslint/bin/eslint.js "phpBB/**/*.js" --ignore-pattern "phpBB/ext/"
node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig" --ignore-pattern "phpBB/ext/"
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,
];

1784
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,65 +6,6 @@
"directories": {
"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": [
"> 1%",
"not ie 11",
@ -101,8 +42,8 @@
"devDependencies": {
"autoprefixer": "^10.4.4",
"cssnano": "^5.1.7",
"eslint": "^8.13.0",
"eslint-config-xo": "^0.40.0",
"eslint": "^9.28.0",
"globals": "^16.2.0",
"gulp": "^5.0.0",
"gulp-concat": "^2.6.1",
"gulp-postcss": "^9.0.1",

View file

@ -11,6 +11,7 @@
<div class="errorbox">
<p><strong>{{ lang('MIGRATION_EXCEPTION_ERROR') }}</strong></p>
<p>{{ MIGRATOR_ERROR }}</p>
{% if MIGRATOR_ERROR_STACK_TRACE %}<p>{{ MIGRATOR_ERROR_STACK_TRACE|nl2br }}</p>{% endif %}
<p><a href="{{ U_RETURN }}">{{ lang('RETURN_TO_EXTENSION_LIST') }}</a></p>
</div>
{% elseif S_PRE_STEP %}

View file

@ -11,6 +11,7 @@
<div class="errorbox">
<p><strong>{{ lang('MIGRATION_EXCEPTION_ERROR') }}</strong></p>
<p>{{ MIGRATOR_ERROR }}</p>
{% if MIGRATOR_ERROR_STACK_TRACE %}<p>{{ MIGRATOR_ERROR_STACK_TRACE|nl2br }}</p>{% endif %}
<p><a href="{{ U_RETURN }}">{{ lang('RETURN_TO_EXTENSION_LIST') }}</a></p>
</div>
{% elseif S_PRE_STEP %}

View file

@ -1,4 +1,6 @@
/* global phpbb */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
/**
* phpBB ACP functions
@ -10,7 +12,7 @@
function parse_document(container)
{
var test = document.createElement('div'),
oldBrowser = (typeof test.style.borderRadius == 'undefined');
oldBrowser = (typeof test.style.borderRadius === 'undefined');
test.remove();
@ -79,7 +81,7 @@ function parse_document(container)
dfn = cell.attr('data-dfn'),
text = dfn ? dfn : $.trim(cell.text());
if (text == '&nbsp;') text = '';
if (text === '&nbsp;') text = '';
colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
for (i=0; i<colspan; i++) {
@ -108,7 +110,7 @@ function parse_document(container)
cells = row.children('td'),
column = 0;
if (cells.length == 1) {
if (cells.length === 1) {
row.addClass('big-column');
return;
}
@ -124,7 +126,7 @@ function parse_document(container)
if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column]));
cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
}
}
else {
@ -156,7 +158,7 @@ function parse_document(container)
*/
container.find('fieldset dt > span:last-child').each(function() {
var $this = $(this);
if ($this.html() == '&nbsp;') {
if ($this.html() === '&nbsp;') {
$this.addClass('responsive-hide');
}
});
@ -194,7 +196,7 @@ function parse_document(container)
links.each(function() {
var link = $(this);
maxHeight = Math.max(maxHeight, Math.max(link.outerHeight(true), link.parent().outerHeight(true)));
})
});
function check() {
var width = $body.width(),
@ -237,7 +239,7 @@ function parse_document(container)
menu.find('a').click(function() { check(true); });
}
phpbb.registerDropdown(item.find('a.responsive-tab-link'), item.find('.dropdown'), {visibleClass: 'activetab', verticalDirection: 'down'});
phpbb.registerDropdown(item.find('a.responsive-tab-link'), item.find('.dropdown'), { visibleClass: 'activetab', verticalDirection: 'down' });
check(true);
$(window).resize(check);
@ -262,7 +264,7 @@ function parse_document(container)
$('#questionnaire-form').css('display', 'none');
var $triggerConfiglist = $('#trigger-configlist');
$triggerConfiglist.on('click', function () {
$triggerConfiglist.on('click', function() {
var $configlist = $('#configlist');
$configlist.closest('.send-stats-data-row').toggleClass('send-stats-data-hidden');
$configlist.closest('.send-stats-row').find('.send-stats-data-row:first-child').toggleClass('send-stats-data-only-row');
@ -272,8 +274,8 @@ function parse_document(container)
$('#configlist').closest('.send-stats-data-row').addClass('send-stats-data-hidden');
// Do not underline actions icons on hover (could not be done via CSS)
$('.actions a:has(i.acp-icon)').mouseover(function () {
$(this).css("text-decoration", "none");
$('.actions a:has(i.acp-icon)').mouseover(function() {
$(this).css('text-decoration', 'none');
});
// Live update BBCode font icon preview
@ -296,11 +298,11 @@ function parse_document(container)
const pageIconFont = document.getElementById('bbcode_font_icon');
if (pageIconFont) {
pageIconFont.addEventListener('keyup', function () {
pageIconFont.addEventListener('keyup', function() {
updateIconClass(this.nextElementSibling, this.value);
});
pageIconFont.addEventListener('blur', function () {
pageIconFont.addEventListener('blur', function() {
updateIconClass(this.nextElementSibling, this.value);
});
}

View file

@ -1,16 +1,17 @@
/* global phpbb, statsData */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries
'use strict';
phpbb.prepareSendStats = function () {
phpbb.prepareSendStats = function() {
var $form = $('#acp_help_phpbb');
var $dark = $('#darkenwrapper');
var $loadingIndicator;
$form.on('submit', function (event) {
$form.on('submit', function(event) {
var $this = $(this),
currentTime = Math.floor(new Date().getTime() / 1000),
statsTime = parseInt($this.find('input[name=help_send_statistics_time]').val(), 10);
@ -23,7 +24,7 @@ phpbb.prepareSendStats = function () {
if (!$this.find('input[name=help_send_statistics]').is(':checked') ||
statsTime > currentTime) {
$form.find('input[type=submit]').click();
setTimeout(function () {
setTimeout(function() {
$form.find('input[type=submit]').click();
}, 300);
return;
@ -74,7 +75,7 @@ phpbb.prepareSendStats = function () {
var $sendStatisticsSuccess = $('<input />', {
type: 'hidden',
name: 'send_statistics_response',
value: JSON.stringify(res)
value: JSON.stringify(res),
});
$sendStatisticsSuccess.appendTo('p.submit-buttons');
@ -90,7 +91,7 @@ phpbb.prepareSendStats = function () {
data: statsData,
success: returnHandler,
error: errorHandler,
cache: false
cache: false,
}).always(function() {
if ($loadingIndicator && $loadingIndicator.is(':visible')) {
$loadingIndicator.fadeOut(phpbb.alertTime);
@ -176,7 +177,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
namedCurve: 'P-256',
},
true,
['deriveKey', 'deriveBits']
[ 'deriveKey', 'deriveBits' ],
);
const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
@ -187,7 +188,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
return {
privateKey: privateKeyString,
publicKey: publicKeyString
publicKey: publicKeyString,
};
} catch (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');
publicKeyInput.value = keyPair.publicKey;
privateKeyInput.value = keyPair.privateKey;
})
})
});
});
/**
* Handler for submitting permissions form in chunks
@ -230,7 +231,7 @@ function submitPermissions() {
fieldsetList = $form.find('fieldset#' + $submitButton.closest('fieldset.permissions').id);
}
$.each(fieldsetList, function (key, value) {
$.each(fieldsetList, function(key, value) {
dataSetIndex = Math.floor(key / 5);
var $fieldset = $('fieldset#' + value.id);
if (key % 5 === 0) {
@ -252,7 +253,7 @@ function submitPermissions() {
permissionSubmitSize = formDataSets.length;
// Add each forum ID to forum ID list to preserve selected forums
$.each($form.find('input[type=hidden][name^=forum_id]'), function (key, value) {
$.each($form.find('input[type=hidden][name^=forum_id]'), function(key, value) {
if (value.name.match(/^forum_id\[([0-9]+)\]$/)) {
forumIds.push(value.value);
}
@ -286,18 +287,18 @@ function submitPermissions() {
$alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, ''));
const $previousPageForm = $('<form>').attr({
action: $alertBoxLink.attr('href'),
method: 'post'
method: 'post',
});
$.each(forumIds, function (key, value) {
$.each(forumIds, function(key, value) {
$previousPageForm.append($('<input>').attr({
type: 'text',
name: 'forum_id[]',
value: value
value: value,
}));
});
$alertBoxLink.on('click', function (e) {
$alertBoxLink.on('click', function(e) {
$('body').append($previousPageForm);
e.preventDefault();
$previousPageForm.submit();
@ -309,19 +310,19 @@ function submitPermissions() {
$alert.find('.alert_close').hide();
if (typeof res.REFRESH_DATA !== 'undefined') {
setTimeout(function () {
setTimeout(function() {
// Create forum to submit using POST. This will prevent
// exceeding the maximum length of URLs
const $form = $('<form>').attr({
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({
type: 'text',
name: 'forum_id[]',
value: value
value: value,
}));
});
@ -329,7 +330,7 @@ function submitPermissions() {
// Hide the alert even if we refresh the page, in case the user
// presses the back button.
$dark.fadeOut(phpbb.alertTime, function () {
$dark.fadeOut(phpbb.alertTime, function() {
if (typeof $alert !== 'undefined') {
$alert.hide();
}
@ -355,7 +356,7 @@ function submitPermissions() {
}
// Create AJAX request for each form data set
$.each(formDataSets, function (key, formData) {
$.each(formDataSets, function(key, formData) {
$.ajax({
url: $form.action,
type: 'POST',
@ -365,7 +366,7 @@ function submitPermissions() {
'&' + $form.children('input[type=hidden]').serialize() +
'&' + $form.find('input[type=checkbox][name^=inherit]').serialize(),
success: handlePermissionReturn,
error: handlePermissionReturn
error: handlePermissionReturn,
});
});
}
@ -379,7 +380,7 @@ $('[data-ajax]').each(function() {
phpbb.ajaxify({
selector: this,
refresh: $this.attr('data-refresh') !== undefined,
callback: fn
callback: fn,
});
}
});
@ -388,11 +389,11 @@ $('[data-ajax]').each(function() {
* Automatically resize textarea
*/
$(function() {
phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), {minHeight: 75});
phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), { minHeight: 75 });
var $setPermissionsForm = $('form#set-permissions');
if ($setPermissionsForm.length) {
$setPermissionsForm.on('submit', function (e) {
$setPermissionsForm.on('submit', function(e) {
submitPermissions();
e.preventDefault();
});
@ -412,7 +413,7 @@ $(function() {
} else {
dateoptionInput.value = this.value;
}
})
});
}
if ($('#acp_help_phpbb')) {

View file

@ -20,7 +20,7 @@
<form method="post" action="#" id="language_selector">
<fieldset class="nobg">
<label for="language">{L_SELECT_LANG}{L_COLON}</label>
<select id="language" name="language">
<select id="language" name="language">
<!-- BEGIN language_select_item -->
<option value="{language_select_item.VALUE}"<!-- IF language_select_item.SELECTED --> selected="selected"<!-- ENDIF -->>{language_select_item.NAME}</option>
<!-- END language_select_item -->

View file

@ -1,4 +1,8 @@
/* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-undef: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var: 0 */
/**
* Hide and show all checkboxes
@ -372,7 +376,7 @@ function match_role_settings(id) {
* @return {string} The sorted object as a string
*/
function sort_and_stringify(obj) {
return JSON.stringify(Object.keys(obj).sort().reduce(function (result, key) {
return JSON.stringify(Object.keys(obj).sort().reduce(function(result, key) {
result[key] = obj[key];
return result;
}, {}));

View file

@ -1,4 +1,5 @@
/* global phpbb */
/* eslint no-var: 0 */
/*
javascript for Bubble Tooltips by Alessandro Fulciniti
@ -24,14 +25,14 @@ var tooltips = [];
* @param {string} headline Text that should appear on top of tooltip
* @param {string} [subId] Sub ID that should only be using tooltips (optional)
*/
phpbb.enableTooltipsSelect = function (id, headline, subId) {
phpbb.enableTooltipsSelect = function(id, headline, subId) {
var $links, hold;
hold = $('<span />', {
id: '_tooltip_container',
css: {
position: 'absolute'
}
position: 'absolute',
},
});
$('body').append(hold);
@ -42,7 +43,7 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) {
$links = $('.roles-options li', '#' + id);
}
$links.each(function () {
$links.each(function() {
var $this = $(this);
if (subId) {
@ -61,7 +62,7 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) {
* @param {jQuery} $element Element to prepare for tooltips
* @param {string} headText Text heading to display
*/
phpbb.prepareTooltips = function ($element, headText) {
phpbb.prepareTooltips = function($element, headText) {
var $tooltip, text, $desc, $title;
text = $element.attr('data-title');
@ -73,8 +74,8 @@ phpbb.prepareTooltips = function ($element, headText) {
$title = $('<span />', {
class: 'top',
css: {
display: 'block'
}
display: 'block',
},
})
.append(document.createTextNode(headText));
@ -82,15 +83,15 @@ phpbb.prepareTooltips = function ($element, headText) {
class: 'bottom',
html: text,
css: {
display: 'block'
}
display: 'block',
},
});
$tooltip = $('<span />', {
class: 'tooltip',
css: {
display: 'block'
}
display: 'block',
},
})
.append($title)
.append($desc);
@ -105,7 +106,7 @@ phpbb.prepareTooltips = function ($element, headText) {
*
* @param {object} $element Element passed by .on()
*/
phpbb.showTooltip = function ($element) {
phpbb.showTooltip = function($element) {
var $this = $($element.target);
$('#_tooltip_container').append(tooltips[$this.attr('data-id')]);
phpbb.positionTooltip($this);
@ -114,7 +115,7 @@ phpbb.showTooltip = function ($element) {
/**
* Hide tooltip
*/
phpbb.hideTooltip = function () {
phpbb.hideTooltip = function() {
var d = document.getElementById('_tooltip_container');
if (d.childNodes.length > 0) {
d.removeChild(d.firstChild);
@ -126,7 +127,7 @@ phpbb.hideTooltip = function () {
*
* @param {jQuery} $element Tooltip element that should be positioned
*/
phpbb.positionTooltip = function ($element) {
phpbb.positionTooltip = function($element) {
var offset;
$element = $element.parent();
@ -135,12 +136,12 @@ phpbb.positionTooltip = function ($element) {
if ($('body').hasClass('rtl')) {
$('#_tooltip_container').css({
top: offset.top + 30,
left: offset.left + 255
left: offset.left + 255,
});
} else {
$('#_tooltip_container').css({
top: offset.top + 30,
left: offset.left - 205
left: offset.left - 205,
});
}
};
@ -148,13 +149,13 @@ phpbb.positionTooltip = function ($element) {
/**
* Prepare roles drop down select
*/
phpbb.prepareRolesDropdown = function () {
phpbb.prepareRolesDropdown = function() {
var $options = $('.roles-options li');
// Display span and hide select
$('.roles-options > span').css('display', 'block');
$('.roles-options > select').hide();
$('.roles-options > input[type=hidden]').each(function () {
$('.roles-options > input[type=hidden]').each(function() {
var $this = $(this);
if ($this.attr('data-name') && !$this.attr('name')) {
@ -163,7 +164,7 @@ phpbb.prepareRolesDropdown = function () {
});
// Prepare highlighting of select options and settings update
$options.each(function () {
$options.each(function() {
var $this = $(this);
var $rolesOptions = $this.closest('.roles-options');
var $span = $rolesOptions.children('span');
@ -182,18 +183,18 @@ phpbb.prepareRolesDropdown = function () {
}
// Prepare resetting drop down on form reset
$this.closest('form').on('reset', function () {
$this.closest('form').on('reset', function() {
$span.text($span.attr('data-default'));
$rolesOptions.children('input[type=hidden]')
.val($span.attr('data-default-val'));
});
}
$this.on('mouseover', function () {
$this.on('mouseover', function() {
var $this = $(this);
$options.removeClass('roles-highlight');
$this.addClass('roles-highlight');
}).on('click', function () {
}).on('click', function() {
var $this = $(this);
var $rolesOptions = $this.closest('.roles-options');

View file

@ -1,4 +1,6 @@
/* global bbfontstyle */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
var phpbb = {};
phpbb.alertTime = 100;
@ -13,7 +15,7 @@ var keymap = {
ENTER: 13,
ESC: 27,
ARROW_UP: 38,
ARROW_DOWN: 40
ARROW_DOWN: 40,
};
var $dark = $('#darkenwrapper');
@ -54,7 +56,7 @@ phpbb.loadingIndicator = function() {
/**
* Show timeout message
*/
phpbb.showTimeoutMessage = function () {
phpbb.showTimeoutMessage = function() {
var $alert = $('#phpbb_alert');
if ($loadingIndicator.is(':visible')) {
@ -363,7 +365,7 @@ phpbb.ajaxify = function(options) {
type: 'POST',
data: data + '&confirm=' + res.YES_VALUE + '&' + $('form', '#phpbb_confirm').serialize(),
success: returnHandler,
error: errorHandler
error: errorHandler,
});
}, false);
}
@ -383,7 +385,7 @@ phpbb.ajaxify = function(options) {
submit = $this.find('input[type="submit"][data-clicked]');
data.push({
name: submit.attr('name'),
value: submit.val()
value: submit.val(),
});
}
} else if (isText) {
@ -409,7 +411,7 @@ phpbb.ajaxify = function(options) {
data: data,
success: returnHandler,
error: errorHandler,
cache: false
cache: false,
});
request.always(function() {
@ -430,7 +432,7 @@ phpbb.ajaxify = function(options) {
});
if (isForm) {
$elements.find('input:submit').click(function () {
$elements.find('input:submit').click(function() {
var $this = $(this);
// Remove data-clicked attribute from any submit button of form
@ -445,10 +447,10 @@ phpbb.ajaxify = function(options) {
phpbb.search = {
cache: {
data: []
data: [],
},
tpl: [],
container: []
container: [],
};
/**
@ -524,7 +526,7 @@ phpbb.search.getKeyword = function($input, keyword, multiline) {
* @param {jQuery} $textarea Search textarea.
* @returns {int} The line number.
*/
phpbb.search.getKeywordLine = function ($textarea) {
phpbb.search.getKeywordLine = function($textarea) {
var selectionStart = $textarea.get(0).selectionStart;
return $textarea.val().substr(0, selectionStart).split('\n').length - 1;
};
@ -609,7 +611,7 @@ phpbb.search.filter = function(data, event, sendRequest) {
if (cache.results[keyword]) {
var response = {
keyword: keyword,
results: cache.results[keyword]
results: cache.results[keyword],
};
phpbb.search.handleResponse(response, $this, true);
proceed = false;
@ -1079,7 +1081,7 @@ phpbb.addAjaxCallback('toggle_link', function() {
$this.attr('href', toggleUrl);
// 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,
heightDiff: 200,
resizeCallback: function() {},
resetCallback: function() {}
resetCallback: function() {},
};
if (phpbb.isTouch) {
@ -1152,7 +1154,7 @@ phpbb.resizeTextArea = function($items, options) {
var maxHeight = Math.min(
Math.max(windowHeight - configuration.heightDiff, configuration.minHeight),
configuration.maxHeight
configuration.maxHeight,
),
$item = $(item),
height = parseInt($item.innerHeight(), 10),
@ -1243,9 +1245,9 @@ phpbb.inBBCodeTag = function(textarea, startTags, endTags) {
*/
phpbb.applyCodeEditor = function(textarea) {
// list of allowed start and end bbcode code tags, in lower case
var startTags = ['[code]', '[code='],
var startTags = [ '[code]', '[code=' ],
startTagsEnd = ']',
endTags = ['[/code]'];
endTags = [ '[/code]' ];
if (!textarea || typeof textarea.selectionStart !== 'number') {
return;
@ -1353,12 +1355,12 @@ phpbb.showDragNDrop = function(textarea) {
return;
}
$('body').on('dragenter dragover', function () {
$('body').on('dragenter dragover', function() {
$(textarea).addClass('drag-n-drop');
}).on('dragleave dragout dragend drop', function() {
$(textarea).removeClass('drag-n-drop');
});
$(textarea).on('dragenter dragover', function () {
$(textarea).on('dragenter dragover', function() {
$(textarea).addClass('drag-n-drop-highlight');
}).on('dragleave dragout dragend drop', function() {
$(textarea).removeClass('drag-n-drop-highlight');
@ -1434,7 +1436,7 @@ phpbb.toggleDropdown = function(event_) {
marginLeft: 0,
left: 0,
marginRight: 0,
maxWidth: (windowWidth - 4) + 'px'
maxWidth: (windowWidth - 4) + 'px',
});
var offset = $this.offset().left,
@ -1468,7 +1470,7 @@ phpbb.toggleDropdown = function(event_) {
var maxOffset = Math.min(contentWidth, fullFreeSpace) + 'px';
options.dropdown.css({
width: maxOffset,
marginLeft: -maxOffset
marginLeft: -maxOffset,
});
}
} 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
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
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) {
ops = $.extend(ops, options);
@ -1666,7 +1668,7 @@ phpbb.toggleSelectSettings = function(el) {
* @param {string} functionName Function to get.
* @returns function
*/
phpbb.getFunctionByName = function (functionName) {
phpbb.getFunctionByName = function(functionName) {
var namespaces = functionName.split('.'),
func = namespaces.pop(),
context = window;
@ -1716,7 +1718,7 @@ phpbb.registerPageDropdowns = function() {
$contents = $this.find('.dropdown'),
options = {
direction: 'auto',
verticalDirection: 'auto'
verticalDirection: 'auto',
},
data;
@ -1763,7 +1765,7 @@ phpbb.registerPageDropdowns = function() {
* Handle avatars to be lazy loaded.
*/
phpbb.lazyLoadAvatars = function loadAvatars() {
$('.avatar[data-src]').each(function () {
$('.avatar[data-src]').each(function() {
var $avatar = $(this);
$avatar
@ -1795,7 +1797,7 @@ phpbb.getEditorTextArea = function(formName, textareaName) {
}
return doc.forms[formName].elements[textareaName];
}
};
phpbb.recaptcha = {
button: null,
@ -1826,7 +1828,7 @@ phpbb.recaptcha = {
if (phpbb.recaptcha.v3.length) {
grecaptcha.execute(
phpbb.recaptcha.v3.data('recaptcha-v3'),
{action: phpbb.recaptcha.v3.val()}
{ action: phpbb.recaptcha.v3.val() },
).then(function(token) {
// Place the token inside the form
phpbb.recaptcha.token.val(token);
@ -1860,7 +1862,7 @@ phpbb.recaptcha = {
phpbb.recaptcha.form.submit();
}
}
},
};
// reCAPTCHA v2 doesn't accept callback functions nested inside objects

View file

@ -1,4 +1,8 @@
/* 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 ]
@ -100,7 +104,7 @@ function bbfontstyle(bbopen, bbclose) {
// IE
else if (document.selection) {
var range = textarea.createTextRange();
range.move("character", new_pos);
range.move('character', new_pos);
range.select();
storeCaret(textarea);
}
@ -271,7 +275,7 @@ function formatAttributeValue(str) {
// Return as-is if it contains none of: space, ' " \ or ]
return str;
}
var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'",
var singleQuoted = '\'' + str.replace(/[\\']/g, '\\$&') + '\'',
doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"';
return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted;
@ -404,7 +408,7 @@ function getCaretPosition(txtarea) {
phpbb.showDragNDrop(textarea);
}
$('textarea').on('keydown', function (e) {
$('textarea').on('keydown', function(e) {
if (e.which === 13 && (e.metaKey || e.ctrlKey)) {
$(this).closest('form').find(':submit').click();
}

View file

@ -2,6 +2,9 @@
* Installer's AJAX frontend handler
*/
/* eslint no-prototype-builtins: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries
'use strict';
@ -359,10 +362,10 @@
} else {
$('#loading_indicator').css('display', 'none');
addMessage('error',
[{
[ {
title: installLang.title,
description: installLang.msg
}]
description: installLang.msg,
} ],
);
}
}
@ -487,7 +490,7 @@
function startPolling(xhReq) {
resetPolling();
transmissionOver = false;
pollTimer = setInterval(function () {
pollTimer = setInterval(function() {
pollContent(xhReq);
}, 250);
}
@ -609,7 +612,7 @@
setAdminTimezone($form);
}
$form.find(':submit').bind('click', function (event) {
$form.find(':submit').bind('click', function(event) {
event.preventDefault();
submitForm($form, $(this));
});

View file

@ -1,4 +1,7 @@
/* global phpbb, plupload, attachInline */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
/* eslint no-unused-vars: 0 */
plupload.addI18n(phpbb.plupload.i18n);
phpbb.plupload.ids = [];
@ -21,7 +24,7 @@ phpbb.plupload.initialize = function() {
// Only execute if Plupload initialized successfully.
phpbb.plupload.uploader.bind('Init', function() {
phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0];
let $attachRowTemplate = $('#attach-row-tpl');
const $attachRowTemplate = $('#attach-row-tpl');
$attachRowTemplate.removeClass('attach-row-tpl');
phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML;
@ -300,7 +303,7 @@ phpbb.plupload.deleteFile = function(row, attachId) {
$.ajax(phpbb.plupload.config.url, {
type: 'POST',
data: $.extend(fields, phpbb.plupload.getSerializedData()),
headers: phpbb.plupload.config.headers
headers: phpbb.plupload.config.headers,
})
.always(always)
.done(done);
@ -452,7 +455,7 @@ phpbb.plupload.fileError = function(file, error) {
.addClass('file-error')
.attr({
'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) {
if (file.size !== 'undefined') {
$(types).each(function(i, type) {
let extensions = [],
const extensions = [],
extsArray = type.extensions.split(',');
$(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 (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', {
code: plupload.FILE_SIZE_ERROR,
message: plupload.translate('File size error.'),
file: file
file: file,
});
callback(false);
@ -587,9 +590,9 @@ phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) {
up.trigger('FileUploaded', file, {
response: JSON.stringify({
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, {
response: JSON.stringify({
error: {
message: json.error.message
}
})
message: json.error.message,
},
}),
});
}
});
@ -692,7 +695,7 @@ phpbb.plupload.uploader.bind('FileUploaded', function(up, file, response) {
row.attr('data-attach-id', file.attachment_data.attach_id);
row.find('.file-inline-bbcode').show();
row.find('.file-status').addClass('file-uploaded');
phpbb.plupload.update(json.data, 'addition', 0, [json.download_url]);
phpbb.plupload.update(json.data, 'addition', 0, [ json.download_url ]);
}
});

View file

@ -33,11 +33,10 @@
"ext-sodium": "*",
"bantu/ini-get-wrapper": "~1.0",
"carlos-mg89/oauth": "^0.8.15",
"chita/topological_sort": "^3.0",
"composer/composer": "^2.0",
"composer/installers": "^1.9",
"composer/package-versions-deprecated": "^1.11",
"doctrine/dbal": "~3.3.6",
"doctrine/dbal": "^3.9",
"google/recaptcha": "~1.1",
"guzzlehttp/guzzle": " ^7.0",
"marc1706/fast-image-size": "^1.1",

81
phpBB/composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5ed4369e5ba29297443f428dd3001fae",
"content-hash": "39f3a7c03ba85a8c7892e5c076372eb0",
"packages": [
{
"name": "bantu/ini-get-wrapper",
@ -171,49 +171,6 @@
},
"time": "2025-02-08T12:14:07+00:00"
},
{
"name": "chita/topological_sort",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/CHItA/TopologicalSort.git",
"reference": "9e0401c712d0c7cf012f264cc105669844d2479e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CHItA/TopologicalSort/zipball/9e0401c712d0c7cf012f264cc105669844d2479e",
"reference": "9e0401c712d0c7cf012f264cc105669844d2479e",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"CHItA\\TopologicalSort\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Máté Bartus",
"email": "mate.bartus@gmail.com"
}
],
"description": "Topological sort function",
"support": {
"issues": "https://github.com/CHItA/TopologicalSort/issues",
"source": "https://github.com/CHItA/TopologicalSort/tree/v3.0.1"
},
"time": "2021-01-04T21:31:59+00:00"
},
{
"name": "composer/ca-bundle",
"version": "1.5.6",
@ -1171,38 +1128,38 @@
},
{
"name": "doctrine/dbal",
"version": "3.3.8",
"version": "3.9.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "f873a820227bc352d023791775a01f078a30dfe1"
"reference": "ec16c82f20be1a7224e65ac67144a29199f87959"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/f873a820227bc352d023791775a01f078a30dfe1",
"reference": "f873a820227bc352d023791775a01f078a30dfe1",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/ec16c82f20be1a7224e65ac67144a29199f87959",
"reference": "ec16c82f20be1a7224e65ac67144a29199f87959",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2",
"doctrine/cache": "^1.11|^2.0",
"doctrine/deprecations": "^0.5.3|^1",
"doctrine/event-manager": "^1.0",
"php": "^7.3 || ^8.0",
"doctrine/event-manager": "^1|^2",
"php": "^7.4 || ^8.0",
"psr/cache": "^1|^2|^3",
"psr/log": "^1|^2|^3"
},
"require-dev": {
"doctrine/coding-standard": "9.0.0",
"jetbrains/phpstorm-stubs": "2022.1",
"phpstan/phpstan": "1.8.2",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "9.5.21",
"psalm/plugin-phpunit": "0.17.0",
"squizlabs/php_codesniffer": "3.7.1",
"symfony/cache": "^5.2|^6.0",
"symfony/console": "^2.7|^3.0|^4.0|^5.0|^6.0",
"vimeo/psalm": "4.24.0"
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
"phpstan/phpstan": "2.1.1",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "9.6.22",
"slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.10.2",
"symfony/cache": "^5.4|^6.0|^7.0",
"symfony/console": "^4.4|^5.4|^6.0|^7.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
@ -1262,7 +1219,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.3.8"
"source": "https://github.com/doctrine/dbal/tree/3.9.4"
},
"funding": [
{
@ -1278,7 +1235,7 @@
"type": "tidelift"
}
],
"time": "2022-08-05T15:35:35+00:00"
"time": "2025-01-16T08:28:55+00:00"
},
{
"name": "doctrine/deprecations",

View file

@ -58,6 +58,7 @@ $db_doctrine = $ref->newInstanceWithoutConstructor();
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($db_doctrine, true);
$db_tools->set_table_prefix($table_prefix);
$tables_data = \Symfony\Component\Yaml\Yaml::parseFile($phpbb_root_path . '/config/default/container/tables.yml');
$tables = [];

View file

@ -2821,6 +2821,13 @@ ucp_pm_viewmessage_custom_fields_before
* Purpose: Add data before the custom fields on the user profile when viewing
a private message
ucp_pm_viewmessage_message_content_before
===
* Locations:
+ styles/prosilver/template/ucp_pm_viewmessage.html
* Since: 3.3.16-RC1
* Purpose: Add content before the private message text
ucp_pm_viewmessage_options_before
===
* Locations:

View file

@ -276,6 +276,11 @@ class acp_extensions
{
$this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user));
}
catch (\Exception $e)
{
$this->template->assign_var('MIGRATOR_ERROR', $e->getMessage());
$this->template->assign_var('MIGRATOR_ERROR_STACK_TRACE', phpbb_filter_root_path($e->getTraceAsString()));
}
$this->tpl_name = 'acp_ext_enable';
@ -363,6 +368,11 @@ class acp_extensions
{
$this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user));
}
catch (\Exception $e)
{
$this->template->assign_var('MIGRATOR_ERROR', $e->getMessage());
$this->template->assign_var('MIGRATOR_ERROR_STACK_TRACE', phpbb_filter_root_path($e->getTraceAsString()));
}
$this->tpl_name = 'acp_ext_delete_data';

View file

@ -2716,7 +2716,7 @@ function get_backtrace()
// Only show function arguments for include etc.
// Other parameters may contain sensible information
$argument = '';
if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once')))
if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once', 'try_apply')))
{
$argument = htmlspecialchars(phpbb_filter_root_path($trace['args'][0]), ENT_COMPAT);
}

View file

@ -107,7 +107,7 @@ function installer_msg_handler($errno, $msg_text, $errfile, $errline): bool
{
/** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
$iohandler = $phpbb_installer_container->get('installer.helper.iohandler');
$iohandler->add_error_message($msg);
$iohandler->add_error_message($msg, get_backtrace());
$iohandler->send_response(true);
exit();
}

View file

@ -70,11 +70,11 @@ $lang = array_merge($lang, array(
<p>phpBB supports the following databases:</p>
<ul>
<li>MySQL 4.1.3 or above (MySQLi required)</li>
<li>PostgreSQL 8.3+</li>
<li>SQLite 3.6.15+</li>
<li>MS SQL Server 2000 or above (directly or via ODBC)</li>
<li>MS SQL Server 2005 or above (native)</li>
<li>MySQL 5.6 or above</li>
<li>MariaDB 10.2.7 or above</li>
<li>PostgreSQL 9.4 or above</li>
<li>SQLite 3.8.3 or above</li>
<li>MS SQL Server 2012 or above (via ODBC or the native adapter)</li>
<li>Oracle</li>
</ul>
@ -184,9 +184,9 @@ $lang = array_merge($lang, array(
'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
// Database options
'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension',
'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server via ODBC',
'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server [ Native ]',
'DB_OPTION_MYSQLI' => 'MySQL',
'DB_OPTION_ORACLE' => 'Oracle',
'DB_OPTION_POSTGRES' => 'PostgreSQL',
'DB_OPTION_SQLITE3' => 'SQLite 3',
@ -202,10 +202,13 @@ $lang = array_merge($lang, array(
'INST_ERR_DB_NO_WRITABLE' => 'Both the database and the directory containing it must be writable.',
'INST_ERR_DB_NO_ERROR' => 'No error message given.',
'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension” option you have selected. Please try the “MySQL” option instead.',
'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
'INST_ERR_DB_NO_MARIADB' => 'The version of MariaDB installed on this machine is too old, it must be upgraded to at least 10.2.7.',
'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is too old, it must be upgraded to at least 5.6.',
'INST_ERR_DB_NO_MSSQL' => 'The version of Microsoft SQL Server installed on this machine is too old, it must be upgraded to at least SQL Server 2012 (11.0.2100.60)',
'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.8.3.',
'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed is too old, it must be upgraded to at least 12.1.0.2.',
'INST_ERR_DB_NO_POSTGRES' => 'The version of the PostgreSQL you have installed is too old, it must be upgraded to at least 9.4.',
'INST_ERR_DB_NO_POSTGRES_UTF8' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
'INST_SCHEMA_FILE_NOT_WRITABLE' => 'The schema file is not writable',
//

View file

@ -1681,6 +1681,18 @@ switch ($mode)
$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);
if (isset($cp_row['blockrow']) && count($cp_row['blockrow']))

View file

@ -79,7 +79,7 @@ class connection_parameter_factory
string|null $name = null,
string|null $port = null) : array
{
if ($params['driver'] === 'pdo_sqlite')
if (in_array($params['driver'], ['pdo_sqlite', 'sqlite3']))
{
return self::enrich_parameters(
self::build_sqlite_parameters($params, $host, $user, $password)

View file

@ -13,6 +13,7 @@
namespace phpbb\db\doctrine;
use InvalidArgumentException;
use phpbb\db\tools\doctrine as doctrine_dbtools;
class table_helper
{
@ -123,6 +124,54 @@ class table_helper
}
}
/**
* Maps table names to their short names for the purpose of prefixing tables' index names.
*
* @param array $table_names Table names with prefix to add to the map.
* @param string $table_prefix Tables prefix.
*
* @return array<string, string> Pairs of table names and their short name representations.
* @psalm-return array{string, string}
*/
public static function map_short_table_names(array $table_names = [], string $table_prefix = ''): array
{
$short_table_names_map = [];
foreach ($table_names as $table_name)
{
$short_table_names_map[$table_name] = self::generate_shortname(doctrine_dbtools::remove_prefix($table_name, $table_prefix));
}
return $short_table_names_map;
}
/**
* Generates short table names for the purpose of prefixing tables' index names.
*
* @param string $table_name Table name without prefix to generate its short name.
*
* @return string Short table name.
*/
public static function generate_shortname(string $table_name = ''): string
{
// Only shorten actually long names
if (strlen($table_name) > 4)
{
// Remove vowels
$table_name = preg_replace('/([^aeiou_])([aeiou]+)/i', '$1', $table_name);
// Remove underscores
$table_name = str_replace('_', '', $table_name);
// Remove repeated consonants and their combinations (like 'ss', 'flfl' and similar)
$table_name = preg_replace('/(.+)\\1+/i', '$1', $table_name);
// Restrict short name length to 10 chars
$table_name = substr($table_name, 0, 10);
}
return $table_name;
}
/**
* Private constructor. Call methods of table_helper statically.
*/

View file

@ -15,7 +15,7 @@ namespace phpbb\db\driver;
/**
* SQLite3 Database Abstraction Layer
* Minimum Requirement: 3.6.15+
* Minimum Requirement: 3.8.3+
*/
class sqlite3 extends \phpbb\db\driver\driver
{

View file

@ -0,0 +1,146 @@
<?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\db\migration\data\v400;
use phpbb\db\migration\migration;
use phpbb\db\doctrine\table_helper;
use phpbb\db\tools\doctrine as doctrine_dbtools;
class rename_duplicated_index_names extends migration
{
/**
* @var array
*/
protected static $table_keys;
/**
* @var array
*/
protected static $rename_index;
public static function depends_on()
{
return [
'\phpbb\db\migration\data\v400\storage_track_index',
];
}
public function update_schema()
{
if (!isset(self::$rename_index))
{
if (!isset(self::$table_keys))
{
$this->get_tables_index_names();
}
$short_table_names = table_helper::map_short_table_names(array_keys(self::$table_keys), $this->table_prefix);
foreach (self::$table_keys as $table_name => $key_names)
{
$prefixless_table_name = doctrine_dbtools::remove_prefix($table_name, $this->table_prefix);
foreach ($key_names as $key_name)
{
// If 'old' key name is already new format, do not rename it
if (str_starts_with($key_name, $short_table_names[$table_name]))
{
continue;
}
// If 'old' key name is prefixed by its table name with and/or without table name common prefix
// (f.e. 'phpbb_log_log_time'), remove it to prefix with the relevant table's short name
$cleaned_key_name = $key_name;
foreach ([$table_name, $prefixless_table_name] as $prefix)
{
$cleaned_key_name = doctrine_dbtools::remove_prefix($cleaned_key_name, $prefix);
}
$key_name_new = $short_table_names[$table_name] . '_' . $cleaned_key_name;
self::$rename_index[$table_name][$key_name] = $key_name_new;
}
}
}
return [
'rename_index' => self::$rename_index,
];
}
public function revert_schema()
{
$schema = $this->update_schema();
array_walk($schema['rename_index'], function (&$index_data, $table_name) {
$index_data = array_flip($index_data);
});
return $schema;
}
protected function get_schema()
{
$self_classname = '\\' . str_replace('/', '\\', self::class);
$finder_factory = new \phpbb\finder\factory(null, false, $this->phpbb_root_path, $this->php_ext);
$finder = $finder_factory->get();
$migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes();
$self_class_index = array_search($self_classname, $migrator_classes);
unset($migrator_classes[$self_class_index]);
$schema_generator = new \phpbb\db\migration\schema_generator(
$migrator_classes,
$this->config,
$this->db,
$this->db_tools,
$this->phpbb_root_path,
$this->php_ext,
$this->table_prefix,
$this->tables
);
return $schema_generator->get_schema();
}
public function get_tables_index_names()
{
$schema_manager = $this->db_tools->get_connection()->createSchemaManager();
$table_names = $schema_manager->listTableNames();
if (!empty($table_names))
{
foreach ($table_names as $table_name)
{
$indices = $schema_manager->listTableIndexes($table_name);
$indices = array_keys(array_filter($indices,
function (\Doctrine\DBAL\Schema\Index $index)
{
return !$index->isPrimary();
})
);
if (!empty($indices))
{
self::$table_keys[$table_name] = $indices;
}
}
}
else
{
foreach ($this->get_schema() as $table_name => $table_data)
{
if (isset($table_data['KEYS']))
{
self::$table_keys[$table_name] = array_keys($table_data['KEYS']);
}
}
}
}
}

View file

@ -42,6 +42,7 @@ class helper
'add_primary_keys' => 2, // perform_schema_changes only uses one level, but second is in the function
'add_unique_index' => 2,
'add_index' => 2,
'rename_index' => 1,
);
foreach ($nested_level as $change_type => $data_depth)

View file

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

View file

@ -14,21 +14,17 @@
namespace phpbb\db\migration;
use Closure;
use LogicException;
use phpbb\config\config;
use phpbb\db\driver\driver_interface;
use phpbb\db\migrator;
use phpbb\db\tools\tools_interface;
use UnexpectedValueException;
use CHItA\TopologicalSort\TopologicalSort;
/**
* The schema generator generates the schema based on the existing migrations
*/
class schema_generator
{
use TopologicalSort;
/** @var config */
protected $config;
@ -103,24 +99,56 @@ class schema_generator
return $this->tables;
}
$migrations = $this->class_names;
$filter = function($class_name) {
return !migrator::is_migration($class_name);
};
$edges = function($class_name) {
return $class_name::depends_on();
};
$apply_for_each = function($class_name) {
$this->apply_migration_to_schema($class_name);
};
try
$dependency_counts = [];
$dependencies = [];
$applicable_migrations = [];
$migration_count = 0;
foreach ($this->class_names as $class_name)
{
$this->topologicalSort($migrations, $edges, true, $apply_for_each, $filter);
if (!migrator::is_migration($class_name))
{
continue;
}
$migration_count++;
$migration_dependencies = $class_name::depends_on();
if (empty($migration_dependencies))
{
$applicable_migrations[] = $class_name;
continue;
}
$dependency_counts[$class_name] = count($migration_dependencies);
foreach ($migration_dependencies as $migration_dependency)
{
$dependencies[$migration_dependency][] = $class_name;
}
}
catch (LogicException $e)
$applied_migrations = 0;
while (!empty($applicable_migrations))
{
$migration = array_pop($applicable_migrations);
$this->apply_migration_to_schema($migration);
++$applied_migrations;
if (!array_key_exists($migration, $dependencies))
{
continue;
}
$dependents = $dependencies[$migration];
foreach ($dependents as $dependent)
{
$dependency_counts[$dependent]--;
if ($dependency_counts[$dependent] === 0)
{
$applicable_migrations[] = $dependent;
}
}
}
if ($migration_count !== $applied_migrations)
{
throw new UnexpectedValueException(
"Migrations either have circular dependencies or unsatisfiable dependencies."
@ -159,6 +187,7 @@ class schema_generator
'add_index' => 'KEYS',
'add_unique_index' => 'KEYS',
'drop_keys' => 'KEYS',
'rename_index' => 'KEYS',
];
$schema_changes = $migration->update_schema();
@ -178,6 +207,7 @@ class schema_generator
{
case 'add':
case 'change':
case 'rename':
$action = function(&$value, $changes, $value_transform = null) {
self::set_all($value, $changes, $value_transform);
};
@ -319,7 +349,7 @@ class schema_generator
*/
private static function get_value_transform(string $change_type, string $schema_type) : Closure|null
{
if ($change_type !== 'add')
if (!in_array($change_type, ['add', 'rename']))
{
return null;
}
@ -327,6 +357,23 @@ class schema_generator
switch ($schema_type)
{
case 'index':
if ($change_type == 'rename')
{
return function(&$value, $key, $change) {
if (isset($value[$key]))
{
$data_backup = $value[$key];
unset($value[$key]);
$value[$change] = $data_backup;
unset($data_backup);
}
else
{
return null;
}
};
}
return function(&$value, $key, $change) {
$value[$key] = ['INDEX', $change];
};

View file

@ -49,6 +49,11 @@ class doctrine implements tools_interface
*/
private $return_statements;
/**
* @var string
*/
private $table_prefix;
/**
* Database tools constructors.
*
@ -61,6 +66,14 @@ class doctrine implements tools_interface
$this->connection = $connection;
}
/**
* {@inheritDoc}
*/
public function get_connection(): Connection
{
return $this->connection;
}
/**
* @return AbstractSchemaManager
*
@ -86,6 +99,14 @@ class doctrine implements tools_interface
return $this->get_schema_manager()->createSchema();
}
/**
* {@inheritDoc}
*/
public function set_table_prefix($table_prefix): void
{
$this->table_prefix = $table_prefix;
}
/**
* {@inheritDoc}
*/
@ -289,6 +310,12 @@ class doctrine implements tools_interface
if (count($primary_key_indexes))
{
// For PostgreSQL, drop primary index first to avoid "Dependent objects still exist" error
if (stripos($this->get_schema_manager()->getDatabasePlatform()->getname(), 'postgresql') !== false)
{
$this->get_schema_manager()->dropIndex('"primary"', $table_name);
}
$ret = $this->alter_schema(
function (Schema $schema) use ($table_name, $column_name): void
{
@ -324,6 +351,19 @@ class doctrine implements tools_interface
);
}
/**
* {@inheritDoc}
*/
public function sql_rename_index(string $table_name, string $index_name_old, string $index_name_new)
{
return $this->alter_schema(
function (Schema $schema) use ($table_name, $index_name_old, $index_name_new): void
{
$this->schema_rename_index($schema, $table_name, $index_name_old, $index_name_new);
}
);
}
/**
* {@inheritDoc}
*/
@ -378,6 +418,59 @@ class doctrine implements tools_interface
}
}
/**
* {@inheritDoc}
*/
public static function add_prefix(string $name, string $prefix): string
{
return str_ends_with($prefix, '_') ? $prefix . $name : $prefix . '_' . $name;
}
/**
* {@inheritDoc}
*/
public static function remove_prefix(string $name, string $prefix = ''): string
{
$prefix = str_ends_with($prefix, '_') ? $prefix : $prefix . '_';
return $prefix && str_starts_with($name, $prefix) ? substr($name, strlen($prefix)) : $name;
}
/**
* Returns an array of the table index names and relevant data in format
* [
* [$index_name] = [
* 'columns' => (array) $index_columns,
* 'flags' => (array) $index_flags,
* 'options' => (array) $index_options,
* 'is_primary'=> (bool) $isPrimary,
* 'is_unique' => (bool) $isUnique,
* 'is_simple' => (bool) $isSimple,
* ]
*
* @param string $table_name
*
* @return array
*/
public function sql_get_table_index_data(string $table_name): array
{
$schema = $this->get_schema();
$table = $schema->getTable($table_name);
$indexes = [];
foreach ($table->getIndexes() as $index)
{
$indexes[$index->getName()] = [
'columns' => array_map('strtolower', $index->getUnquotedColumns()),
'flags' => $index->getFlags(),
'options' => $index->getOptions(),
'is_primary'=> $index->isPrimary(),
'is_unique' => $index->isUnique(),
'is_simple' => $index->isSimpleIndex(),
];
}
return $indexes;
}
/**
* Returns an array of indices for either unique and primary keys, or simple indices.
*
@ -452,34 +545,26 @@ class doctrine implements tools_interface
*/
protected function alter_schema(callable $callback)
{
try
$current_schema = $this->get_schema();
$new_schema = clone $current_schema;
call_user_func($callback, $new_schema);
$comparator = new comparator();
$schemaDiff = $comparator->compareSchemas($current_schema, $new_schema);
$queries = $schemaDiff->toSql($this->get_schema_manager()->getDatabasePlatform());
if ($this->return_statements)
{
$current_schema = $this->get_schema();
$new_schema = clone $current_schema;
call_user_func($callback, $new_schema);
$comparator = new comparator();
$schemaDiff = $comparator->compareSchemas($current_schema, $new_schema);
$queries = $schemaDiff->toSql($this->get_schema_manager()->getDatabasePlatform());
if ($this->return_statements)
{
return $queries;
}
foreach ($queries as $query)
{
// executeQuery() must be used here because $query might return a result set, for instance REPAIR does
$this->connection->executeQuery($query);
}
return true;
return $queries;
}
catch (Exception $e)
foreach ($queries as $query)
{
// @todo: check if it makes sense to properly handle the exception
return false;
// executeQuery() must be used here because $query might return a result set, for instance REPAIR does
$this->connection->executeQuery($query);
}
return true;
}
/**
@ -547,6 +632,11 @@ class doctrine implements tools_interface
'use_key' => true,
'per_table' => true,
],
'rename_index' => [
'method' => 'schema_rename_index',
'use_key' => true,
'per_table' => true,
],
];
foreach ($mapping as $action => $params)
@ -604,6 +694,7 @@ class doctrine implements tools_interface
}
$table = $schema->createTable($table_name);
$short_table_name = table_helper::generate_shortname(self::remove_prefix($table_name, $this->table_prefix));
$dbms_name = $this->get_schema_manager()->getDatabasePlatform()->getName();
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
@ -629,25 +720,18 @@ class doctrine implements tools_interface
foreach ($table_data['KEYS'] as $key_name => $key_data)
{
$columns = (is_array($key_data[1])) ? $key_data[1] : [$key_data[1]];
$key_name = !str_starts_with($key_name, $short_table_name) ? self::add_prefix($key_name, $short_table_name) : $key_name;
// Supports key columns defined with there length
$columns = array_map(function (string $column)
{
if (strpos($column, ':') !== false)
{
$parts = explode(':', $column, 2);
return $parts[0];
}
return $column;
}, $columns);
$options = [];
$this->schema_get_index_key_data($columns, $options);
if ($key_data[0] === 'UNIQUE')
{
$table->addUniqueIndex($columns, $key_name);
$table->addUniqueIndex($columns, $key_name, $options);
}
else
{
$table->addIndex($columns, $key_name);
$table->addIndex($columns, $key_name, [], $options);
}
}
}
@ -661,6 +745,8 @@ class doctrine implements tools_interface
}
/**
* Removes a table
*
* @param Schema $schema
* @param string $table_name
* @param bool $safe_check
@ -678,6 +764,8 @@ class doctrine implements tools_interface
}
/**
* Adds column to a table
*
* @param Schema $schema
* @param string $table_name
* @param string $column_name
@ -708,6 +796,8 @@ class doctrine implements tools_interface
}
/**
* Alters column properties
*
* @param Schema $schema
* @param string $table_name
* @param string $column_name
@ -738,6 +828,8 @@ class doctrine implements tools_interface
}
/**
* Alters column properties or adds a column
*
* @param Schema $schema
* @param string $table_name
* @param string $column_name
@ -760,6 +852,8 @@ class doctrine implements tools_interface
}
/**
* Removes a column in a table
*
* @param Schema $schema
* @param string $table_name
* @param string $column_name
@ -812,6 +906,8 @@ class doctrine implements tools_interface
}
/**
* Creates non-unique index for a table
*
* @param Schema $schema
* @param string $table_name
* @param string $index_name
@ -824,16 +920,53 @@ class doctrine implements tools_interface
{
$columns = (is_array($column)) ? $column : [$column];
$table = $schema->getTable($table_name);
$short_table_name = table_helper::generate_shortname(self::remove_prefix($table_name, $this->table_prefix));
$index_name = !str_starts_with($index_name, $short_table_name) ? self::add_prefix($index_name, $short_table_name) : $index_name;
if ($safe_check && $table->hasIndex($index_name))
{
return;
}
$table->addIndex($columns, $index_name);
$options = [];
$this->schema_get_index_key_data($columns, $options);
$table->addIndex($columns, $index_name, [], $options);
}
/**
* Renames table index
*
* @param Schema $schema
* @param string $table_name
* @param string $index_name_old
* @param string $index_name_new
* @param bool $safe_check
*
* @throws SchemaException
*/
protected function schema_rename_index(Schema $schema, string $table_name, string $index_name_old, string $index_name_new, bool $safe_check = false): void
{
$table = $schema->getTable($table_name);
$short_table_name = table_helper::generate_shortname(self::remove_prefix($table_name, $this->table_prefix));
if (!$table->hasIndex($index_name_old))
{
$index_name_old = !str_starts_with($index_name_old, $short_table_name) ? self::add_prefix($index_name_old, $short_table_name) : self::remove_prefix($index_name_old, $short_table_name);
}
$index_name_new = !str_starts_with($index_name_new, $short_table_name) ? self::add_prefix($index_name_new, $short_table_name) : $index_name_new;
if ($safe_check && !$table->hasIndex($index_name_old))
{
return;
}
$table->renameIndex($index_name_old, $index_name_new);
}
/**
* Creates unique (non-primary) index for a table
*
* @param Schema $schema
* @param string $table_name
* @param string $index_name
@ -846,16 +979,23 @@ class doctrine implements tools_interface
{
$columns = (is_array($column)) ? $column : [$column];
$table = $schema->getTable($table_name);
$short_table_name = table_helper::generate_shortname(self::remove_prefix($table_name, $this->table_prefix));
$index_name = !str_starts_with($index_name, $short_table_name) ? self::add_prefix($index_name, $short_table_name) : $index_name;
if ($safe_check && $table->hasIndex($index_name))
{
return;
}
$table->addUniqueIndex($columns, $index_name);
$options = [];
$this->schema_get_index_key_data($columns, $options);
$table->addUniqueIndex($columns, $index_name, $options);
}
/**
* Removes table index
*
* @param Schema $schema
* @param string $table_name
* @param string $index_name
@ -866,6 +1006,12 @@ class doctrine implements tools_interface
protected function schema_index_drop(Schema $schema, string $table_name, string $index_name, bool $safe_check = false): void
{
$table = $schema->getTable($table_name);
$short_table_name = table_helper::generate_shortname(self::remove_prefix($table_name, $this->table_prefix));
if (!$table->hasIndex($index_name))
{
$index_name = !str_starts_with($index_name, $short_table_name) ? self::add_prefix($index_name, $short_table_name) : self::remove_prefix($index_name, $short_table_name);
}
if ($safe_check && !$table->hasIndex($index_name))
{
@ -876,6 +1022,8 @@ class doctrine implements tools_interface
}
/**
* Creates primary key for a table
*
* @param $column
* @param Schema $schema
* @param string $table_name
@ -891,6 +1039,30 @@ class doctrine implements tools_interface
$table->setPrimaryKey($columns);
}
/**
* Checks if index data contains key length
* and put it into $options['lengths'] array.
* Handles key length in formats of 'keyname:123' or 'keyname(123)'
*
* @param array $columns
* @param array $options
*/
protected function schema_get_index_key_data(array &$columns, array &$options): void
{
if (!empty($columns))
{
$columns = array_map(function (string $column) use (&$options)
{
if (preg_match('/^([a-zA-Z0-9_]+)(?:(?:\:|\()([0-9]{1,3})\)?)?$/', $column, $parts))
{
$options['lengths'][] = $parts[2] ?? null;
return $parts[1];
}
return $column;
}, $columns);
}
}
/**
* Recreate an index of a table
*

View file

@ -165,6 +165,17 @@ interface tools_interface
*/
public function sql_create_index(string $table_name, string $index_name, $column);
/**
* Rename index
*
* @param string $table_name Table to modify
* @param string $index_name_old Name of the index to rename
* @param string $index_name_new New name of the index being renamed
*
* @return bool|string[] True if the statements have been executed
*/
public function sql_rename_index(string $table_name, string $index_name_old, string $index_name_new);
/**
* Drop Index
*
@ -215,4 +226,41 @@ interface tools_interface
* @return void
*/
public function sql_truncate_table(string $table_name): void;
/**
* Gets current Doctrine DBAL connection
*
* @return \Doctrine\DBAL\Connection
*/
public function get_connection(): \Doctrine\DBAL\Connection;
/**
* Adds prefix to a string if needed
*
* @param string $name Table name with tables prefix
* @param string $prefix Prefix to add
*
* @return string Prefixed name
*/
public static function add_prefix(string $name, string $prefix): string;
/**
* Removes prefix from string if exists. If prefix is empty,
* the first part of the string ending with underscore will be removed.
*
* @param string $name String to remove the prefix from
* @param string $prefix Prefix to remove
*
* @return string Prefixless string
*/
public static function remove_prefix(string $name, string $prefix = ''): string;
/**
* Sets table prefix
*
* @param string $table_prefix String to test vs prefix
*
* @return void
*/
public function set_table_prefix(string $table_prefix): void;
}

View file

@ -339,6 +339,14 @@ class helper
protected function render_language_select($selected_language = null)
{
$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)
{
$this->template->assign_block_vars('language_select_item', array(

View file

@ -39,7 +39,7 @@ class database
// Note: php 5.5 alpha 2 deprecated mysql.
// Keep mysqli before mysql in this list.
'mysqli' => array(
'LABEL' => 'MySQL with MySQLi Extension',
'LABEL' => 'MySQL',
'SCHEMA' => 'mysql_41',
'MODULE' => 'mysqli',
'DOCTRINE' => ['pdo_mysql'],
@ -59,7 +59,7 @@ class database
'2.0.x' => true,
),
'mssqlnative' => array(
'LABEL' => 'MS SQL Server 2005+ [ Native ]',
'LABEL' => 'MS SQL Server [ Native ]',
'SCHEMA' => 'mssql',
'MODULE' => 'sqlsrv',
'DOCTRINE' => ['pdo_sqlsrv'],
@ -78,7 +78,7 @@ class database
'2.0.x' => false,
),
'postgres' => array(
'LABEL' => 'PostgreSQL 8.3+',
'LABEL' => 'PostgreSQL',
'SCHEMA' => 'postgres',
'MODULE' => 'pgsql',
'DOCTRINE' => ['pdo_pgsql'],
@ -393,6 +393,7 @@ class database
$doctrine_db = connection_factory::get_connection_from_params($dbms, $dbhost, $dbuser, $dbpass, $dbname, $dbport);
$db_tools_factory = new \phpbb\db\tools\factory();
$db_tools = $db_tools_factory->get($doctrine_db);
$db_tools->set_table_prefix($table_prefix);
$tables = $db_tools->sql_list_tables();
$tables = array_map('strtolower', $tables);
$table_intersect = array_intersect($tables, $table_ary);
@ -405,10 +406,29 @@ class database
}
// Check if database version is supported
/** @psalm-suppress UndefinedInterfaceMethod */
$db_server_version = $doctrine_db->getWrappedConnection()->getServerVersion();
switch ($dbms)
{
case 'mysqli':
if (stripos($db->sql_server_info(), 'mariadb') !== false && version_compare($db_server_version, '10.2.7', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_MARIADB',
);
}
else
{
if (version_compare($db_server_version, '5.6', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_MYSQLI',
);
}
}
break;
case 'sqlite3':
if (version_compare($db->sql_server_info(true), '3.6.15', '<'))
if (version_compare($db_server_version, '3.8.3', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_SQLITE3',
@ -416,20 +436,7 @@ class database
}
break;
case 'oracle':
$sql = "SELECT *
FROM NLS_DATABASE_PARAMETERS
WHERE PARAMETER = 'NLS_RDBMS_VERSION'
OR PARAMETER = 'NLS_CHARACTERSET'";
$result = $db->sql_query($sql);
$stats = [];
while ($row = $db->sql_fetchrow($result))
{
$stats[$row['parameter']] = $row['value'];
}
$db->sql_freeresult($result);
if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
if (version_compare($db_server_version, '12.1.0.2', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_ORACLE',
@ -437,17 +444,35 @@ class database
}
break;
case 'postgres':
$sql = "SHOW server_encoding;";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
if (version_compare($db_server_version, '9.4', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_POSTGRES',
);
}
else
{
$sql = "SHOW server_encoding;";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_POSTGRES_UTF8',
);
}
}
break;
case 'mssqlnative':
case 'mssql_odbc':
if (version_compare($db_server_version, '11.0.2100.60', '<'))
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_MSSQL',
);
}
break;
}
}

View file

@ -280,7 +280,9 @@ class installer
}
catch (\Exception $e)
{
$this->iohandler->add_error_message($e->getMessage());
$stack_trace = phpbb_filter_root_path(str_replace("\n", '<br>', $e->getTraceAsString()));
$message = $e->getMessage();
$this->iohandler->add_error_message($message, $stack_trace);
$this->iohandler->send_response(true);
$fail_cleanup = true;
}

View file

@ -98,6 +98,7 @@ class add_tables extends task_base
$this->schema_file_path = $phpbb_root_path . 'store/schema.json';
$this->table_prefix = $this->config->get('table_prefix');
$this->change_prefix = $this->config->get('change_table_prefix', true);
$this->db_tools->set_table_prefix($this->table_prefix);
parent::__construct(true);
}

View file

@ -145,6 +145,7 @@ class create_schema_file extends \phpbb\install\task_base
$migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes();
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($this->db_doctrine, true);
$db_tools->set_table_prefix($table_prefix);
$tables_data = \Symfony\Component\Yaml\Yaml::parseFile($this->phpbb_root_path . '/config/default/container/tables.yml');
$tables = [];
foreach ($tables_data['parameters'] as $parameter => $table)

View file

@ -145,31 +145,29 @@ class check_filesystem extends \phpbb\install\task_base
// Try to create file if it does not exists
if (!file_exists($path))
{
$fp = @fopen($path, 'w');
@fclose($fp);
try
if (!is_resource($fp = @fopen($path, 'w')))
{
$this->filesystem->phpbb_chmod($path,
\phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE
);
$exists = true;
$exists = $writable = false;
}
catch (\phpbb\filesystem\exception\filesystem_exception $e)
else
{
// Do nothing
@fclose($fp);
try
{
$this->filesystem->phpbb_chmod($path,
\phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE
);
$exists = true;
}
catch (\phpbb\filesystem\exception\filesystem_exception $e)
{
$writable = false;
}
}
}
if (file_exists($path))
else if (!$this->filesystem->is_writable($path))
{
if (!$this->filesystem->is_writable($path))
{
$writable = false;
}
}
else
{
$exists = $writable = false;
$writable = false;
}
$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);
}
usort($available_languages, [$this, 'sort_by_local_name']);
return $available_languages;
}
@ -123,4 +125,16 @@ class language_file_helper
'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;
}
/**
* Gets the event dispatcher instance
*
* @return dispatcher_interface
*/
public function get_phpbb_dispatcher()
{
return $this->phpbb_dispatcher;
}
/**
* Get the namespace look up order
*

View file

@ -24,9 +24,13 @@ class event extends \Twig\Node\Node
/** @var \phpbb\template\twig\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->template_event_priority_array = $template_event_priority_array;
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');
$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)
{
$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 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)
$compiler
->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'))
@ -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
->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->setNamespaceLookUpOrder(\$previous_look_up_order);\n")
;
->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n");
}
if ($this->environment->isDebug())
{
$compiler
->outdent()
->write("}\n\n")
;
->write("}\n\n");
}
}
}

View file

@ -18,6 +18,9 @@ class event extends \Twig\TokenParser\AbstractTokenParser
/** @var \phpbb\template\twig\environment */
protected $environment;
/** @var array */
protected $template_event_priority_array;
/**
* Constructor
*
@ -26,6 +29,25 @@ class event extends \Twig\TokenParser\AbstractTokenParser
public function __construct(\phpbb\template\twig\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->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

@ -88,7 +88,10 @@ class twig extends \phpbb\template\base
foreach ($extensions as $extension)
{
$this->twig->addExtension($extension);
if (!$this->twig->hasExtension(get_class($extension)))
{
$this->twig->addExtension($extension);
}
}
// Add admin namespace

View file

@ -34,41 +34,48 @@ self.addEventListener('push', event => {
notificationVersion = parseInt(notificationData.version, 10);
pushToken = notificationData.token;
} catch {
self.registration.showNotification(event.data.text());
event.waitUntil(self.registration.showNotification(event.data.text()));
return;
}
const getNotificationUrl = '{{ U_WEBPUSH_GET_NOTIFICATION }}';
const assetsVersion = parseInt('{{ ASSETS_VERSION }}', 10);
event.waitUntil((async() => {
const getNotificationUrl = '{{ U_WEBPUSH_GET_NOTIFICATION }}';
const assetsVersion = parseInt('{{ ASSETS_VERSION }}', 10);
// Force update if versions differ
if (assetsVersion !== notificationVersion) {
self.registration.update();
}
// Force update if versions differ
if (assetsVersion !== notificationVersion) {
await self.registration.update();
}
const formData = new FormData();
formData.append('item_id', itemId.toString(10));
formData.append('type_id', typeId.toString(10));
formData.append('user_id', userId.toString(10));
formData.append('token', pushToken);
const formData = new FormData();
formData.append('item_id', itemId.toString(10));
formData.append('type_id', typeId.toString(10));
formData.append('user_id', userId.toString(10));
formData.append('token', pushToken);
fetch(getNotificationUrl, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
body: formData,
})
.then(response => response.json())
.then(response => {
const responseBody = response.title + '\n' + response.text;
try {
const response = await fetch(getNotificationUrl, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
body: formData,
});
const responseData = await response.json();
const responseBody = responseData.title + '\n' + responseData.text;
const options = {
body: responseBody,
data: response,
icon: response.avatar.src,
data: responseData,
icon: responseData.avatar.src,
};
self.registration.showNotification(response.heading, options);
});
await self.registration.showNotification(responseData.heading, options);
} catch (e) {
console.error('Push error:', e);
}
})());
});
/**

View file

@ -1,4 +1,6 @@
/* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries
@ -11,7 +13,7 @@ phpbb.addAjaxCallback('mark_forums_read', function(res) {
var iconsArray = {
forum_unread: 'forum_read',
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() {
@ -52,9 +54,9 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
global_unread: 'global_read',
announce_unread: 'announce_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 classMap = {};
var classNames = [];
@ -206,7 +208,7 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
var mostVotes = 0;
// Set min-height to prevent the page from jumping when the content changes
var updatePanelHeight = function (height) {
var updatePanelHeight = function(height) {
height = (typeof height === 'undefined') ? panel.find('.inner').outerHeight() : height;
panel.css('min-height', height);
};
@ -218,7 +220,7 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
}
if (!res.can_vote) {
poll.find('.polls, .poll_max_votes, .poll_vote, .poll_option_select').fadeOut(500, function () {
poll.find('.polls, .poll_max_votes, .poll_vote, .poll_option_select').fadeOut(500, function() {
poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show();
});
} else {
@ -260,7 +262,7 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
var barTimeLapse = (res.can_vote) ? 500 : 1500;
var newBarClass = (percent === 100) ? 'pollbar5' : 'pollbar' + (Math.floor(percent / 20) + 1);
setTimeout(function () {
setTimeout(function() {
bar.animate({ width: percentRel + '%' }, 500)
.removeClass('pollbar1 pollbar2 pollbar3 pollbar4 pollbar5')
.addClass(newBarClass)
@ -292,13 +294,13 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
resizePanel(500);
}, 1500);
var resizePanel = function (time) {
var resizePanel = function(time) {
var panelHeight = panel.height();
var innerHeight = panel.find('.inner').outerHeight();
if (panelHeight !== innerHeight) {
panel.css({ minHeight: '', height: panelHeight })
.animate({ height: innerHeight }, time, function () {
.animate({ height: innerHeight }, time, function() {
panel.css({ minHeight: innerHeight, height: '' });
});
}
@ -332,7 +334,7 @@ $('[data-ajax]').each(function() {
selector: this,
refresh: $this.attr('data-refresh') !== undefined,
filter: filter,
callback: fn
callback: fn,
});
}
});
@ -367,7 +369,7 @@ $('.display_post').click(function(e) {
$('.display_post_review').on('click', function(e) {
e.preventDefault();
let $displayPostLink = $(this);
const $displayPostLink = $(this);
$displayPostLink.closest('.post-ignore').removeClass('post-ignore');
$displayPostLink.hide();
});
@ -379,7 +381,7 @@ $('.display_post_review').on('click', function(e) {
* In any case the link will toggle the display status of the search panel and link text will be
* appropriately changed based on the status of the search panel.
*/
$('#member_search').click(function () {
$('#member_search').click(function() {
var $memberlistSearch = $('#memberlist_search');
$memberlistSearch.slideToggle('fast');
@ -399,7 +401,7 @@ const $scrollTopButton = $('.to-top-button');
if ($scrollTopButton.length) {
// Show or hide the button based on scroll position
$(window).scroll(function () {
$(window).scroll(function() {
if ($(this).scrollTop() > 300) {
$scrollTopButton.fadeIn(); // Fade in the button
} else {
@ -408,9 +410,9 @@ if ($scrollTopButton.length) {
});
// Scroll smoothly to the top when the button is clicked
$scrollTopButton.click(function (e) {
$scrollTopButton.click(function(e) {
e.preventDefault(); // Prevent the default anchor link behavior
$('html, body').animate({scrollTop: 0}, 500); // Smooth scroll to top
$('html, body').animate({ scrollTop: 0 }, 500); // Smooth scroll to top
});
}

View file

@ -1,4 +1,7 @@
/* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var:0 */
/**
* phpBB forum functions
@ -103,14 +106,14 @@ jQuery(function($) {
$('.sub-panels').each(function() {
var $childNodes = $('a[data-subpanel]', this),
panels = $childNodes.map(function () {
panels = $childNodes.map(function() {
return this.getAttribute('data-subpanel');
}),
showPanel = this.getAttribute('data-show-panel');
if (panels.length) {
activateSubPanel(showPanel, panels);
$childNodes.click(function () {
$childNodes.click(function() {
activateSubPanel(this.getAttribute('data-subpanel'), panels);
return false;
});
@ -232,7 +235,7 @@ function phpbbCheckKey(event) {
jQuery(function($) {
'use strict';
$('form input[type=text], form input[type=password]').on('keypress', function (e) {
$('form input[type=text], form input[type=password]').on('keypress', function(e) {
var defaultButton = $(this).parents('form').find('input[type=submit].default-submit-action');
if (!defaultButton || defaultButton.length <= 0) {
@ -369,7 +372,7 @@ function parseDocument($container) {
var $this = $(this),
$links = $this.find('.crumb'),
length = $links.length,
classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'],
classes = [ 'wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny' ],
classesLength = classes.length,
maxHeight = 0,
lastWidth = false,
@ -496,7 +499,7 @@ function parseDocument($container) {
// Find all headers, get contents
$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++;
});
@ -600,7 +603,7 @@ function parseDocument($container) {
if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column]));
cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
}
} else {
cell.addClass('empty');
@ -687,7 +690,7 @@ function parseDocument($container) {
var $tabLink = $item.find('a.responsive-tab-link');
phpbb.registerDropdown($tabLink, $item.find('.dropdown'), {
visibleClass: 'activetab'
visibleClass: 'activetab',
});
check(true);

View file

@ -149,6 +149,7 @@
<!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}"<!-- IF bcc_recipient.COLOUR --> style="color:{bcc_recipient.COLOUR};"<!-- ENDIF -->><strong>{bcc_recipient.NAME}</strong></a><!-- ENDIF -->&nbsp;<!-- END bcc_recipient --><!-- ENDIF -->
</p>
{% EVENT ucp_pm_viewmessage_message_content_before %}
<div class="content">{MESSAGE}</div>

131
tests/cron/wrapper_test.php Normal file
View file

@ -0,0 +1,131 @@
<?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.
*
*/
require_once __DIR__ . '/../template/template_test_case.php';
class phpbb_cron_wrapper_test extends phpbb_template_template_test_case
{
private $task;
private $routing_helper;
private $wrapper;
protected function setUp(): void
{
global $phpbb_root_path;
$this->setup_engine([], $phpbb_root_path . 'styles/all/template');
global $phpbb_filesystem;
$phpbb_filesystem = new \phpbb\filesystem\filesystem();
$this->task = $this->createMock(\phpbb\cron\task\task::class);
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
$this->wrapper = new \phpbb\cron\task\wrapper(
$this->task,
$this->routing_helper,
$this->template
);
}
public function test_generate_template_pagination()
{
$this->task = $this->createMock(\phpbb\cron\task\parametrized::class);
$this->task->expects($this->any())
->method('get_parameters')
->willReturn(['f' => '5']);
$this->task->expects($this->any())
->method('get_name')
->willReturn('test_task');
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
$this->routing_helper->expects($this->any())
->method('route')
->with('phpbb_cron_run', ['cron_type' => 'test_task', 'f' => '5'])
->willReturn('app.php/cron/foo?f=5');
$this->wrapper = new \phpbb\cron\task\wrapper(
$this->task,
$this->routing_helper,
$this->template
);
$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()
{
$this->assertFalse($this->wrapper->is_parametrized());
}
public function test_is_ready()
{
$this->task->method('is_runnable')->willReturn(true);
$this->task->method('should_run')->willReturn(true);
$this->assertTrue($this->wrapper->is_ready());
}
public function test_get_url_non_parametrized()
{
$this->task->method('get_name')->willReturn('test_task');
$this->routing_helper->expects($this->once())
->method('route')
->with('phpbb_cron_run', ['cron_type' => 'test_task'])
->willReturn('/cron/url');
$this->assertEquals('/cron/url', $this->wrapper->get_url());
}
public function test_get_html_tag()
{
$this->template = $this->createMock(\phpbb\template\template::class);
$this->wrapper = new \phpbb\cron\task\wrapper(
$this->task,
$this->routing_helper,
$this->template
);
$this->template->expects($this->once())
->method('set_filenames');
$this->template->expects($this->once())
->method('assign_var');
$this->template->expects($this->once())
->method('assign_display')
->willReturn('<img src="cron">');
$this->assertEquals('<img src="cron">', $this->wrapper->get_html_tag());
}
public function test_call_forwards_to_task()
{
$this->task = $this->getMockBuilder(\phpbb\cron\task\task::class)
->disableOriginalConstructor()
->setMethods(['get_name', 'run', 'is_runnable', 'should_run', 'some_method'])
->getMock();
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
$this->wrapper = new \phpbb\cron\task\wrapper(
$this->task,
$this->routing_helper,
$this->template
);
$this->task->expects($this->once())
->method('some_method')
->with('arg1', 'arg2')
->willReturn('result');
$result = $this->wrapper->some_method('arg1', 'arg2');
$this->assertEquals('result', $result);
}
}

View file

@ -28,10 +28,12 @@ class phpbb_dbal_auto_increment_test extends phpbb_database_test_case
{
parent::setUp();
$table_prefix = 'prefix_';
$this->db = $this->new_dbal();
$this->db_doctrine = $this->new_doctrine_dbal();
$factory = new \phpbb\db\tools\factory();
$this->tools = $factory->get($this->db_doctrine);
$this->tools->set_table_prefix($table_prefix);
$this->table_data = array(
'COLUMNS' => array(

View file

@ -35,12 +35,15 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
protected function setUp(): void
{
parent::setUp();
$table_prefix = 'prefix_';
$this->db = $this->new_dbal();
$this->doctrine_db = $this->new_doctrine_dbal();
$factory = new \phpbb\db\tools\factory();
$this->tools = $factory->get($this->doctrine_db);
$this->tools->set_table_prefix($table_prefix);
$this->table_data = array(
'COLUMNS' => array(
@ -232,23 +235,25 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
public function test_column_change_with_index()
{
$short_table_name = \phpbb\db\doctrine\table_helper::generate_shortname('table_name');
// Create column
$this->assertFalse($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012'));
$this->assertTrue($this->tools->sql_column_add('prefix_table_name', 'c_bug_12012', array('DECIMAL', 0)));
$this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012'));
// Create index over the column
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', 'i_bug_12012'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_i_bug_12012'));
$this->assertTrue($this->tools->sql_create_index('prefix_table_name', 'i_bug_12012', array('c_bug_12012', 'c_bool')));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'i_bug_12012'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_i_bug_12012'));
// Change type from int to string
$this->assertTrue($this->tools->sql_column_change('prefix_table_name', 'c_bug_12012', array('VCHAR:100', '')));
// Remove the index
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'i_bug_12012'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_i_bug_12012'));
$this->assertTrue($this->tools->sql_index_drop('prefix_table_name', 'i_bug_12012'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', 'i_bug_12012'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_i_bug_12012'));
// Remove the column
$this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012'));
@ -301,19 +306,21 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
public function test_column_remove_with_index()
{
$short_table_name = \phpbb\db\doctrine\table_helper::generate_shortname('table_name');
// Create column
$this->assertFalse($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012_2'));
$this->assertTrue($this->tools->sql_column_add('prefix_table_name', 'c_bug_12012_2', array('UINT', 4)));
$this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012_2'));
// Create index over the column
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', 'bug_12012_2'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_bug_12012_2'));
$this->assertTrue($this->tools->sql_create_index('prefix_table_name', 'bug_12012_2', array('c_bug_12012_2', 'c_bool')));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'bug_12012_2'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_bug_12012_2'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', 'bug_12012_3'));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_bug_12012_3'));
$this->assertTrue($this->tools->sql_create_index('prefix_table_name', 'bug_12012_3', array('c_bug_12012_2')));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'bug_12012_3'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_bug_12012_3'));
// Remove the column
$this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_bug_12012_2'));
@ -443,24 +450,24 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
public function test_index_exists()
{
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'i_simple'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', \phpbb\db\doctrine\table_helper::generate_shortname('table_name') . '_i_simple'));
}
public function test_unique_index_exists()
{
$this->assertTrue($this->tools->sql_unique_index_exists('prefix_table_name', 'i_uniq'));
$this->assertTrue($this->tools->sql_unique_index_exists('prefix_table_name', \phpbb\db\doctrine\table_helper::generate_shortname('table_name') . '_i_uniq'));
}
public function test_create_index_against_index_exists()
{
$this->tools->sql_create_index('prefix_table_name', 'fookey', array('c_timestamp', 'c_decimal'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'fookey'));
$this->assertTrue($this->tools->sql_index_exists('prefix_table_name', \phpbb\db\doctrine\table_helper::generate_shortname('table_name') . '_fookey'));
}
public function test_create_unique_index_against_unique_index_exists()
{
$this->tools->sql_create_unique_index('prefix_table_name', 'i_uniq_ts_id', array('c_timestamp', 'c_id'));
$this->assertTrue($this->tools->sql_unique_index_exists('prefix_table_name', 'i_uniq_ts_id'));
$this->assertTrue($this->tools->sql_unique_index_exists('prefix_table_name', \phpbb\db\doctrine\table_helper::generate_shortname('table_name') . '_i_uniq_ts_id'));
}
public function test_create_int_default_null()
@ -493,27 +500,28 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
$table_suffix = str_repeat('a', 25 - strlen($table_prefix));
$table_name = $table_prefix . $table_suffix;
$short_table_name = \phpbb\db\doctrine\table_helper::generate_shortname($table_suffix);
$this->tools->sql_create_table($table_name, $this->table_data);
// Index name and table suffix and table prefix have > maximum index length chars in total.
// Index name and table suffix have <= maximum index length chars in total.
$long_index_name = str_repeat('i', $max_index_length - strlen($table_suffix));
$this->assertFalse($this->tools->sql_index_exists($table_name, $long_index_name));
$this->assertFalse($this->tools->sql_index_exists($table_name, $short_table_name . '_' . $long_index_name));
$this->assertTrue($this->tools->sql_create_index($table_name, $long_index_name, array('c_timestamp')));
$this->assertTrue($this->tools->sql_index_exists($table_name, $long_index_name));
$this->assertTrue($this->tools->sql_index_exists($table_name, $short_table_name . '_' . $long_index_name));
// Index name and table suffix have > maximum index length chars in total.
$very_long_index_name = str_repeat('i', $max_index_length);
$this->assertFalse($this->tools->sql_index_exists($table_name, $very_long_index_name));
$this->assertFalse($this->tools->sql_index_exists($table_name, $short_table_name . '_' . $very_long_index_name));
$this->assertTrue($this->tools->sql_create_index($table_name, $very_long_index_name, array('c_timestamp')));
$this->assertTrue($this->tools->sql_index_exists($table_name, $very_long_index_name));
$this->assertTrue($this->tools->sql_index_exists($table_name, $short_table_name . '_' . $very_long_index_name));
$this->tools->sql_table_drop($table_name);
// Index name has > maximum index length chars - that should not be possible.
$too_long_index_name = str_repeat('i', $max_index_length + 1);
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $too_long_index_name));
$this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $short_table_name . '_' . $too_long_index_name));
$this->setExpectedTriggerError(E_USER_ERROR); // TODO: Do we want to keep this limitation, if yes reimplement the user check
/* https://github.com/phpbb/phpbb/blob/aee5e373bca6cd20d44b99585d3b758276a2d7e6/phpBB/phpbb/db/tools/tools.php#L1488-L1517 */
$this->tools->sql_create_index('prefix_table_name', $too_long_index_name, array('c_timestamp'));

View file

@ -22,12 +22,22 @@ class phpbb_dbal_migration_schema extends \phpbb\db\migration\migration
),
),
'add_tables' => array(
$this->table_prefix . 'foobar' => array(
'COLUMNS' => array(
'module_id' => array('UINT:3', NULL, 'auto_increment'),
),
$this->table_prefix . 'foobar' => [
'COLUMNS' => [
'module_id' => ['UINT:3', NULL, 'auto_increment'],
'user_id' => ['ULINT', 0],
'endpoint' => ['VCHAR:220', ''],
'expiration_time' => ['TIMESTAMP', 0],
'p256dh' => ['VCHAR:200', ''],
'auth' => ['VCHAR:100', ''],
],
'PRIMARY_KEY' => 'module_id',
),
'KEYS' => [
'i_simple' => ['INDEX', ['user_id', 'endpoint:191']],
'i_uniq' => ['UNIQUE', ['expiration_time', 'p256dh(100)']],
'i_auth' => ['INDEX', 'auth'],
],
],
),
);
}

View file

@ -0,0 +1,65 @@
<?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.
*
*/
class phpbb_dbal_migration_schema_index extends \phpbb\db\migration\migration
{
function update_schema()
{
return [
'add_tables' => [
$this->table_prefix . 'foobar1' => [
'COLUMNS' => [
'user_id' => ['UINT', 0],
'username' => ['VCHAR:50', 0],
],
'KEYS' => [
'tstidx_user_id' => ['UNIQUE', 'user_id'],
'tstidx_username' => ['INDEX', 'username'],
],
],
$this->table_prefix . 'foobar2' => [
'COLUMNS' => [
'ban_userid' => ['ULINT', 0],
'ban_ip' => ['VCHAR:40', ''],
'ban_reason' => ['VCHAR:100', ''],
],
'KEYS' => [
'tstidx_ban_userid' => ['UNIQUE', 'ban_userid'],
'tstidxban_data' => ['INDEX', ['ban_ip', 'ban_reason']],
],
],
],
'rename_index' => [
$this->table_prefix . 'foobar1' => [
'tstidx_user_id' => 'fbr1_user_id',
'tstidx_username' => 'fbr1_username',
],
$this->table_prefix . 'foobar2' => [
'tstidx_ban_userid' => 'fbr2_ban_userid',
'tstidxban_data' => 'fbr2_ban_data',
],
],
];
}
function revert_schema()
{
return [
'drop_tables' => [
$this->table_prefix . 'foobar1',
$this->table_prefix . 'foobar2',
],
];
}
}

View file

@ -24,6 +24,7 @@ require_once __DIR__ . '/migration/revert_table_with_dependency.php';
require_once __DIR__ . '/migration/fail.php';
require_once __DIR__ . '/migration/installed.php';
require_once __DIR__ . '/migration/schema.php';
require_once __DIR__ . '/migration/schema_index.php';
class phpbb_dbal_migrator_test extends phpbb_database_test_case
{
@ -52,12 +53,15 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
protected function setUp(): void
{
global $table_prefix;
parent::setUp();
$this->db = $this->new_dbal();
$this->doctrine_db = $this->new_doctrine_dbal();
$factory = new \phpbb\db\tools\factory();
$this->db_tools = $factory->get($this->doctrine_db);
$this->db_tools->set_table_prefix($table_prefix);
$this->config = new \phpbb\config\db($this->db, new phpbb_mock_cache, 'phpbb_config');
@ -408,6 +412,61 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
$this->assertTrue($this->db_tools->sql_column_exists('phpbb_config', 'test_column1'));
$this->assertTrue($this->db_tools->sql_table_exists('phpbb_foobar'));
$index_data_row = $this->db_tools->sql_get_table_index_data('phpbb_foobar');
$this->assertEquals(4, count($index_data_row));
$this->assertTrue(isset($index_data_row['i_simple']));
$this->assertTrue(isset($index_data_row['i_uniq']));
$this->assertTrue(isset($index_data_row['i_auth']));
$is_mysql = $this->db->get_sql_layer() === 'mysqli'; // Key 'lengths' option only applies to MySQL indexes
// MSSQL primary index key has 'clustered' flag, 'nonclustered' otherwise
// See https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described?view=sql-server-ver17#indexes-and-constraints
$is_mssql = in_array($this->db->get_sql_layer(), ['mssqlnative', 'mssql_odbc']);
foreach ($index_data_row as $index_name => $index_data)
{
switch ($index_name)
{
case 'i_simple':
$this->assertEquals(['user_id', 'endpoint'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']);
$this->assertEquals(2, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
$this->assertEquals($is_mysql ? 191 : null, $index_data['options']['lengths'][1]);
break;
case 'i_uniq':
$this->assertEquals(['expiration_time', 'p256dh'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertTrue($index_data['is_unique']);
$this->assertFalse($index_data['is_simple']);
$this->assertEquals(2, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
$this->assertEquals($is_mysql ? 100 : null, $index_data['options']['lengths'][1]);
break;
case 'i_auth':
$this->assertEquals(['auth'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']);
$this->assertEquals(1, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
break;
default: // Primary key
$this->assertEquals(['module_id'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
$this->assertTrue($index_data['is_primary']);
$this->assertTrue($index_data['is_unique']);
$this->assertFalse($index_data['is_simple']);
$this->assertEquals(1, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
break;
}
}
while ($this->migrator->migration_state('phpbb_dbal_migration_schema'))
{
$this->migrator->revert('phpbb_dbal_migration_schema');
@ -416,4 +475,86 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
$this->assertFalse($this->db_tools->sql_column_exists('phpbb_config', 'test_column1'));
$this->assertFalse($this->db_tools->sql_table_exists('phpbb_foobar'));
}
public function test_rename_index()
{
$this->migrator->set_migrations(array('phpbb_dbal_migration_schema_index'));
while (!$this->migrator->finished())
{
$this->migrator->update();
}
$this->assertTrue($this->db_tools->sql_unique_index_exists('phpbb_foobar1', 'fbr1_user_id'));
$this->assertTrue($this->db_tools->sql_index_exists('phpbb_foobar1', 'fbr1_username'));
$this->assertTrue($this->db_tools->sql_unique_index_exists('phpbb_foobar2', 'fbr2_ban_userid'));
$this->assertTrue($this->db_tools->sql_index_exists('phpbb_foobar2', 'fbr2_ban_data'));
while ($this->migrator->migration_state('phpbb_dbal_migration_schema_index'))
{
$this->migrator->revert('phpbb_dbal_migration_schema_index');
}
$this->assertFalse($this->db_tools->sql_table_exists('phpbb_foobar1'));
$this->assertFalse($this->db_tools->sql_table_exists('phpbb_foobar2'));
}
public function test_schema_generator(): array
{
global $phpbb_root_path, $phpEx;
$finder_factory = new \phpbb\finder\factory(null, false, $phpbb_root_path, $phpEx);
$finder = $finder_factory->get();
$migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes();
$schema_generator = new \phpbb\db\migration\schema_generator(
$migrator_classes,
$this->config,
$this->db,
$this->db_tools,
$phpbb_root_path,
$phpEx,
'phpbb_',
self::get_core_tables()
);
$db_table_schema = $schema_generator->get_schema();
$this->assertNotEmpty($db_table_schema);
return $db_table_schema;
}
/**
* @depends test_schema_generator
*/
public function test_table_indexes(array $db_table_schema)
{
$table_keys = [];
foreach ($db_table_schema as $table_name => $table_data)
{
if (isset($table_data['KEYS']))
{
foreach ($table_data['KEYS'] as $key_name => $key_data)
{
$table_keys[$table_name][] = $key_name;
}
}
}
$this->assertNotEmpty($table_keys);
$table_names = array_merge(array_keys($db_table_schema), ['phpbb_custom_table']);
$short_table_names = \phpbb\db\doctrine\table_helper::map_short_table_names($table_names, 'phpbb_');
$this->assertEquals('phpbb_custom_table', array_search(\phpbb\db\doctrine\table_helper::generate_shortname('custom_table'), $short_table_names));
$this->assertEquals($short_table_names['phpbb_custom_table'], \phpbb\db\doctrine\table_helper::generate_shortname('custom_table'));
foreach ($table_keys as $table_name => $key_names)
{
$index_prefix = $short_table_names[$table_name] . '_';
foreach ($key_names as $key_name)
{
$this->assertEquals(0, strpos($key_name, $index_prefix), "$key_name does not contain $index_prefix");
}
}
}
}

View file

@ -154,6 +154,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
{
$phpbb_root_path = __DIR__ . './../../phpBB/';
$php_ext = 'php';
$table_prefix = 'phpbb_';
$config = new \phpbb\config\config(array('version' => PHPBB_VERSION));
$db = $this->new_dbal();
@ -162,7 +163,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
$factory = new \phpbb\db\tools\factory();
$finder_factory = new \phpbb\finder\factory(null, false, $phpbb_root_path, $php_ext);
$db_tools = $factory->get($db_doctrine);
$table_prefix = 'phpbb_';
$db_tools->set_table_prefix($table_prefix);
$container = new phpbb_mock_container_builder();

View file

@ -37,6 +37,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
{
parent::setUp();
$this->table_prefix = 'phpbb_';
$this->config = new \phpbb\config\config(array(
'version' => '3.1.0',
));
@ -45,13 +46,13 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$factory = new \phpbb\db\tools\factory();
$this->db_tools = $factory->get($this->db_doctrine);
$this->db_tools->set_table_prefix($this->table_prefix);
$finder_factory = $this->createMock('\phpbb\finder\factory');
$this->phpbb_root_path = __DIR__ . '/';
$this->phpEx = 'php';
$this->cache = new \phpbb\cache\service(new phpbb_mock_cache(), $this->config, $this->db, $phpbb_dispatcher, $this->phpbb_root_path, $this->phpEx);
$this->table_prefix = 'phpbb_';
$container = new phpbb_mock_container_builder();
$cache_path = $this->phpbb_root_path . 'cache/twig';

View file

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

View file

@ -16,8 +16,6 @@
*/
class phpbb_functional_extension_global_lang_test extends phpbb_functional_test_case
{
protected $phpbb_extension_manager;
private static $helper;
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
{
protected $phpbb_extension_manager;
private static $helper;
protected static $fixtures = array(

View file

@ -16,8 +16,6 @@
*/
class phpbb_functional_extension_permission_lang_test extends phpbb_functional_test_case
{
protected $phpbb_extension_manager;
private static $helper;
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
tags:
- { name: event.listener }
foo_bar.listener.user_setup:
class: foo\bar\event\user_setup
tags:
- { 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:
foo_foo.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
{
protected $phpbb_extension_manager;
private static $helper;
protected static $fixtures = array(

View file

@ -55,6 +55,10 @@ class migrations_check_config_added_test extends phpbb_test_case
{
global $phpbb_root_path, $phpEx;
$this->table_prefix = 'phpbb_';
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->config = new \phpbb\config\config([
'search_type' => '\phpbb\search\fulltext_mysql',
]);
@ -63,9 +67,7 @@ class migrations_check_config_added_test extends phpbb_test_case
$this->db_doctrine = $this->createMock(\Doctrine\DBAL\Connection::class);
$factory = new \phpbb\db\tools\factory();
$this->db_tools = $factory->get($this->db_doctrine);
$this->table_prefix = 'phpbb_';
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->db_tools->set_table_prefix($this->table_prefix);
$tools = [
new \phpbb\db\migration\tool\config($this->config),

View file

@ -23,6 +23,8 @@ class get_callable_from_step_test extends phpbb_database_test_case
$db = $this->new_dbal();
$db_doctrine = $this->new_doctrine_dbal();
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($db_doctrine);
$db_tools->set_table_prefix($table_prefix);
$user = $this->getMockBuilder('\phpbb\user')->disableOriginalConstructor()->getMock();
$user->ip = '127.0.0.1';
$module_manager = new \phpbb\module\module_manager(
@ -38,7 +40,7 @@ class get_callable_from_step_test extends phpbb_database_test_case
new phpbb_mock_container_builder(),
new \phpbb\config\config(array()),
$db,
$factory->get($db_doctrine),
$db_tools,
'phpbb_migrations',
$phpbb_root_path,
$php_ext,

View file

@ -30,14 +30,16 @@ class schema_generator_test extends phpbb_test_case
parent::setUp();
$this->table_prefix = 'phpbb_';
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->config = new \phpbb\config\config(array());
$this->db = new \phpbb\db\driver\sqlite3();
$this->doctrine_db = \phpbb\db\doctrine\connection_factory::get_connection(new phpbb_mock_config_php_file());
$factory = new \phpbb\db\tools\factory();
$this->db_tools = $factory->get($this->doctrine_db);
$this->table_prefix = 'phpbb_';
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->db_tools->set_table_prefix($this->table_prefix);
}
protected function get_schema_generator(array $class_names)

View file

@ -15,7 +15,7 @@ require_once __DIR__ . '/template_test_case.php';
class phpbb_template_extension_test extends phpbb_template_template_test_case
{
protected function setup_engine(array $new_config = [])
protected function setup_engine(array $new_config = [], string $template_path = '')
{
global $config, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;

View file

@ -21,7 +21,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
/** @var string */
protected $parent_template_path;
protected function setup_engine(array $new_config = array())
protected function setup_engine(array $new_config = array(), string $template_path = '')
{
global $phpbb_root_path, $phpEx, $user;

View file

@ -1,4 +1,7 @@
<?php
use phpbb\template\twig\twig;
/**
*
* This file is part of the phpBB Forum Software package.
@ -14,6 +17,7 @@
class phpbb_template_template_test_case extends phpbb_test_case
{
protected $lang;
/** @var twig */
protected $template;
protected $template_path;
protected $user;
@ -68,7 +72,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
return $defaults;
}
protected function setup_engine(array $new_config = array())
protected function setup_engine(array $new_config = array(), string $template_path = '')
{
global $phpbb_root_path, $phpEx;
@ -90,7 +94,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
$phpEx
);
$this->template_path = $this->test_path . '/templates';
$this->template_path = $template_path ?: $this->test_path . '/templates';
$cache_path = $phpbb_root_path . 'cache/twig';
$context = new \phpbb\template\context();

View file

@ -21,7 +21,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
/** @var string */
protected $parent_template_path;
protected function setup_engine(array $new_config = array())
protected function setup_engine(array $new_config = [], string $template_path = '')
{
global $phpbb_root_path, $phpEx, $user;

View file

@ -88,6 +88,7 @@ abstract class phpbb_database_test_case extends TestCase
$doctrine = \phpbb\db\doctrine\connection_factory::get_connection(new phpbb_mock_config_php_file());
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($doctrine, true);
$db_tools->set_table_prefix($table_prefix);
$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix, self::get_core_tables());
file_put_contents(self::$schema_file, json_encode($schema_generator->get_schema()));

View file

@ -327,6 +327,8 @@ class phpbb_database_test_connection_manager
*/
protected function load_schema_from_file($directory, \phpbb\db\driver\driver_interface $db, \Doctrine\DBAL\Connection $doctrine)
{
global $table_prefix;
$schema = $this->dbms['SCHEMA'];
if ($this->config['dbms'] == 'phpbb\db\driver\mysql')
@ -363,7 +365,7 @@ class phpbb_database_test_connection_manager
}
else
{
global $phpbb_root_path, $phpEx, $table_prefix;
global $phpbb_root_path, $phpEx;
$finder = new \phpbb\finder\finder(null, false, $phpbb_root_path, $phpEx);
$classes = $finder->core_path('phpbb/db/migration/data/')
@ -373,6 +375,7 @@ class phpbb_database_test_connection_manager
$doctrine = \phpbb\db\doctrine\connection_factory::get_connection(new phpbb_mock_config_php_file());
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($doctrine, true);
$db_tools->set_table_prefix($table_prefix);
$tables = phpbb_database_test_case::get_core_tables();
$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix, $tables);
@ -381,6 +384,7 @@ class phpbb_database_test_connection_manager
$factory = new \phpbb\db\tools\factory();
$db_tools = $factory->get($doctrine);
$db_tools->set_table_prefix($table_prefix);
foreach ($db_table_schema as $table_name => $table_data)
{
$db_tools->sql_create_table(

View file

@ -286,6 +286,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$factory = new \phpbb\db\tools\factory();
$finder_factory = new \phpbb\finder\factory(null, false, $phpbb_root_path, $phpEx);
$db_tools = $factory->get($db_doctrine);
$db_tools->set_table_prefix(self::$config['table_prefix']);
$container = new phpbb_mock_container_builder();
$migrator = new \phpbb\db\migrator(
@ -644,7 +645,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$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))
{
preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match);