mirror of
https://github.com/phpbb/phpbb.git
synced 2025-09-13 09:32:12 +02:00
Compare commits
158 Commits
release-3.
...
release-3.
Author | SHA1 | Date | |
---|---|---|---|
|
9bf6e7f32e | ||
|
c93381ff04 | ||
|
88b79aba00 | ||
|
9c6df33e3b | ||
|
605726a4d7 | ||
|
3103e99dc7 | ||
|
a8c93ff661 | ||
|
1f4eac13b9 | ||
|
5e43f6195c | ||
|
6846eeaa48 | ||
|
b602b57b02 | ||
|
ba487a24dc | ||
|
015c9313a7 | ||
|
e7c81cd1a6 | ||
|
bf7936380a | ||
|
3f56bbb9d1 | ||
|
44d0a3a716 | ||
|
999122acdb | ||
|
c785c4b716 | ||
|
b305070e0a | ||
|
99634d4c05 | ||
|
fad1c652c0 | ||
|
1df74005a8 | ||
|
c7856ce162 | ||
|
cccf01447f | ||
|
ddc3eaa5bf | ||
|
65fa73855c | ||
|
391e4943d9 | ||
|
6801f7949f | ||
|
710aa10905 | ||
|
4a78202f96 | ||
|
d6a591cde3 | ||
|
4e447cc91a | ||
|
ec75f1741b | ||
|
af38f9d6c8 | ||
|
4614d3d92b | ||
|
866a4dc6d4 | ||
|
492352f652 | ||
|
1d05f722cb | ||
|
c1b88de806 | ||
|
89168c507b | ||
|
7a69c0f98c | ||
|
8cc6075d92 | ||
|
03b36d46c3 | ||
|
8104a446d4 | ||
|
aff3852568 | ||
|
39905eaf4b | ||
|
534cef94c9 | ||
|
a0ced790e2 | ||
|
0537365cac | ||
|
6e34e3c24e | ||
|
fecf3306f3 | ||
|
39db7005cd | ||
|
e956629735 | ||
|
89ca3f087e | ||
|
29d137cc5e | ||
|
88a11c1377 | ||
|
69b895caae | ||
|
d7f433fbf7 | ||
|
4d00c4c8af | ||
|
1e6c5cd381 | ||
|
0fbc5a3d83 | ||
|
3bfb2b3f69 | ||
|
337d876df7 | ||
|
8246023e0f | ||
|
b28b94b1f1 | ||
|
baf4bd7b5c | ||
|
81126dc97e | ||
|
391f80d480 | ||
|
febe44ed79 | ||
|
ede9a6815a | ||
|
2801415c1c | ||
|
dd029ed592 | ||
|
1d4fbd240e | ||
|
7275cdd152 | ||
|
b1e6fad38a | ||
|
9671a00214 | ||
|
d17b15a545 | ||
|
f841a0a1b8 | ||
|
7472d300b6 | ||
|
06ef03f8d6 | ||
|
40322bb1b6 | ||
|
6218c2e120 | ||
|
afbf7aadd2 | ||
|
a860a3310a | ||
|
ca24013470 | ||
|
99734fc648 | ||
|
3547f0bf0e | ||
|
01a22e7223 | ||
|
2145938d74 | ||
|
62a8741494 | ||
|
13155bf846 | ||
|
4d966d1762 | ||
|
056fb494b1 | ||
|
da7c9f6a7c | ||
|
73eb54bf54 | ||
|
6af8872ef3 | ||
|
a3070bedeb | ||
|
a12f903e93 | ||
|
d4cb357b26 | ||
|
b6e31e3664 | ||
|
7355ee623a | ||
|
a7385f0fbe | ||
|
c5814ddfaa | ||
|
96c439bf10 | ||
|
7a21a9032e | ||
|
1619014120 | ||
|
0a4d062e16 | ||
|
dda2dfecb3 | ||
|
b29c0ca153 | ||
|
c0296d10db | ||
|
4f3f91dfc3 | ||
|
52c931a8b6 | ||
|
9ca70432d9 | ||
|
1fbb807cc7 | ||
|
98f446df67 | ||
|
43b9254d1d | ||
|
97034e0776 | ||
|
02e5a7afc4 | ||
|
7efddcef54 | ||
|
ea36b83ee9 | ||
|
59cece1a0a | ||
|
e5fa23c3c0 | ||
|
9a7d88362f | ||
|
7f6c859b0d | ||
|
441a5a2175 | ||
|
ceca69d121 | ||
|
6a72d0305b | ||
|
7a8d9671c2 | ||
|
5b3d238804 | ||
|
1860a06eab | ||
|
1862992ca7 | ||
|
95fa6cceee | ||
|
19076de94c | ||
|
27289cbfad | ||
|
3d76942cdf | ||
|
51cc7202f8 | ||
|
303a933403 | ||
|
54b54c41c6 | ||
|
59e50d6d53 | ||
|
2a1656e7b3 | ||
|
12ce75b5f5 | ||
|
b82d90eb39 | ||
|
f302440297 | ||
|
848021c743 | ||
|
c4b4e1d7a9 | ||
|
ed33f06235 | ||
|
643845306a | ||
|
95511540ea | ||
|
b3b5fcc874 | ||
|
1b4ba00a73 | ||
|
8caf2e7c59 | ||
|
a87a60c108 | ||
|
8cc0e5438a | ||
|
2c8be65dcf | ||
|
c3598d0d58 | ||
|
92a2c08616 | ||
|
e5b43eabe1 |
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,7 +2,7 @@ Checklist:
|
||||
|
||||
- [ ] Correct branch: master for new features; 3.3.x for fixes
|
||||
- [ ] Tests pass
|
||||
- [ ] Code follows coding guidelines: [master](https://area51.phpbb.com/docs/dev/master/development/coding_guidelines.html) and [3.3.x](https://area51.phpbb.com/docs/dev/3.3.x/development/coding_guidelines.html)
|
||||
- [ ] Code follows coding guidelines: [master](https://area51.phpbb.com/docs/master/coding-guidelines.html) and [3.3.x](https://area51.phpbb.com/docs/dev/3.3.x/development/coding_guidelines.html)
|
||||
- [ ] Commit follows commit message [format](https://area51.phpbb.com/docs/dev/3.3.x/development/git.html)
|
||||
|
||||
Tracker ticket (set the ticket ID to **your ticket ID**):
|
||||
|
46
.github/workflows/tests.yml
vendored
46
.github/workflows/tests.yml
vendored
@@ -126,6 +126,8 @@ jobs:
|
||||
db: "mysql:5.7"
|
||||
- php: '8.1'
|
||||
db: "mysql:5.7"
|
||||
- php: '8.2'
|
||||
db: "mysql:5.7"
|
||||
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.db_alias != '' && matrix.db_alias || matrix.db }}
|
||||
|
||||
@@ -253,6 +255,10 @@ jobs:
|
||||
db: "postgres:12"
|
||||
- php: '8.0'
|
||||
db: "postgres:13"
|
||||
- php: '8.1'
|
||||
db: "postgres:14"
|
||||
- php: '8.2'
|
||||
db: "postgres:14"
|
||||
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.db }}
|
||||
|
||||
@@ -442,18 +448,36 @@ jobs:
|
||||
|
||||
# Test with IIS & PostgreSQL on Windows
|
||||
windows-tests:
|
||||
runs-on: windows-2016
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- php: '7.4'
|
||||
db: "postgres"
|
||||
type: 'unit'
|
||||
- php: '8.0'
|
||||
db: "postgres"
|
||||
type: 'unit'
|
||||
- php: '8.1'
|
||||
db: "postgres"
|
||||
type: 'unit'
|
||||
- php: '8.2'
|
||||
db: "postgres"
|
||||
type: 'unit'
|
||||
- php: '7.4'
|
||||
db: "postgres"
|
||||
type: 'functional'
|
||||
- php: '8.0'
|
||||
db: "postgres"
|
||||
type: 'functional'
|
||||
- php: '8.1'
|
||||
db: "postgres"
|
||||
type: 'functional'
|
||||
- php: '8.2'
|
||||
db: "postgres"
|
||||
type: 'functional'
|
||||
|
||||
name: Windows - PHP ${{ matrix.php }} - ${{ matrix.db }}
|
||||
name: Windows - PHP ${{ matrix.php }} - ${{ matrix.db }} - ${{ matrix.type }}
|
||||
|
||||
steps:
|
||||
- name: Prepare git for Windows
|
||||
@@ -530,17 +554,27 @@ jobs:
|
||||
run: |
|
||||
$postgreSqlSvc = Get-Service "postgresql*"
|
||||
Set-Service $postgreSqlSvc.Name -StartupType manual
|
||||
$postgreSqlSvc.Start()
|
||||
$runningStatus = [System.ServiceProcess.ServiceControllerStatus]::Running
|
||||
$maxStartTimeout = New-TimeSpan -Seconds 30
|
||||
try {
|
||||
(Get-Service "postgresql*").Start()
|
||||
$postgreSqlSvc.Start()
|
||||
$postgreSqlSvc.WaitForStatus($runningStatus, $maxStartTimeout)
|
||||
} catch {
|
||||
$_ | select *
|
||||
}
|
||||
[System.Environment]::SetEnvironmentVariable('PATH',$Env:PATH+";${env:PGBIN}")
|
||||
$env:PGPASSWORD = 'root'
|
||||
psql -c 'ALTER SYSTEM SET hot_standby = on;' -U postgres
|
||||
psql -c 'ALTER SYSTEM SET wal_level = minimal;' -U postgres
|
||||
psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres
|
||||
psql -c 'create database phpbb_tests;' -U postgres
|
||||
Add-MpPreference -ExclusionPath "${env:PGDATA}" # Exclude PGDATA directory from Windows Defender
|
||||
Set-MpPreference -ExclusionPath "${env:PGDATA}" # Exclude PGDATA directory from Windows Defender
|
||||
Set-MpPreference -DisableRealtimeMonitoring $true
|
||||
- name: Run unit tests
|
||||
if: ${{ matrix.type == 'unit' }}
|
||||
run: |
|
||||
phpBB/vendor/bin/phpunit --configuration .github/phpunit-psql-windows-github.xml --verbose --stop-on-error
|
||||
phpBB/vendor/bin/phpunit --configuration .github/phpunit-psql-windows-github.xml --verbose --stop-on-error --exclude-group functional
|
||||
- name: Run unit tests
|
||||
if: ${{ matrix.type == 'functional' }}
|
||||
run: |
|
||||
phpBB/vendor/bin/phpunit --configuration .github/phpunit-psql-windows-github.xml --verbose --stop-on-error --group functional
|
||||
|
33
.gitignore
vendored
33
.gitignore
vendored
@@ -1,33 +1,54 @@
|
||||
*~
|
||||
/phpunit.xml
|
||||
# Excludes cache
|
||||
/phpBB/cache/*
|
||||
!/phpBB/cache/.htaccess
|
||||
!/phpBB/cache/index.html
|
||||
/phpBB/composer.phar
|
||||
|
||||
# Excludes user data
|
||||
/phpBB/config*.php*
|
||||
/phpBB/ext/*
|
||||
/phpBB/files/*
|
||||
/phpBB/images/avatars/gallery/*
|
||||
/phpBB/images/avatars/upload/*
|
||||
/phpBB/images/ranks/*
|
||||
/phpBB/install/schemas/schema.json
|
||||
/phpBB/store/*
|
||||
|
||||
# Excludes all custom langages
|
||||
/phpBB/language/*
|
||||
!/phpBB/language/en
|
||||
/phpBB/store/*
|
||||
|
||||
# Excludes all custom styles
|
||||
/phpBB/styles/*
|
||||
!/phpBB/styles/prosilver
|
||||
/phpBB/styles/prosilver/theme/*/
|
||||
!/phpBB/styles/prosilver/theme/en
|
||||
!/phpBB/styles/prosilver/theme/images
|
||||
!/phpBB/styles/all
|
||||
node_modules
|
||||
|
||||
# Excludes all custom env
|
||||
/phpBB/config/*
|
||||
!/phpBB/config/default
|
||||
!/phpBB/config/development
|
||||
!/phpBB/config/installer
|
||||
!/phpBB/config/production
|
||||
!/phpBB/config/test
|
||||
!/phpBB/config/.htaccess
|
||||
|
||||
# Excludes vendors
|
||||
/phpBB/vendor
|
||||
|
||||
# Excludes test / dev files
|
||||
/phpunit.xml
|
||||
/phpBB/composer.phar
|
||||
/tests/phpbb_unit_tests.sqlite*
|
||||
/tests/test_config*.php
|
||||
/tests/tmp/*
|
||||
/tests/vendor
|
||||
/vagrant/phpbb-install-config.yml
|
||||
.vagrant
|
||||
node_modules
|
||||
|
||||
# Excludes IDE / editors files
|
||||
*~
|
||||
.idea
|
||||
*.DS_Store*
|
||||
/.vscode
|
||||
|
@@ -2,9 +2,9 @@
|
||||
|
||||
<project name="phpBB" description="The phpBB forum software" default="all" basedir="../">
|
||||
<!-- a few settings for the build -->
|
||||
<property name="newversion" value="3.3.5-RC1" />
|
||||
<property name="prevversion" value="3.3.4" />
|
||||
<property name="olderversions" value="3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5, 3.1.6, 3.1.7, 3.1.7-pl1, 3.1.8, 3.1.9, 3.1.10, 3.1.11, 3.1.12, 3.2.0, 3.2.1, 3.2.2, 3.2.3, 3.2.4, 3.2.5, 3.2.6, 3.2.7, 3.2.8, 3.2.9, 3.2.10, 3.2.11, 3.3.0, 3.3.1, 3.3.2, 3.3.3" />
|
||||
<property name="newversion" value="3.3.6-RC1" />
|
||||
<property name="prevversion" value="3.3.5" />
|
||||
<property name="olderversions" value="3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5, 3.1.6, 3.1.7, 3.1.7-pl1, 3.1.8, 3.1.9, 3.1.10, 3.1.11, 3.1.12, 3.2.0, 3.2.1, 3.2.2, 3.2.3, 3.2.4, 3.2.5, 3.2.6, 3.2.7, 3.2.8, 3.2.9, 3.2.10, 3.2.11, 3.3.0, 3.3.1, 3.3.2, 3.3.3, 3.3.4" />
|
||||
<!-- no configuration should be needed beyond this point -->
|
||||
|
||||
<property name="oldversions" value="${olderversions}, ${prevversion}" />
|
||||
|
BIN
composer.phar
BIN
composer.phar
Binary file not shown.
@@ -29,7 +29,7 @@
|
||||
|
||||
<!-- BEGIN upload -->
|
||||
:: {upload.FILE_INFO}<br />
|
||||
<!-- IF upload.S_DENIED --><span class="error">{upload.DENIED}</span><!-- ELSEIF upload.ERROR_MSG --><span class="error">{upload.ERROR_MSG}</span><!-- ELSE --><span class="success">{L_SUCCESSFULLY_UPLOADED}</span><!-- ENDIF -->
|
||||
<!-- IF upload.S_DENIED --><span class="error">{upload.L_DENIED}</span><!-- ELSEIF upload.ERROR_MSG --><span class="error">{upload.ERROR_MSG}</span><!-- ELSE --><span class="success">{L_SUCCESSFULLY_UPLOADED}</span><!-- ENDIF -->
|
||||
<br /><br />
|
||||
<!-- END upload -->
|
||||
|
||||
|
@@ -105,7 +105,7 @@
|
||||
<!-- BEGIN items -->
|
||||
<tr>
|
||||
|
||||
<td style="text-align: center;"><img src="{items.IMG_SRC}" alt="{items.TEXT_ALT}" title="{items.TEXT_ALT}" /><input type="hidden" name="image[{items.IMG}]" value="1" /></td>
|
||||
<td style="text-align: center;"><img src="{items.IMG_SRC}" alt="{items.TEXT_ALT}" title="{items.TEXT_ALT}" style="max-width: 160px;"><input type="hidden" name="image[{items.IMG}]" value="1" /></td>
|
||||
<td style="vertical-align: top;">[{items.IMG}]</td>
|
||||
<!-- IF S_SMILIES -->
|
||||
<td><input class="text post" type="text" name="code[{items.IMG}]" value="{items.CODE}" size="10" maxlength="50" /></td>
|
||||
|
@@ -140,7 +140,6 @@
|
||||
<td class="tabled"><strong>{{ PHP_VERSION_INFO }}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% if S_TOTAL_ORPHAN %}
|
||||
<td class="tabled">{{ lang('NUMBER_ORPHAN') ~ lang('COLON') }}</td>
|
||||
<td class="tabled">
|
||||
{% if TOTAL_ORPHAN > 0 %}
|
||||
@@ -149,8 +148,6 @@
|
||||
<strong>{{ TOTAL_ORPHAN }}</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% if S_VERSIONCHECK %}
|
||||
<tr>
|
||||
@@ -204,10 +201,12 @@
|
||||
<td class="tabled">{{ lang('FILES_PER_DAY') ~ lang('COLON') }}</td>
|
||||
<td class="tabled"><strong>{{ FILES_PER_DAY }}</strong></td>
|
||||
</tr>
|
||||
{% if S_VERSIONCHECK %}
|
||||
<tr>
|
||||
<td class="tabled"> </td>
|
||||
<td class="tabled"> </td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@@ -85,7 +85,7 @@
|
||||
<!-- BEGIN ranks -->
|
||||
<tr>
|
||||
<!-- EVENT acp_ranks_list_column_before -->
|
||||
<td style="text-align: center;"><!-- IF ranks.S_RANK_IMAGE --><img src="{ranks.RANK_IMAGE}" alt="{ranks.RANK_TITLE}" title="{ranks.RANK_TITLE}" /><!-- ELSE --> - <!-- ENDIF --></td>
|
||||
<td style="text-align: center;"><!-- IF ranks.S_RANK_IMAGE --><img src="{ranks.RANK_IMAGE}" alt="{ranks.RANK_TITLE}" title="{ranks.RANK_TITLE}" style="max-width: 160px;"><!-- ELSE --> - <!-- ENDIF --></td>
|
||||
<td style="text-align: center;">{ranks.RANK_TITLE}</td>
|
||||
<td style="text-align: center;"><!-- IF ranks.S_SPECIAL_RANK --> - <!-- ELSE -->{ranks.MIN_POSTS}<!-- ENDIF --></td>
|
||||
<!-- EVENT acp_ranks_list_column_after -->
|
||||
|
4
phpBB/assets/plupload/plupload.full.min.js
vendored
4
phpBB/assets/plupload/plupload.full.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -96,6 +96,8 @@ include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/constants.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
|
||||
|
||||
// Registered before building the container so the development environment stay capable of intercepting
|
||||
// the container builder exceptions.
|
||||
if (PHPBB_ENVIRONMENT === 'development')
|
||||
{
|
||||
\phpbb\debug\debug::enable();
|
||||
@@ -129,6 +131,11 @@ catch (InvalidArgumentException $e)
|
||||
}
|
||||
}
|
||||
|
||||
if ($phpbb_container->getParameter('debug.error_handler'))
|
||||
{
|
||||
\phpbb\debug\debug::enable();
|
||||
}
|
||||
|
||||
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
|
||||
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
|
||||
|
||||
|
172
phpBB/composer.lock
generated
172
phpBB/composer.lock
generated
@@ -42,16 +42,16 @@
|
||||
},
|
||||
{
|
||||
"name": "composer/package-versions-deprecated",
|
||||
"version": "1.11.99.3",
|
||||
"version": "1.11.99.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/package-versions-deprecated.git",
|
||||
"reference": "fff576ac850c045158a250e7e27666e146e78d18"
|
||||
"reference": "b174585d1fe49ceed21928a945138948cb394600"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/fff576ac850c045158a250e7e27666e146e78d18",
|
||||
"reference": "fff576ac850c045158a250e7e27666e146e78d18",
|
||||
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b174585d1fe49ceed21928a945138948cb394600",
|
||||
"reference": "b174585d1fe49ceed21928a945138948cb394600",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -95,7 +95,7 @@
|
||||
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
|
||||
"support": {
|
||||
"issues": "https://github.com/composer/package-versions-deprecated/issues",
|
||||
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.3"
|
||||
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -111,7 +111,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-17T13:49:14+00:00"
|
||||
"time": "2021-09-13T08:41:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "google/recaptcha",
|
||||
@@ -238,16 +238,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
|
||||
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -259,7 +259,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
"dev-master": "1.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -275,10 +275,25 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle promises library",
|
||||
@@ -287,22 +302,36 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/1.4.1"
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.1"
|
||||
},
|
||||
"time": "2021-03-07T09:25:29+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-22T20:56:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.2",
|
||||
"version": "1.8.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -339,13 +368,34 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "George Mponos",
|
||||
"email": "gmponos@gmail.com",
|
||||
"homepage": "https://github.com/gmponos"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com",
|
||||
"homepage": "https://github.com/sagikazarmark"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
@@ -362,9 +412,23 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.3"
|
||||
},
|
||||
"time": "2021-04-26T09:17:50+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-05T13:56:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lusitanian/oauth",
|
||||
@@ -859,16 +923,16 @@
|
||||
},
|
||||
{
|
||||
"name": "s9e/text-formatter",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/s9e/TextFormatter.git",
|
||||
"reference": "00df71d0a803c041efa320ce2f2c0e56c1a6fca9"
|
||||
"reference": "b9d9d7ac480301f0cf718345daf591ddf475d9f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/s9e/TextFormatter/zipball/00df71d0a803c041efa320ce2f2c0e56c1a6fca9",
|
||||
"reference": "00df71d0a803c041efa320ce2f2c0e56c1a6fca9",
|
||||
"url": "https://api.github.com/repos/s9e/TextFormatter/zipball/b9d9d7ac480301f0cf718345daf591ddf475d9f1",
|
||||
"reference": "b9d9d7ac480301f0cf718345daf591ddf475d9f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -895,7 +959,7 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"version": "2.10.0"
|
||||
"version": "2.11.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -927,9 +991,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/s9e/TextFormatter/issues",
|
||||
"source": "https://github.com/s9e/TextFormatter/tree/2.10.0"
|
||||
"source": "https://github.com/s9e/TextFormatter/tree/2.11.0"
|
||||
},
|
||||
"time": "2021-08-11T15:45:12+00:00"
|
||||
"time": "2021-10-02T19:08:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
@@ -3212,16 +3276,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-webdriver/webdriver",
|
||||
"version": "1.11.1",
|
||||
"version": "1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-webdriver/php-webdriver.git",
|
||||
"reference": "da16e39968f8dd5cfb7d07eef91dc2b731c69880"
|
||||
"reference": "99d4856ed7dffcdf6a52eccd6551e83d8d557ceb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/da16e39968f8dd5cfb7d07eef91dc2b731c69880",
|
||||
"reference": "da16e39968f8dd5cfb7d07eef91dc2b731c69880",
|
||||
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/99d4856ed7dffcdf6a52eccd6551e83d8d557ceb",
|
||||
"reference": "99d4856ed7dffcdf6a52eccd6551e83d8d557ceb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3230,20 +3294,19 @@
|
||||
"ext-zip": "*",
|
||||
"php": "^5.6 || ~7.0 || ^8.0",
|
||||
"symfony/polyfill-mbstring": "^1.12",
|
||||
"symfony/process": "^2.8 || ^3.1 || ^4.0 || ^5.0"
|
||||
"symfony/process": "^2.8 || ^3.1 || ^4.0 || ^5.0 || ^6.0"
|
||||
},
|
||||
"replace": {
|
||||
"facebook/webdriver": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.0",
|
||||
"ondram/ci-detector": "^2.1 || ^3.5 || ^4.0",
|
||||
"php-coveralls/php-coveralls": "^2.4",
|
||||
"php-mock/php-mock-phpunit": "^1.1 || ^2.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpunit/phpunit": "^5.7 || ^7 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"symfony/var-dumper": "^3.3 || ^4.0 || ^5.0"
|
||||
"symfony/var-dumper": "^3.3 || ^4.0 || ^5.0 || ^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-SimpleXML": "For Firefox profile creation"
|
||||
@@ -3272,9 +3335,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
|
||||
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.11.1"
|
||||
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.0"
|
||||
},
|
||||
"time": "2021-05-21T15:12:49+00:00"
|
||||
"time": "2021-10-14T09:30:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
@@ -3629,16 +3692,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "28af674ff175d0768a5a978e6de83f697d4a7f05"
|
||||
"reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/28af674ff175d0768a5a978e6de83f697d4a7f05",
|
||||
"reference": "28af674ff175d0768a5a978e6de83f697d4a7f05",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5",
|
||||
"reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3677,7 +3740,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.4"
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3685,7 +3748,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-07-19T06:46:01+00:00"
|
||||
"time": "2021-12-02T12:42:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
@@ -4199,16 +4262,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "3.1.3",
|
||||
"version": "3.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "6b853149eab67d4da22291d36f5b0631c0fd856e"
|
||||
"reference": "0c32ea2e40dbf59de29f3b49bf375176ce7dd8db"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e",
|
||||
"reference": "6b853149eab67d4da22291d36f5b0631c0fd856e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0c32ea2e40dbf59de29f3b49bf375176ce7dd8db",
|
||||
"reference": "0c32ea2e40dbf59de29f3b49bf375176ce7dd8db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4217,7 +4280,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-mbstring": "*",
|
||||
"phpunit/phpunit": "^6.0"
|
||||
"phpunit/phpunit": "^8.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -4264,7 +4327,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3"
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/3.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4272,7 +4335,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-30T07:47:53+00:00"
|
||||
"time": "2021-11-11T13:51:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
@@ -4554,7 +4617,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2020-11-30T07:30:19+00:00"
|
||||
},
|
||||
{
|
||||
@@ -4606,16 +4668,16 @@
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.6.0",
|
||||
"version": "3.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
|
||||
"reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
|
||||
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f268ca40d54617c6e06757f83f699775c9b3ff2e",
|
||||
"reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4658,7 +4720,7 @@
|
||||
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
|
||||
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
|
||||
},
|
||||
"time": "2021-04-09T00:54:41+00:00"
|
||||
"time": "2021-10-11T04:00:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
@@ -4975,5 +5037,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "7.1.3"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
@@ -116,6 +116,7 @@ services:
|
||||
- '@dbal.conn'
|
||||
- '@config'
|
||||
- '@filesystem'
|
||||
- '@router'
|
||||
- '%tables.ext%'
|
||||
- '%core.root_path%'
|
||||
- '%core.php_ext%'
|
||||
|
@@ -11,6 +11,7 @@ core:
|
||||
sql_explain: true
|
||||
memory: true
|
||||
show_errors: true
|
||||
error_handler: true
|
||||
|
||||
twig:
|
||||
debug: true
|
||||
|
@@ -50,6 +50,8 @@
|
||||
<ol>
|
||||
<li><a href="#changelog">Changelog</a>
|
||||
<ul>
|
||||
<li><a href="#v335">Changes since 3.3.5</a></li>
|
||||
<li><a href="#v335rc1">Changes since 3.3.5-RC1</a></li>
|
||||
<li><a href="#v334">Changes since 3.3.4</a></li>
|
||||
<li><a href="#v334rc1">Changes since 3.3.4-RC1</a></li>
|
||||
<li><a href="#v333">Changes since 3.3.3</a></li>
|
||||
@@ -157,6 +159,58 @@
|
||||
<div class="inner">
|
||||
|
||||
<div class="content">
|
||||
<a name="v335"></a><h3>Changes since 3.3.5</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16881">PHPBB3-16881</a>] - Fix ACP Statistic Table</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16883">PHPBB3-16883</a>] - Check if var is array before using count in installer diff</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16887">PHPBB3-16887</a>] - Update required PHP version</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16889">PHPBB3-16889</a>] - Postgres on windows builds keep failing</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16892">PHPBB3-16892</a>] - Duplicate entry for jav files in extension guesser</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16895">PHPBB3-16895</a>] - 'Permission' migration tool incorrectly handles role removal</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16897">PHPBB3-16897</a>] - sqlite3 drivers generates warnings when executing an explain query plan that fails</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16900">PHPBB3-16900</a>] - Invalid email subject header on long topic titles</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16904">PHPBB3-16904</a>] - Regression for topic selection in MCP in 3.3.5</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16908">PHPBB3-16908</a>] - PHP warning on non-existent post id requests</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16910">PHPBB3-16910</a>] - PHP warning if trying to attach orphaned files to non existent posts</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16914">PHPBB3-16914</a>] - Missing id in memberlist email template</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16924">PHPBB3-16924</a>] - Double escaping of config values inserted with db config</li>
|
||||
</ul>
|
||||
<h4>Improvement</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-13508">PHPBB3-13508</a>] - Support using INCLUDEJS and INCLUDECSS in twig template format</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16828">PHPBB3-16828</a>] - Add hook event before find_users_for_notification() execute</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16859">PHPBB3-16859</a>] - Language selection option is displayed on register if only 1 language is installed</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16885">PHPBB3-16885</a>] - Add filters to Twig - INT and FLOAT</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16888">PHPBB3-16888</a>] - Add the list of allowed attachment types using accept attribute </li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16896">PHPBB3-16896</a>] - Improve .gitignore visibility</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16898">PHPBB3-16898</a>] - Do not restrict the debug error handler to the development environment</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16899">PHPBB3-16899</a>] - Add SVG and WEBP image type to ranks, smilies and topic icons</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16902">PHPBB3-16902</a>] - Improve search results count for MySQL</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16909">PHPBB3-16909</a>] - Add PHP 8.2 builds to test matrix</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16912">PHPBB3-16912</a>] - Improve mail encoding to better match RFC 2047</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16921">PHPBB3-16921</a>] - Increase PHP requirements in the DOCS</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16930">PHPBB3-16930</a>] - Remove redundant topic ID from last post URL</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16933">PHPBB3-16933</a>] - Inconsistent handling of hyphen by phpBB Native search backend</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16939">PHPBB3-16939</a>] - Wait for postgres service to start in GitHub Actions windows builds</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16940">PHPBB3-16940</a>] - Optimize phpBB Native Search</li>
|
||||
</ul>
|
||||
<h4>Task</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16927">PHPBB3-16927</a>] - Update plupload to latest version</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16928">PHPBB3-16928</a>] - Update composer and composer dependencies to latest versions</li>
|
||||
</ul>
|
||||
|
||||
<a name="v335rc1"></a><h3>Changes since 3.3.5-RC1</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB3-16878">PHPBB3-16878</a>] - Error in password_hash() with ARGON2 + Sodium & threadcount > 1</li>
|
||||
</ul>
|
||||
<h4>Hardening</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/SECURITY-254">SECURITY-254</a>] - Disallow whitespace characters that might be invisible</li>
|
||||
</ul>
|
||||
|
||||
<a name="v334"></a><h3>Changes since 3.3.4</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
|
@@ -147,7 +147,7 @@
|
||||
<li>Oracle</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>PHP 7.1.3+</strong> up to and including <strong>PHP 7.4</strong> with support for the database you intend to use.</li>
|
||||
<li><strong>PHP 7.1.3+</strong> up to and including <strong>PHP 8.1</strong> with support for the database you intend to use.</li>
|
||||
<li>The following PHP modules are required:
|
||||
<ul>
|
||||
<li>json</li>
|
||||
|
@@ -1000,29 +1000,45 @@ class acp_attachments
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$files_added = $space_taken = 0;
|
||||
$error_msg = '';
|
||||
$upload_row = [];
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$post_row = $post_info[$upload_list[$row['attach_id']]];
|
||||
$upload_row = [
|
||||
'FILE_INFO' => $user->lang('UPLOADING_FILE_TO', $row['real_filename'], $upload_list[$row['attach_id']]),
|
||||
];
|
||||
|
||||
$template->assign_block_vars('upload', array(
|
||||
'FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']),
|
||||
'S_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? true : false,
|
||||
'L_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : '')
|
||||
);
|
||||
if (isset($post_info[$upload_list[$row['attach_id']]]))
|
||||
{
|
||||
$post_row = $post_info[$upload_list[$row['attach_id']]];
|
||||
$upload_row = array_merge($upload_row, [
|
||||
'S_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']),
|
||||
'L_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']) ? $user->lang('UPLOAD_DENIED_FORUM', $forum_names[$row['forum_id']]) : '',
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$error_msg = $user->lang('UPLOAD_POST_NOT_EXIST', $row['real_filename'], $upload_list[$row['attach_id']]);
|
||||
$upload_row = array_merge($upload_row, [
|
||||
'ERROR_MSG' => $error_msg,
|
||||
]);
|
||||
};
|
||||
|
||||
if (!$auth->acl_get('f_attach', $post_row['forum_id']))
|
||||
$template->assign_block_vars('upload', $upload_row);
|
||||
|
||||
if ($error_msg || !$auth->acl_get('f_attach', $post_row['forum_id']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Adjust attachment entry
|
||||
$sql_ary = array(
|
||||
$sql_ary = [
|
||||
'in_message' => 0,
|
||||
'is_orphan' => 0,
|
||||
'poster_id' => $post_row['poster_id'],
|
||||
'post_msg_id' => $post_row['post_id'],
|
||||
'topic_id' => $post_row['topic_id'],
|
||||
);
|
||||
];
|
||||
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
|
||||
@@ -1042,7 +1058,7 @@ class acp_attachments
|
||||
$space_taken += $row['filesize'];
|
||||
$files_added++;
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_FILEUPLOAD', false, array($post_row['post_id'], $row['real_filename']));
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_FILEUPLOAD', false, [$post_row['post_id'], $row['real_filename']]);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
@@ -1054,9 +1070,9 @@ class acp_attachments
|
||||
}
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_ORPHAN' => true)
|
||||
);
|
||||
$template->assign_vars([
|
||||
'S_ORPHAN' => true,
|
||||
]);
|
||||
|
||||
$attachments_per_page = (int) $config['topics_per_page'];
|
||||
|
||||
@@ -1084,15 +1100,15 @@ class acp_attachments
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$template->assign_block_vars('orphan', array(
|
||||
$template->assign_block_vars('orphan', [
|
||||
'FILESIZE' => get_formatted_filesize($row['filesize']),
|
||||
'FILETIME' => $user->format_date($row['filetime']),
|
||||
'REAL_FILENAME' => utf8_basename($row['real_filename']),
|
||||
'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']),
|
||||
'ATTACH_ID' => $row['attach_id'],
|
||||
'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
|
||||
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id']))
|
||||
);
|
||||
'POST_ID' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
|
||||
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id']),
|
||||
]);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
@@ -1105,10 +1121,10 @@ class acp_attachments
|
||||
$start
|
||||
);
|
||||
|
||||
$template->assign_vars(array(
|
||||
$template->assign_vars([
|
||||
'TOTAL_FILES' => $num_files,
|
||||
'TOTAL_SIZE' => get_formatted_filesize($total_size),
|
||||
));
|
||||
]);
|
||||
|
||||
break;
|
||||
|
||||
|
@@ -91,29 +91,43 @@ class acp_icons
|
||||
{
|
||||
$img_size = getimagesize($phpbb_root_path . $img_path . '/' . $path . $img);
|
||||
|
||||
if (!$img_size[0] || !$img_size[1] || strlen($img) > 255)
|
||||
if ($img_size)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!$img_size[0] || !$img_size[1] || strlen($img) > 255)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// adjust the width and height to be lower than 128px while perserving the aspect ratio (for icons)
|
||||
if ($mode == 'icons')
|
||||
// adjust the width and height to be lower than 128px while perserving the aspect ratio (for icons)
|
||||
if ($mode == 'icons')
|
||||
{
|
||||
if ($img_size[0] > 127 && $img_size[0] > $img_size[1])
|
||||
{
|
||||
$img_size[1] = (int) ($img_size[1] * (127 / $img_size[0]));
|
||||
$img_size[0] = 127;
|
||||
}
|
||||
else if ($img_size[1] > 127)
|
||||
{
|
||||
$img_size[0] = (int) ($img_size[0] * (127 / $img_size[1]));
|
||||
$img_size[1] = 127;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($img_size[0] > 127 && $img_size[0] > $img_size[1])
|
||||
{
|
||||
$img_size[1] = (int) ($img_size[1] * (127 / $img_size[0]));
|
||||
$img_size[0] = 127;
|
||||
}
|
||||
else if ($img_size[1] > 127)
|
||||
{
|
||||
$img_size[0] = (int) ($img_size[0] * (127 / $img_size[1]));
|
||||
$img_size[1] = 127;
|
||||
}
|
||||
// getimagesize can't read the dimensions of the SVG files
|
||||
// https://bugs.php.net/bug.php?id=71517
|
||||
$xml_get = simplexml_load_file($phpbb_root_path . $img_path . '/' . $path . $img);
|
||||
|
||||
$svg_width = intval($xml_get['width']);
|
||||
$svg_height = intval($xml_get['height']);
|
||||
}
|
||||
|
||||
$_images[$path . $img]['file'] = $path . $img;
|
||||
$_images[$path . $img]['width'] = $img_size[0];
|
||||
$_images[$path . $img]['height'] = $img_size[1];
|
||||
|
||||
// Give SVG a fallback on failure
|
||||
$_images[$path . $img]['width'] = $img_size ? $img_size[0] : ($svg_width ?: 32);
|
||||
$_images[$path . $img]['height'] = $img_size ? $img_size[1] : ($svg_height ?: 32);
|
||||
}
|
||||
}
|
||||
unset($imglist);
|
||||
|
@@ -544,20 +544,13 @@ class acp_main
|
||||
$files_per_day = $total_files;
|
||||
}
|
||||
|
||||
if ($config['allow_attachments'] || $config['allow_pm_attach'])
|
||||
{
|
||||
$sql = 'SELECT COUNT(attach_id) AS total_orphan
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 1
|
||||
AND filetime < ' . (time() - 3*60*60);
|
||||
$result = $db->sql_query($sql);
|
||||
$total_orphan = (int) $db->sql_fetchfield('total_orphan');
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$total_orphan = false;
|
||||
}
|
||||
$sql = 'SELECT COUNT(attach_id) AS total_orphan
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 1
|
||||
AND filetime < ' . (time() - 3*60*60);
|
||||
$result = $db->sql_query($sql);
|
||||
$total_orphan = (int) $db->sql_fetchfield('total_orphan');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$dbsize = get_database_size();
|
||||
|
||||
@@ -575,7 +568,6 @@ class acp_main
|
||||
'DBSIZE' => $dbsize,
|
||||
'UPLOAD_DIR_SIZE' => $upload_dir_size,
|
||||
'TOTAL_ORPHAN' => $total_orphan,
|
||||
'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true,
|
||||
'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'],
|
||||
'DATABASE_INFO' => $db->sql_server_info(),
|
||||
'PHP_VERSION_INFO' => PHP_VERSION,
|
||||
|
@@ -55,8 +55,8 @@ class acp_ranks
|
||||
$min_posts = ($special_rank) ? 0 : max(0, $request->variable('min_posts', 0));
|
||||
$rank_image = $request->variable('rank_image', '');
|
||||
|
||||
// The rank image has to be a jpg, gif or png
|
||||
if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg)$#i', $rank_image))
|
||||
// The rank image has to be a jp(e)g, gif, png, svg or webp
|
||||
if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg|\.svg|\.webp)$#i', $rank_image))
|
||||
{
|
||||
$rank_image = '';
|
||||
}
|
||||
|
@@ -322,9 +322,9 @@ class acp_search
|
||||
{
|
||||
$sql = 'SELECT post_id, poster_id, forum_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_id >= ' . (int) ($post_counter + 1) . '
|
||||
AND post_id <= ' . (int) ($post_counter + $this->batch_size);
|
||||
$result = $db->sql_query($sql);
|
||||
WHERE post_id > ' . (int) $post_counter . '
|
||||
ORDER BY post_id ASC';
|
||||
$result = $db->sql_query_limit($sql, $this->batch_size);
|
||||
|
||||
$ids = $posters = $forum_ids = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
@@ -339,14 +339,13 @@ class acp_search
|
||||
if (count($ids))
|
||||
{
|
||||
$this->search->index_remove($ids, $posters, $forum_ids);
|
||||
$post_counter = $ids[count($ids) - 1];
|
||||
}
|
||||
|
||||
$post_counter += $this->batch_size;
|
||||
}
|
||||
// save the current state
|
||||
$this->save_state();
|
||||
|
||||
if ($post_counter <= $this->max_post_id)
|
||||
if ($post_counter < $this->max_post_id)
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
@@ -393,9 +392,9 @@ class acp_search
|
||||
{
|
||||
$sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_id >= ' . (int) ($post_counter + 1) . '
|
||||
AND post_id <= ' . (int) ($post_counter + $this->batch_size);
|
||||
$result = $db->sql_query($sql);
|
||||
WHERE post_id > ' . (int) $post_counter . '
|
||||
ORDER BY post_id ASC';
|
||||
$result = $db->sql_query_limit($sql, $this->batch_size);
|
||||
|
||||
$buffer = $db->sql_buffer_nested_transactions();
|
||||
|
||||
@@ -416,13 +415,12 @@ class acp_search
|
||||
$this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);
|
||||
}
|
||||
$row_count++;
|
||||
$post_counter = $row['post_id'];
|
||||
}
|
||||
if (!$buffer)
|
||||
{
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$post_counter += $this->batch_size;
|
||||
}
|
||||
// save the current state
|
||||
$this->save_state();
|
||||
@@ -434,7 +432,7 @@ class acp_search
|
||||
$this->search->tidy();
|
||||
$config['num_posts'] = $num_posts;
|
||||
|
||||
if ($post_counter <= $this->max_post_id)
|
||||
if ($post_counter < $this->max_post_id)
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
|
@@ -28,7 +28,7 @@ if (!defined('IN_PHPBB'))
|
||||
*/
|
||||
|
||||
// phpBB Version
|
||||
@define('PHPBB_VERSION', '3.3.5-RC1');
|
||||
@define('PHPBB_VERSION', '3.3.6-RC1');
|
||||
|
||||
// QA-related
|
||||
// define('PHPBB_QA', 1);
|
||||
|
@@ -168,8 +168,14 @@ class diff
|
||||
$final = $edit->final;
|
||||
|
||||
// We can simplify one case where the array is usually supposed to be empty...
|
||||
if (count($orig) == 1 && trim($orig[0]) === '') $orig = array();
|
||||
if (count($final) == 1 && trim($final[0]) === '') $final = array();
|
||||
if (is_array($orig) && count($orig) == 1 && trim($orig[0]) === '')
|
||||
{
|
||||
$orig = array();
|
||||
}
|
||||
if (is_array($final) && count($final) == 1 && trim($final[0]) === '')
|
||||
{
|
||||
$final = array();
|
||||
}
|
||||
|
||||
if (!$orig && !$final)
|
||||
{
|
||||
|
@@ -263,49 +263,68 @@ function phpbb_version_compare($version1, $version2, $operator = null)
|
||||
// functions used for building option fields
|
||||
|
||||
/**
|
||||
* Pick a language, any language ...
|
||||
*/
|
||||
function language_select($default = '')
|
||||
* Pick a language, any language ...
|
||||
*
|
||||
* @param string $default Language ISO code to be selected by default in the dropdown list
|
||||
* @param array $langdata Language data in format of array(array('lang_iso' => string, lang_local_name => string), ...)
|
||||
*
|
||||
* @return string HTML options for language selection dropdown list.
|
||||
*/
|
||||
function language_select($default = '', array $langdata = [])
|
||||
{
|
||||
global $db;
|
||||
|
||||
$sql = 'SELECT lang_iso, lang_local_name
|
||||
FROM ' . LANG_TABLE . '
|
||||
ORDER BY lang_english_name';
|
||||
$result = $db->sql_query($sql);
|
||||
if (empty($langdata))
|
||||
{
|
||||
$sql = 'SELECT lang_iso, lang_local_name
|
||||
FROM ' . LANG_TABLE . '
|
||||
ORDER BY lang_english_name';
|
||||
$result = $db->sql_query($sql);
|
||||
$langdata = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$lang_options = '';
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
foreach ($langdata as $row)
|
||||
{
|
||||
$selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : '';
|
||||
$lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>';
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $lang_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a template/theme combo,
|
||||
*/
|
||||
function style_select($default = '', $all = false)
|
||||
* Pick a template/theme combo
|
||||
*
|
||||
* @param string $default Style ID to be selected by default in the dropdown list
|
||||
* @param bool $all Flag indicating if all styles data including inactive ones should be fetched
|
||||
* @param array $styledata Style data in format of array(array('style_id' => int, style_name => string), ...)
|
||||
*
|
||||
* @return string HTML options for style selection dropdown list.
|
||||
*/
|
||||
function style_select($default = '', $all = false, array $styledata = [])
|
||||
{
|
||||
global $db;
|
||||
|
||||
$sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
|
||||
$sql = 'SELECT style_id, style_name
|
||||
FROM ' . STYLES_TABLE . "
|
||||
$sql_where
|
||||
ORDER BY style_name";
|
||||
$result = $db->sql_query($sql);
|
||||
if (empty($styledata))
|
||||
{
|
||||
$sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
|
||||
$sql = 'SELECT style_id, style_name
|
||||
FROM ' . STYLES_TABLE . "
|
||||
$sql_where
|
||||
ORDER BY style_name";
|
||||
$result = $db->sql_query($sql);
|
||||
$styledata = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$style_options = '';
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
foreach ($styledata as $row)
|
||||
{
|
||||
$selected = ($row['style_id'] == $default) ? ' selected="selected"' : '';
|
||||
$style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>';
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $style_options;
|
||||
}
|
||||
|
@@ -479,7 +479,7 @@ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perm
|
||||
/**
|
||||
* Get physical file listing
|
||||
*/
|
||||
function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')
|
||||
function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png|svg|webp')
|
||||
{
|
||||
$matches = array($dir => array());
|
||||
|
||||
|
@@ -35,7 +35,7 @@ function phpbb_module_notes_url($mode, $module_row)
|
||||
}
|
||||
|
||||
global $user_id;
|
||||
return ($user_id) ? "&u=$user_id" : '';
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_warn_url($mode, $module_row)
|
||||
@@ -43,34 +43,18 @@ function phpbb_module_warn_url($mode, $module_row)
|
||||
if ($mode == 'front' || $mode == 'list')
|
||||
{
|
||||
global $forum_id;
|
||||
|
||||
return ($forum_id) ? "&f=$forum_id" : '';
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
if ($mode == 'warn_post')
|
||||
{
|
||||
global $forum_id, $post_id;
|
||||
|
||||
if ($post_id)
|
||||
{
|
||||
$url_extra = "&p=$post_id";
|
||||
}
|
||||
else if ($forum_id)
|
||||
{
|
||||
$url_extra = "&f=$forum_id";
|
||||
}
|
||||
else
|
||||
{
|
||||
$url_extra = '';
|
||||
}
|
||||
|
||||
return $url_extra;
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
else
|
||||
{
|
||||
global $user_id;
|
||||
|
||||
return ($user_id) ? "&u=$user_id" : '';
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,30 +83,34 @@ function phpbb_module_reports_url($mode, $module_row)
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_extra_url()
|
||||
/**
|
||||
* Generate URL parameters for MCP modules
|
||||
*
|
||||
* @param array $additional_parameters Array with additional parameters in format of ['key' => 'parameter_name']
|
||||
*
|
||||
* @return string String with URL parameters (empty string if not any)
|
||||
*/
|
||||
function phpbb_extra_url($additional_parameters = [])
|
||||
{
|
||||
global $forum_id, $topic_id, $post_id, $report_id, $user_id;
|
||||
$url_extra = [];
|
||||
$url_parameters = array_merge([
|
||||
'f' => 'forum_id',
|
||||
't' => 'topic_id',
|
||||
'p' => 'post_id',
|
||||
'r' => 'report_id',
|
||||
'u' => 'user_id',
|
||||
], $additional_parameters);
|
||||
|
||||
if ($post_id)
|
||||
foreach ($url_parameters as $key => $value)
|
||||
{
|
||||
$url_extra = "&p=$post_id";
|
||||
global $$value;
|
||||
if (isset($$value) && $parameter = $$value)
|
||||
{
|
||||
$url_extra[] = "$key=$parameter";
|
||||
}
|
||||
}
|
||||
else if ($topic_id)
|
||||
{
|
||||
$url_extra = "&t=$topic_id";
|
||||
}
|
||||
else if ($forum_id)
|
||||
{
|
||||
$url_extra = "&f=$forum_id";
|
||||
}
|
||||
else
|
||||
{
|
||||
$url_extra = '';
|
||||
}
|
||||
$url_extra .= ($user_id) ? "&u=$user_id" : '';
|
||||
$url_extra .= ($report_id) ? "&r=$report_id" : '';
|
||||
|
||||
return $url_extra;
|
||||
return implode('&', $url_extra);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1840,65 +1840,84 @@ class smtp_class
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given string for proper display in UTF-8.
|
||||
*
|
||||
* This version is using base64 encoded data. The downside of this
|
||||
* is if the mail client does not understand this encoding the user
|
||||
* is basically doomed with an unreadable subject.
|
||||
*
|
||||
* Please note that this version fully supports RFC 2045 section 6.8.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $eol End of line we are using (optional to be backwards compatible)
|
||||
*/
|
||||
* Encodes the given string for proper display in UTF-8 or US-ASCII.
|
||||
*
|
||||
* This version is based on iconv_mime_encode() implementation
|
||||
* from symfomy/polyfill-iconv
|
||||
* https://github.com/symfony/polyfill-iconv/blob/fd324208ec59a39ebe776e6e9ec5540ad4f40aaa/Iconv.php#L355
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $eol Lines delimiter (optional to be backwards compatible)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function mail_encode($str, $eol = "\r\n")
|
||||
{
|
||||
// Check if string contains ASCII only characters
|
||||
$is_ascii = strlen($str) === utf8_strlen($str);
|
||||
|
||||
// Define start delimimter, end delimiter and spacer
|
||||
$scheme = $is_ascii ? 'Q' : 'B';
|
||||
|
||||
// Define start delimiter, end delimiter
|
||||
// Use the Quoted-Printable encoding for ASCII strings to avoid unnecessary encoding in Base64
|
||||
$start = $is_ascii ? "=?US-ASCII?Q?" : "=?UTF-8?B?";
|
||||
$end = "?=";
|
||||
$delimiter = "$eol ";
|
||||
$start = '=?' . ($is_ascii ? 'US-ASCII' : 'UTF-8') . '?' . $scheme . '?';
|
||||
$end = '?=';
|
||||
|
||||
// Maximum encoded-word length is 75 as per RFC 2047 section 2.
|
||||
// $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $delimiter . $end)!!!
|
||||
$split_length = 75 - strlen($start . $delimiter . $end);
|
||||
// $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $eol . $end)!!!
|
||||
$split_length = 75 - strlen($start . $eol . $end);
|
||||
$split_length = $split_length - $split_length % 4;
|
||||
|
||||
// Use the Quoted-Printable encoding for ASCII strings to avoid unnecessary encoding in Base64
|
||||
$encoded_str = $is_ascii ? quoted_printable_encode($str) : base64_encode($str);
|
||||
$line_length = strlen($start) + strlen($end);
|
||||
$line_offset = strlen($start) + 1;
|
||||
$line_data = '';
|
||||
|
||||
// If encoded string meets the limits, we just return with the correct data.
|
||||
if (strlen($encoded_str) <= $split_length)
|
||||
$is_quoted_printable = 'Q' === $scheme;
|
||||
|
||||
preg_match_all('/./us', $str, $chars);
|
||||
$chars = $chars[0] ?? [];
|
||||
|
||||
$str = [];
|
||||
foreach ($chars as $char)
|
||||
{
|
||||
return $start . $encoded_str . $end;
|
||||
}
|
||||
$encoded_char = $is_quoted_printable
|
||||
? $char = preg_replace_callback(
|
||||
'/[=_\?\x20\x00-\x1F\x80-\xFF]/',
|
||||
function ($matches)
|
||||
{
|
||||
$hex = dechex(ord($matches[0]));
|
||||
$hex = strlen($hex) == 1 ? "0$hex" : $hex;
|
||||
return '=' . strtoupper($hex);
|
||||
},
|
||||
$char
|
||||
)
|
||||
: base64_encode($line_data . $char);
|
||||
|
||||
// If there is only ASCII data, we just return what we want, correctly splitting the lines.
|
||||
if ($is_ascii)
|
||||
{
|
||||
return $start . implode($end . $delimiter . $start, str_split($encoded_str, $split_length)) . $end;
|
||||
}
|
||||
|
||||
// UTF-8 data, compose encoded lines
|
||||
$array = utf8_str_split($str);
|
||||
$str = '';
|
||||
|
||||
while (count($array))
|
||||
{
|
||||
$text = '';
|
||||
|
||||
while (count($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length)
|
||||
if (isset($encoded_char[$split_length - $line_length]))
|
||||
{
|
||||
$text .= array_shift($array);
|
||||
if (!$is_quoted_printable)
|
||||
{
|
||||
$line_data = base64_encode($line_data);
|
||||
}
|
||||
$str[] = $start . $line_data . $end;
|
||||
$line_length = $line_offset;
|
||||
$line_data = '';
|
||||
}
|
||||
|
||||
$str .= $start . base64_encode($text) . $end . $delimiter;
|
||||
$line_data .= $char;
|
||||
$is_quoted_printable && $line_length += strlen($char);
|
||||
}
|
||||
|
||||
return substr($str, 0, -strlen($delimiter));
|
||||
if ($line_data !== '')
|
||||
{
|
||||
if (!$is_quoted_printable)
|
||||
{
|
||||
$line_data = base64_encode($line_data);
|
||||
}
|
||||
$str[] = $start . $line_data . $end;
|
||||
}
|
||||
|
||||
return implode($eol . ' ', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1906,7 +1925,7 @@ function mail_encode($str, $eol = "\r\n")
|
||||
*/
|
||||
function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)
|
||||
{
|
||||
global $config, $phpbb_root_path, $phpEx;
|
||||
global $config, $phpbb_root_path, $phpEx, $phpbb_dispatcher;
|
||||
|
||||
// Convert Numeric Character References to UTF-8 chars (ie. Emojis)
|
||||
$subject = utf8_decode_ncr($subject);
|
||||
@@ -1935,8 +1954,54 @@ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)
|
||||
*/
|
||||
$additional_parameters = $config['email_force_sender'] ? '-f' . $config['board_email'] : '';
|
||||
|
||||
/**
|
||||
* Modify data before sending out emails with PHP's mail function
|
||||
*
|
||||
* @event core.phpbb_mail_before
|
||||
* @var string to The message recipient
|
||||
* @var string subject The message subject
|
||||
* @var string msg The message text
|
||||
* @var string headers The email headers
|
||||
* @var string eol The endline character
|
||||
* @var string additional_parameters The additional parameters
|
||||
* @since 3.3.6-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'to',
|
||||
'subject',
|
||||
'msg',
|
||||
'headers',
|
||||
'eol',
|
||||
'additional_parameters',
|
||||
];
|
||||
extract($phpbb_dispatcher->trigger_event('core.phpbb_mail_before', compact($vars)));
|
||||
|
||||
$result = mail($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers, $additional_parameters);
|
||||
|
||||
/**
|
||||
* Execute code after sending out emails with PHP's mail function
|
||||
*
|
||||
* @event core.phpbb_mail_after
|
||||
* @var string to The message recipient
|
||||
* @var string subject The message subject
|
||||
* @var string msg The message text
|
||||
* @var string headers The email headers
|
||||
* @var string eol The endline character
|
||||
* @var string additional_parameters The additional parameters
|
||||
* @var bool result True if the email was sent, false otherwise
|
||||
* @since 3.3.6-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'to',
|
||||
'subject',
|
||||
'msg',
|
||||
'headers',
|
||||
'eol',
|
||||
'additional_parameters',
|
||||
'result',
|
||||
];
|
||||
extract($phpbb_dispatcher->trigger_event('core.phpbb_mail_after', compact($vars)));
|
||||
|
||||
$collector->uninstall();
|
||||
$err_msg = $collector->format_errors();
|
||||
|
||||
|
@@ -662,7 +662,7 @@ class p_master
|
||||
// Add url_extra parameter to u_action url
|
||||
if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra'])
|
||||
{
|
||||
$this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra'];
|
||||
$this->module->u_action .= '&' . $this->module_ary[$this->active_module_row_id]['url_extra'];
|
||||
}
|
||||
|
||||
// Assign the module path for re-usage
|
||||
@@ -920,7 +920,7 @@ class p_master
|
||||
}
|
||||
|
||||
// Was not allowed in categories before - /*!$item_ary['cat'] && */
|
||||
$u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : '';
|
||||
$u_title .= (isset($item_ary['url_extra']) && $item_ary['url_extra']) ? '&' . $item_ary['url_extra'] : '';
|
||||
|
||||
// Only output a categories items if it's currently selected
|
||||
if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent)))
|
||||
|
@@ -813,20 +813,42 @@ function posting_gen_inline_attachments(&$attachment_data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate inline attachment entry
|
||||
*/
|
||||
function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true)
|
||||
* Generate inline attachment entry
|
||||
*
|
||||
* @param array $attachment_data The attachment data
|
||||
* @param string $filename_data The filename data (filecomment)
|
||||
* @param bool $show_attach_box Whether to show the attach box
|
||||
* @param mixed $forum_id The forum id to check or false if private message
|
||||
* @return int
|
||||
*/
|
||||
function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true, $forum_id = false)
|
||||
{
|
||||
global $template, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
|
||||
global $template, $cache, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
|
||||
|
||||
$allowed_attachments = array_keys($cache->obtain_attach_extensions($forum_id)['_allowed_']);
|
||||
|
||||
// Some default template variables
|
||||
$template->assign_vars(array(
|
||||
$default_vars = [
|
||||
'S_SHOW_ATTACH_BOX' => $show_attach_box,
|
||||
'S_HAS_ATTACHMENTS' => count($attachment_data),
|
||||
'FILESIZE' => $config['max_filesize'],
|
||||
'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '',
|
||||
'MAX_ATTACHMENT_FILESIZE' => $config['max_filesize'] > 0 ? $user->lang('MAX_ATTACHMENT_FILESIZE', get_formatted_filesize($config['max_filesize'])) : '',
|
||||
));
|
||||
'ALLOWED_ATTACHMENTS' => !empty($allowed_attachments) ? implode(',', $allowed_attachments) : '',
|
||||
];
|
||||
|
||||
/**
|
||||
* Modify default attachments template vars
|
||||
*
|
||||
* @event core.modify_default_attachments_template_vars
|
||||
* @var array allowed_attachments Array containing allowed attachments data
|
||||
* @var array default_vars Array containing default attachments template vars
|
||||
* @since 3.3.6-RC1
|
||||
*/
|
||||
$vars = ['allowed_attachments', 'default_vars'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.modify_default_attachments_template_vars', compact($vars)));
|
||||
|
||||
$template->assign_vars($default_vars);
|
||||
|
||||
if (count($attachment_data))
|
||||
{
|
||||
|
@@ -1752,7 +1752,8 @@ function validate_username($username, $allowed_username = false, $allow_all_name
|
||||
}
|
||||
|
||||
// ... fast checks first.
|
||||
if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username))
|
||||
if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username)
|
||||
|| preg_match('/[\x{180E}\x{2005}-\x{200D}\x{202F}\x{205F}\x{2060}\x{FEFF}]/u', $username))
|
||||
{
|
||||
return 'INVALID_CHARS';
|
||||
}
|
||||
|
@@ -159,33 +159,23 @@ class ucp_prefs
|
||||
phpbb_timezone_select($template, $user, $data['tz'], true);
|
||||
|
||||
// check if there are any user-selectable languages
|
||||
$sql = 'SELECT COUNT(lang_id) as languages_count
|
||||
FROM ' . LANG_TABLE;
|
||||
$sql = 'SELECT lang_iso, lang_local_name
|
||||
FROM ' . LANG_TABLE . '
|
||||
ORDER BY lang_english_name';
|
||||
$result = $db->sql_query($sql);
|
||||
if ($db->sql_fetchfield('languages_count') > 1)
|
||||
{
|
||||
$s_more_languages = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_more_languages = false;
|
||||
}
|
||||
$lang_row = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
$s_more_languages = count($lang_row) > 1;
|
||||
|
||||
// check if there are any user-selectable styles
|
||||
$sql = 'SELECT COUNT(style_id) as styles_count
|
||||
FROM ' . STYLES_TABLE . '
|
||||
WHERE style_active = 1';
|
||||
$sql = 'SELECT style_id, style_name
|
||||
FROM ' . STYLES_TABLE . '
|
||||
WHERE style_active = 1
|
||||
ORDER BY style_name';
|
||||
$result = $db->sql_query($sql);
|
||||
if ($db->sql_fetchfield('styles_count') > 1)
|
||||
{
|
||||
$s_more_styles = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_more_styles = false;
|
||||
}
|
||||
$styles_row = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
$s_more_styles = count($styles_row) > 1;
|
||||
|
||||
$template->assign_vars(array(
|
||||
'ERROR' => (count($error)) ? implode('<br />', $error) : '',
|
||||
@@ -205,11 +195,11 @@ class ucp_prefs
|
||||
'DEFAULT_DATEFORMAT' => $config['default_dateformat'],
|
||||
'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']),
|
||||
|
||||
'S_MORE_LANGUAGES' => $s_more_languages,
|
||||
'S_MORE_LANGUAGES' => $s_more_languages,
|
||||
'S_MORE_STYLES' => $s_more_styles,
|
||||
|
||||
'S_LANG_OPTIONS' => language_select($data['lang']),
|
||||
'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['user_style']),
|
||||
'S_LANG_OPTIONS' => language_select($data['lang'], $lang_row),
|
||||
'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['user_style'], false, $styles_row),
|
||||
'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false,
|
||||
'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false)
|
||||
);
|
||||
|
@@ -150,15 +150,11 @@ class ucp_register
|
||||
}
|
||||
|
||||
// Checking amount of available languages
|
||||
$sql = 'SELECT lang_id
|
||||
FROM ' . LANG_TABLE;
|
||||
$sql = 'SELECT lang_iso, lang_local_name
|
||||
FROM ' . LANG_TABLE . '
|
||||
ORDER BY lang_english_name';
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$lang_row = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$lang_row[] = $row;
|
||||
}
|
||||
$lang_row = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if ($coppa === false && $config['coppa_enable'])
|
||||
@@ -171,7 +167,7 @@ class ucp_register
|
||||
unset($now);
|
||||
|
||||
$template_vars = array(
|
||||
'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang) : '',
|
||||
'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang, $lang_row) : '',
|
||||
'L_COPPA_NO' => $user->lang('UCP_COPPA_BEFORE', $coppa_birthday),
|
||||
'L_COPPA_YES' => $user->lang('UCP_COPPA_ON_AFTER', $coppa_birthday),
|
||||
|
||||
@@ -186,7 +182,7 @@ class ucp_register
|
||||
else
|
||||
{
|
||||
$template_vars = array(
|
||||
'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang) : '',
|
||||
'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang, $lang_row) : '',
|
||||
'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()),
|
||||
|
||||
'S_SHOW_COPPA' => false,
|
||||
@@ -633,6 +629,14 @@ class ucp_register
|
||||
// Assign template vars for timezone select
|
||||
phpbb_timezone_select($template, $user, $data['tz'], true);
|
||||
|
||||
// Checking amount of available languages
|
||||
$sql = 'SELECT lang_iso, lang_local_name
|
||||
FROM ' . LANG_TABLE . '
|
||||
ORDER BY lang_english_name';
|
||||
$result = $db->sql_query($sql);
|
||||
$lang_row = (array) $db->sql_fetchrowset($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$template_vars = array(
|
||||
'USERNAME' => $data['username'],
|
||||
'PASSWORD' => $data['new_password'],
|
||||
@@ -643,7 +647,7 @@ class ucp_register
|
||||
'L_USERNAME_EXPLAIN' => $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])),
|
||||
'L_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars'])),
|
||||
|
||||
'S_LANG_OPTIONS' => language_select($data['lang']),
|
||||
'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($data['lang'], $lang_row) : '',
|
||||
'S_TZ_PRESELECT' => !$submit,
|
||||
'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false,
|
||||
'S_REGISTRATION' => true,
|
||||
|
@@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
|
||||
$convertor_data = array(
|
||||
'forum_name' => 'phpBB 2.0.x',
|
||||
'version' => '1.0.3',
|
||||
'phpbb_version' => '3.3.5',
|
||||
'phpbb_version' => '3.3.6',
|
||||
'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>',
|
||||
'dbms' => $dbms,
|
||||
'dbhost' => $dbhost,
|
||||
|
@@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli')
|
||||
define('IN_PHPBB', true);
|
||||
define('IN_INSTALL', true);
|
||||
define('PHPBB_ENVIRONMENT', 'production');
|
||||
define('PHPBB_VERSION', '3.3.5-RC1');
|
||||
define('PHPBB_VERSION', '3.3.6-RC1');
|
||||
$phpbb_root_path = __DIR__ . '/../';
|
||||
$phpEx = substr(strrchr(__FILE__, '.'), 1);
|
||||
|
||||
|
@@ -316,7 +316,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('update_hashes_lock
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.3.5-RC1');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.3.6-RC1');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400');
|
||||
|
||||
|
@@ -170,4 +170,5 @@ $lang = array_merge($lang, array(
|
||||
'UPLOAD_DIR_EXPLAIN' => 'Storage path for attachments. Please note that if you change this directory while already having uploaded attachments you need to manually copy the files to their new location.',
|
||||
'UPLOAD_ICON' => 'Upload icon',
|
||||
'UPLOAD_NOT_DIR' => 'The upload location you specified does not appear to be a directory.',
|
||||
'UPLOAD_POST_NOT_EXIST' => 'File “%1$s” can not be uploaded to post number %2$d as the post does not exist.',
|
||||
));
|
||||
|
@@ -77,5 +77,6 @@ $lang = array_merge($lang, array(
|
||||
'PARENT_MODULE_FIND_ERROR' => 'Unable to determine the parent module identifier: %s',
|
||||
'PERMISSION_NOT_EXIST' => 'The permission setting "%s" unexpectedly does not exist.',
|
||||
|
||||
'ROLE_ASSIGNED_NOT_EXIST' => 'The permission role assigned to group "%1$s" unexpectedly does not exist. Role id: "%2$s"',
|
||||
'ROLE_NOT_EXIST' => 'The permission role "%s" unexpectedly does not exist.',
|
||||
));
|
||||
|
@@ -170,9 +170,9 @@ class db extends config
|
||||
if (!isset($this->config[$key]))
|
||||
{
|
||||
$sql = 'INSERT INTO ' . $this->table . ' ' . $this->db->sql_build_array('INSERT', array(
|
||||
'config_name' => $this->db->sql_escape($key),
|
||||
'config_value' => $this->db->sql_escape($new_value),
|
||||
'is_dynamic' => ($use_cache) ? 0 : 1));
|
||||
'config_name' => $key,
|
||||
'config_value' => $new_value,
|
||||
'is_dynamic' => $use_cache ? 0 : 1));
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
||||
|
@@ -390,7 +390,7 @@ class sqlite3 extends \phpbb\db\driver\driver
|
||||
{
|
||||
$html_table = false;
|
||||
|
||||
if ($result = $this->dbo->query("EXPLAIN QUERY PLAN $explain_query"))
|
||||
if ($result = @$this->dbo->query("EXPLAIN QUERY PLAN $explain_query"))
|
||||
{
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
|
74
phpBB/phpbb/db/migration/data/v33x/remove_orphaned_roles.php
Normal file
74
phpBB/phpbb/db/migration/data/v33x/remove_orphaned_roles.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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\v33x;
|
||||
|
||||
class remove_orphaned_roles extends \phpbb\db\migration\migration
|
||||
{
|
||||
static public function depends_on()
|
||||
{
|
||||
return ['\phpbb\db\migration\data\v33x\v335'];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['custom', [[$this, 'acl_remove_orphaned_roles']]],
|
||||
];
|
||||
}
|
||||
|
||||
public function acl_remove_orphaned_roles()
|
||||
{
|
||||
$role_ids = [];
|
||||
|
||||
$sql = 'SELECT auth_role_id
|
||||
FROM ' . ACL_GROUPS_TABLE . '
|
||||
WHERE auth_role_id <> 0
|
||||
AND forum_id = 0';
|
||||
$result = $this->db->sql_query($sql);
|
||||
$auth_role_ids = array_keys($this->db->sql_fetchrowset($result));
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (count($auth_role_ids))
|
||||
{
|
||||
$sql = 'SELECT role_id
|
||||
FROM ' . ACL_ROLES_TABLE . '
|
||||
WHERE ' . $this->db->sql_in_set('role_id', $auth_role_ids);
|
||||
$result = $this->db->sql_query($sql);
|
||||
$role_ids = array_keys($this->db->sql_fetchrowset($result));
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$non_existent_role_ids = array_diff($auth_role_ids, $role_ids);
|
||||
|
||||
// Nothing to do, there are no non-existent roles assigned to groups
|
||||
if (empty($non_existent_role_ids))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove assigned non-existent roles from users and groups
|
||||
$sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
|
||||
WHERE ' . $this->db->sql_in_set('auth_role_id', $non_existent_role_ids);
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
|
||||
WHERE ' . $this->db->sql_in_set('auth_role_id', $non_existent_role_ids);
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$auth = new \phpbb\auth\auth();
|
||||
$auth->acl_clear_prefetch();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v335.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v335.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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\v33x;
|
||||
|
||||
class v335 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.5', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v335rc1',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.5']],
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v336rc1.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v336rc1.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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\v33x;
|
||||
|
||||
class v336rc1 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.6-RC1', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\remove_orphaned_roles',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.6-RC1']],
|
||||
];
|
||||
}
|
||||
}
|
@@ -21,6 +21,9 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
/** @var \phpbb\auth\auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var \includes\acp\auth\auth_admin */
|
||||
protected $auth_admin;
|
||||
|
||||
/** @var \phpbb\cache\service */
|
||||
protected $cache;
|
||||
|
||||
@@ -49,6 +52,12 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
$this->auth = $auth;
|
||||
$this->phpbb_root_path = $phpbb_root_path;
|
||||
$this->php_ext = $php_ext;
|
||||
|
||||
if (!class_exists('auth_admin'))
|
||||
{
|
||||
include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
|
||||
}
|
||||
$this->auth_admin = new \auth_admin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,12 +127,6 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
// We've added permissions, so set to true to notify the user.
|
||||
$this->permissions_added = true;
|
||||
|
||||
if (!class_exists('auth_admin'))
|
||||
{
|
||||
include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
|
||||
}
|
||||
$auth_admin = new \auth_admin();
|
||||
|
||||
// We have to add a check to see if the !$global (if global, local, and if local, global) permission already exists. If it does, acl_add_option currently has a bug which would break the ACL system, so we are having a work-around here.
|
||||
if ($this->exists($auth_option, !$global))
|
||||
{
|
||||
@@ -140,19 +143,19 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
{
|
||||
if ($global)
|
||||
{
|
||||
$auth_admin->acl_add_option(array('global' => array($auth_option)));
|
||||
$this->auth_admin->acl_add_option(array('global' => array($auth_option)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$auth_admin->acl_add_option(array('local' => array($auth_option)));
|
||||
$this->auth_admin->acl_add_option(array('local' => array($auth_option)));
|
||||
}
|
||||
}
|
||||
|
||||
// The permission has been added, now we can copy it if needed
|
||||
if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from]))
|
||||
if ($copy_from && isset($this->auth_admin->acl_options['id'][$copy_from]))
|
||||
{
|
||||
$old_id = $auth_admin->acl_options['id'][$copy_from];
|
||||
$new_id = $auth_admin->acl_options['id'][$auth_option];
|
||||
$old_id = $this->auth_admin->acl_options['id'][$copy_from];
|
||||
$new_id = $this->auth_admin->acl_options['id'][$auth_option];
|
||||
|
||||
$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE);
|
||||
|
||||
@@ -177,7 +180,7 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
}
|
||||
}
|
||||
|
||||
$auth_admin->acl_clear_prefetch();
|
||||
$this->auth_admin->acl_clear_prefetch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +294,8 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
|
||||
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
return $this->db->sql_nextid();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,6 +332,66 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the role type
|
||||
$sql = 'SELECT role_type
|
||||
FROM ' . ACL_ROLES_TABLE . '
|
||||
WHERE role_id = ' . (int) $role_id;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$role_type = $this->db->sql_fetchfield('role_type');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Get complete auth array
|
||||
$sql = 'SELECT auth_option, auth_option_id
|
||||
FROM ' . ACL_OPTIONS_TABLE . "
|
||||
WHERE auth_option " . $this->db->sql_like_expression($role_type . $this->db->get_any_char());
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
$auth_settings = [];
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$auth_settings[$row['auth_option']] = ACL_NO;
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Get the role auth settings we need to re-set...
|
||||
$sql = 'SELECT o.auth_option, r.auth_setting
|
||||
FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o
|
||||
WHERE o.auth_option_id = r.auth_option_id
|
||||
AND r.role_id = ' . (int) $role_id;
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$auth_settings[$row['auth_option']] = $row['auth_setting'];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Get role assignments
|
||||
$hold_ary = $this->auth_admin->get_role_mask($role_id);
|
||||
|
||||
// Re-assign permissions
|
||||
foreach ($hold_ary as $forum_id => $forum_ary)
|
||||
{
|
||||
if (isset($forum_ary['users']))
|
||||
{
|
||||
$this->auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
|
||||
}
|
||||
|
||||
if (isset($forum_ary['groups']))
|
||||
{
|
||||
$this->auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove role from users and groups just to be sure (happens through acl_set)
|
||||
$sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
|
||||
WHERE auth_role_id = ' . $role_id;
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
|
||||
WHERE auth_role_id = ' . $role_id;
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
|
||||
WHERE role_id = ' . $role_id;
|
||||
$this->db->sql_query($sql);
|
||||
@@ -425,6 +490,11 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
WHERE role_id = ' . $role_id;
|
||||
$this->db->sql_query($sql);
|
||||
$role_data = $this->db->sql_fetchrow();
|
||||
if (!$role_data)
|
||||
{
|
||||
throw new \phpbb\db\migration\exception('ROLE_ASSIGNED_NOT_EXIST', $name, $role_id);
|
||||
}
|
||||
|
||||
$role_name = $role_data['role_name'];
|
||||
$role_type = $role_data['role_type'];
|
||||
|
||||
@@ -571,6 +641,10 @@ class permission implements \phpbb\db\migration\tool\tool_interface
|
||||
WHERE role_id = ' . $role_id;
|
||||
$this->db->sql_query($sql);
|
||||
$role_name = $this->db->sql_fetchfield('role_name');
|
||||
if (!$role_name)
|
||||
{
|
||||
throw new \phpbb\db\migration\exception('ROLE_ASSIGNED_NOT_EXIST', $name, $role_id);
|
||||
}
|
||||
|
||||
return $this->permission_unset($role_name, $auth_option, 'role');
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ class container_configuration implements ConfigurationInterface
|
||||
->booleanNode('sql_explain')->defaultValue(false)->end()
|
||||
->booleanNode('memory')->defaultValue(false)->end()
|
||||
->booleanNode('show_errors')->defaultValue(false)->end()
|
||||
->booleanNode('error_handler')->defaultValue(false)->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('twig')
|
||||
|
@@ -30,9 +30,11 @@ class manager
|
||||
protected $cache;
|
||||
protected $php_ext;
|
||||
protected $extensions;
|
||||
protected $recently_changed_ext_status;
|
||||
protected $extension_table;
|
||||
protected $phpbb_root_path;
|
||||
protected $cache_name;
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Creates a manager and loads information from database
|
||||
@@ -47,7 +49,7 @@ class manager
|
||||
* @param \phpbb\cache\service $cache A cache instance or null
|
||||
* @param string $cache_name The name of the cache variable, defaults to _ext
|
||||
*/
|
||||
public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\service $cache = null, $cache_name = '_ext')
|
||||
public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\routing\router $router, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\service $cache = null, $cache_name = '_ext')
|
||||
{
|
||||
$this->cache = $cache;
|
||||
$this->cache_name = $cache_name;
|
||||
@@ -56,6 +58,7 @@ class manager
|
||||
$this->db = $db;
|
||||
$this->extension_table = $extension_table;
|
||||
$this->filesystem = $filesystem;
|
||||
$this->router = $router;
|
||||
$this->phpbb_root_path = $phpbb_root_path;
|
||||
$this->php_ext = $php_ext;
|
||||
|
||||
@@ -238,6 +241,12 @@ class manager
|
||||
'ext_state' => serialize($state),
|
||||
);
|
||||
|
||||
if ($active)
|
||||
{
|
||||
$this->recently_changed_ext_status[$name] = false;
|
||||
$this->router->without_cache();
|
||||
}
|
||||
|
||||
$this->update_state($name, $extension_data, $this->is_configured($name) ? 'update' : 'insert');
|
||||
|
||||
if ($active)
|
||||
@@ -287,6 +296,12 @@ class manager
|
||||
$state = $extension->disable_step($old_state);
|
||||
$active = ($state !== false);
|
||||
|
||||
if (!$active)
|
||||
{
|
||||
$this->recently_changed_ext_status[$name] = true;
|
||||
$this->router->without_cache();
|
||||
}
|
||||
|
||||
$extension_data = array(
|
||||
'ext_active' => $active,
|
||||
'ext_state' => serialize($state),
|
||||
@@ -499,6 +514,13 @@ class manager
|
||||
*/
|
||||
public function is_enabled($name)
|
||||
{
|
||||
// The extension has just been enabled and so is not loaded. When asking if it is enabled or
|
||||
// not we should answer no to stay consistent with the status at the beginning of the request.
|
||||
if (isset($this->recently_changed_ext_status[$name]))
|
||||
{
|
||||
return $this->recently_changed_ext_status[$name];
|
||||
}
|
||||
|
||||
return isset($this->extensions[$name]['ext_active']) && $this->extensions[$name]['ext_active'];
|
||||
}
|
||||
|
||||
@@ -510,6 +532,13 @@ class manager
|
||||
*/
|
||||
public function is_disabled($name)
|
||||
{
|
||||
// The extension has just been disabled and so is still loaded. When asking if it is disabled or
|
||||
// not we should answer yes to stay consistent with the status at the beginning of the request.
|
||||
if (isset($this->recently_changed_ext_status[$name]))
|
||||
{
|
||||
return $this->recently_changed_ext_status[$name];
|
||||
}
|
||||
|
||||
return isset($this->extensions[$name]['ext_active']) && !$this->extensions[$name]['ext_active'];
|
||||
}
|
||||
|
||||
|
@@ -163,7 +163,6 @@ class extension_guesser extends guesser_base
|
||||
'ivr' => 'i-world/i-vrml',
|
||||
'ivy' => 'application/x-livescreen',
|
||||
'jam' => 'audio/x-jam',
|
||||
'jav' => 'text/plain',
|
||||
'jav' => 'text/x-java-source',
|
||||
'java' => 'text/x-java-source',
|
||||
'jcm' => 'application/x-java-commerce',
|
||||
|
@@ -255,9 +255,36 @@ class manager
|
||||
'ignore_users' => array(),
|
||||
), $options);
|
||||
|
||||
$notified_users = [];
|
||||
$add_notifications_override = false;
|
||||
|
||||
/**
|
||||
* Get notification data before find_users_for_notification() execute
|
||||
*
|
||||
* @event core.notification_manager_add_notifications_before
|
||||
* @var bool add_notifications_override Flag indicating whether function should return after event
|
||||
* @var array|string notification_type_name Type identifier or array of item types
|
||||
* @var string data Data specific for this notification type that will be inserted
|
||||
* @var array notified_users Array of notified users
|
||||
* @var string options Optional options to control what notifications are loaded
|
||||
* @since 3.3.6-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'add_notifications_override',
|
||||
'notification_type_name',
|
||||
'data',
|
||||
'notified_users',
|
||||
'options',
|
||||
];
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.notification_manager_add_notifications_before', compact($vars)));
|
||||
|
||||
if ($add_notifications_override)
|
||||
{
|
||||
return $notified_users;
|
||||
}
|
||||
|
||||
if (is_array($notification_type_name))
|
||||
{
|
||||
$notified_users = array();
|
||||
$temp_options = $options;
|
||||
|
||||
foreach ($notification_type_name as $type)
|
||||
|
@@ -45,7 +45,7 @@ class argon2i extends base_native
|
||||
$this->memory_cost = max($memory_cost, defined('PASSWORD_ARGON2_DEFAULT_MEMORY_COST') ? PASSWORD_ARGON2_DEFAULT_MEMORY_COST : 65536);
|
||||
$this->time_cost = max($time_cost, defined('PASSWORD_ARGON2_DEFAULT_TIME_COST') ? PASSWORD_ARGON2_DEFAULT_TIME_COST : 4);
|
||||
$this->threads = (defined('PASSWORD_ARGON2_PROVIDER') && PASSWORD_ARGON2_PROVIDER == 'sodium') ?
|
||||
PASSWORD_ARGON2_DEFAULT_THREADS : max($threads, defined('PASSWORD_ARGON2_DEFAULT_THREADS') ? PASSWORD_ARGON2_DEFAULT_THREADS : 1);
|
||||
1 : max($threads, defined('PASSWORD_ARGON2_DEFAULT_THREADS') ? PASSWORD_ARGON2_DEFAULT_THREADS : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -80,6 +80,11 @@ class router implements RouterInterface
|
||||
*/
|
||||
protected $cache_dir;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $use_cache;
|
||||
|
||||
/**
|
||||
* Construct method
|
||||
*
|
||||
@@ -97,6 +102,7 @@ class router implements RouterInterface
|
||||
$this->php_ext = $php_ext;
|
||||
$this->context = new RequestContext();
|
||||
$this->cache_dir = $cache_dir;
|
||||
$this->use_cache = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,6 +182,22 @@ class router implements RouterInterface
|
||||
return $this->get_matcher()->match($pathinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the use of a cached URL generator and matcher
|
||||
*/
|
||||
public function with_cache()
|
||||
{
|
||||
$this->use_cache = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the use of a cached URL generator and matcher
|
||||
*/
|
||||
public function without_cache()
|
||||
{
|
||||
$this->use_cache = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UrlMatcher instance associated with this Router.
|
||||
*
|
||||
@@ -198,6 +220,12 @@ class router implements RouterInterface
|
||||
*/
|
||||
protected function create_dumped_url_matcher()
|
||||
{
|
||||
if (!$this->use_cache)
|
||||
{
|
||||
$this->create_new_url_matcher();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$cache = new ConfigCache("{$this->cache_dir}url_matcher.{$this->php_ext}", defined('DEBUG'));
|
||||
@@ -253,6 +281,12 @@ class router implements RouterInterface
|
||||
*/
|
||||
protected function create_dumped_url_generator()
|
||||
{
|
||||
if (!$this->use_cache)
|
||||
{
|
||||
$this->create_new_url_generator();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$cache = new ConfigCache("{$this->cache_dir}url_generator.{$this->php_ext}", defined('DEBUG'));
|
||||
|
@@ -568,8 +568,8 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
);
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_keywords_main_query_before', compact($vars)));
|
||||
|
||||
$sql_select = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : '';
|
||||
$sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';
|
||||
$sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';
|
||||
$sql_select .= $sort_by_sql[$sort_key] ? ", {$sort_by_sql[$sort_key]}" : '';
|
||||
$sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : '';
|
||||
$field = ($type == 'posts') ? 'post_id' : 'topic_id';
|
||||
if (count($author_ary) && $author_name)
|
||||
@@ -610,11 +610,10 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
// if the total result count is not cached yet, retrieve it from the db
|
||||
if (!$result_count && count($id_ary))
|
||||
{
|
||||
$sql_found_rows = 'SELECT FOUND_ROWS() as result_count';
|
||||
$sql_found_rows = str_replace("SELECT $sql_select", "SELECT COUNT(*) as result_count", $sql);
|
||||
$result = $this->db->sql_query($sql_found_rows);
|
||||
$result_count = (int) $this->db->sql_fetchfield('result_count');
|
||||
$this->db->sql_freeresult($result);
|
||||
@@ -828,12 +827,13 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_author_query_before', compact($vars)));
|
||||
|
||||
// If the cache was completely empty count the results
|
||||
$calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS ';
|
||||
$sql_select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';
|
||||
$sql_select .= $sort_by_sql[$sort_key] ? ", {$sort_by_sql[$sort_key]}" : '';
|
||||
|
||||
// Build the query for really selecting the post_ids
|
||||
if ($type == 'posts')
|
||||
{
|
||||
$sql = "SELECT {$calc_results}p.post_id
|
||||
$sql = "SELECT $sql_select
|
||||
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
|
||||
WHERE $sql_author
|
||||
$sql_topic_id
|
||||
@@ -847,7 +847,7 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT {$calc_results}t.topic_id
|
||||
$sql = "SELECT $sql_select
|
||||
FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
|
||||
WHERE $sql_author
|
||||
$sql_topic_id
|
||||
@@ -857,7 +857,7 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
AND t.topic_id = p.topic_id
|
||||
$sql_sort_join
|
||||
$sql_time
|
||||
GROUP BY t.topic_id
|
||||
GROUP BY $sql_select
|
||||
ORDER BY $sql_sort";
|
||||
$field = 'topic_id';
|
||||
}
|
||||
@@ -874,9 +874,10 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
// retrieve the total result count if needed
|
||||
if (!$result_count)
|
||||
{
|
||||
$sql_found_rows = 'SELECT FOUND_ROWS() as result_count';
|
||||
$sql_found_rows = str_replace("SELECT $sql_select", "SELECT COUNT(*) as result_count", $sql);
|
||||
$result = $this->db->sql_query($sql_found_rows);
|
||||
$result_count = (int) $this->db->sql_fetchfield('result_count');
|
||||
$result_count = ($type == 'posts') ? (int) $this->db->sql_fetchfield('result_count') : count($this->db->sql_fetchrowset($result));
|
||||
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$result_count)
|
||||
|
@@ -253,6 +253,16 @@ class fulltext_native extends \phpbb\search\base
|
||||
$keywords[$i] = ' ';
|
||||
break;
|
||||
case '-':
|
||||
// Ignore hyphen if followed by a space
|
||||
if (isset($keywords[$i + 1]) && $keywords[$i + 1] == ' ')
|
||||
{
|
||||
$keywords[$i] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$space = $keywords[$i];
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
$space = $keywords[$i];
|
||||
break;
|
||||
@@ -898,9 +908,6 @@ class fulltext_native extends \phpbb\search\base
|
||||
switch ($this->db->get_sql_layer())
|
||||
{
|
||||
case 'mysqli':
|
||||
|
||||
// 3.x does not support SQL_CALC_FOUND_ROWS
|
||||
// $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT'];
|
||||
$is_mysql = true;
|
||||
|
||||
break;
|
||||
@@ -958,16 +965,10 @@ class fulltext_native extends \phpbb\search\base
|
||||
);
|
||||
}
|
||||
|
||||
// if using mysql and the total result count is not calculated yet, get it from the db
|
||||
if (!$total_results && $is_mysql)
|
||||
{
|
||||
// Also count rows for the query as if there was not LIMIT. Add SQL_CALC_FOUND_ROWS to SQL
|
||||
$sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT'];
|
||||
}
|
||||
|
||||
$sql_array['WHERE'] = implode(' AND ', $sql_where);
|
||||
$sql_array['GROUP_BY'] = ($group_by) ? (($type == 'posts') ? 'p.post_id' : 'p.topic_id') . ', ' . $sort_by_sql[$sort_key] : '';
|
||||
$sql_array['ORDER_BY'] = $sql_sort;
|
||||
$sql_array['SELECT'] .= $sort_by_sql[$sort_key] ? ", {$sort_by_sql[$sort_key]}" : '';
|
||||
|
||||
unset($sql_where, $sql_sort, $group_by);
|
||||
|
||||
@@ -980,10 +981,10 @@ class fulltext_native extends \phpbb\search\base
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// If using mysql and the total result count is not calculated yet, get it from the db
|
||||
if (!$total_results && $is_mysql)
|
||||
{
|
||||
// Get the number of results as calculated by MySQL
|
||||
$sql_count = 'SELECT FOUND_ROWS() as total_results';
|
||||
$sql_count = str_replace("SELECT {$sql_array['SELECT']}", "SELECT COUNT(DISTINCT {$sql_array['SELECT']}) as total_results", $sql);
|
||||
$result = $this->db->sql_query($sql_count);
|
||||
$total_results = (int) $this->db->sql_fetchfield('total_results');
|
||||
$this->db->sql_freeresult($result);
|
||||
@@ -1005,7 +1006,6 @@ class fulltext_native extends \phpbb\search\base
|
||||
$id_ary[] = (int) $row[(($type == 'posts') ? 'post_id' : 'topic_id')];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
}
|
||||
|
||||
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
|
||||
@@ -1137,6 +1137,7 @@ class fulltext_native extends \phpbb\search\base
|
||||
}
|
||||
|
||||
$select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';
|
||||
$select .= $sort_by_sql[$sort_key] ? ", {$sort_by_sql[$sort_key]}" : '';
|
||||
$is_mysql = false;
|
||||
|
||||
/**
|
||||
@@ -1192,7 +1193,6 @@ class fulltext_native extends \phpbb\search\base
|
||||
switch ($this->db->get_sql_layer())
|
||||
{
|
||||
case 'mysqli':
|
||||
// $select = 'SQL_CALC_FOUND_ROWS ' . $select;
|
||||
$is_mysql = true;
|
||||
break;
|
||||
|
||||
@@ -1285,15 +1285,9 @@ class fulltext_native extends \phpbb\search\base
|
||||
|
||||
if (!$total_results && $is_mysql)
|
||||
{
|
||||
// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
|
||||
$sql_calc = str_replace('SELECT ' . $select, 'SELECT SQL_CALC_FOUND_ROWS ' . $select, $sql);
|
||||
|
||||
$result = $this->db->sql_query($sql_calc);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$sql_count = 'SELECT FOUND_ROWS() as total_results';
|
||||
$sql_count = str_replace("SELECT $select", "SELECT COUNT(*) as total_results", $sql);
|
||||
$result = $this->db->sql_query($sql_count);
|
||||
$total_results = (int) $this->db->sql_fetchfield('total_results');
|
||||
$total_results = ($type == 'posts') ? (int) $this->db->sql_fetchfield('total_results') : count($this->db->sql_fetchrowset($result));
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$total_results)
|
||||
|
@@ -836,8 +836,9 @@ class fulltext_postgres extends \phpbb\search\base
|
||||
GROUP BY t.topic_id, $sort_by_sql[$sort_key]";
|
||||
}
|
||||
|
||||
$this->db->sql_query($sql_count);
|
||||
$result_count = (int) $this->db->sql_fetchfield('result_count');
|
||||
$result = $this->db->sql_query($sql_count);
|
||||
$result_count = ($type == 'posts') ? (int) $this->db->sql_fetchfield('result_count') : count($this->db->sql_fetchrowset($result));
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$result_count)
|
||||
{
|
||||
|
@@ -79,6 +79,8 @@ class extension extends \Twig\Extension\AbstractExtension
|
||||
new \Twig\TwigFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)),
|
||||
// @deprecated 3.2.0 Uses twig's JS escape method instead of addslashes
|
||||
new \Twig\TwigFilter('addslashes', 'addslashes'),
|
||||
new \Twig\TwigFilter('int', 'intval'),
|
||||
new \Twig\TwigFilter('float', 'floatval'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -87,24 +87,25 @@ switch ($mode)
|
||||
$post_id = $request->variable('p', 0);
|
||||
if ($post_id)
|
||||
{
|
||||
$topic_forum = array();
|
||||
$topic_forum = [];
|
||||
|
||||
$sql = 'SELECT t.topic_id, t.forum_id
|
||||
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
|
||||
WHERE p.post_id = ' . $post_id . '
|
||||
AND t.topic_id = p.topic_id';
|
||||
$result = $db->sql_query($sql);
|
||||
$topic_forum = $db->sql_fetchrow();
|
||||
$topic_id = (int) $topic_forum['topic_id'];
|
||||
$forum_id = (int) $topic_forum['forum_id'];
|
||||
$topic_forum = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
if (!$post_id || !$topic_id || !$forum_id)
|
||||
if (!$post_id || !$topic_forum)
|
||||
{
|
||||
$user->setup('posting');
|
||||
trigger_error('NO_POST');
|
||||
}
|
||||
|
||||
$topic_id = (int) $topic_forum['topic_id'];
|
||||
$forum_id = (int) $topic_forum['forum_id'];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2078,7 +2079,7 @@ if ($allowed)
|
||||
}
|
||||
|
||||
// Attachment entry
|
||||
posting_gen_attachment_entry($attachment_data, $filename_data, $allowed);
|
||||
posting_gen_attachment_entry($attachment_data, $filename_data, $allowed, $forum_id);
|
||||
|
||||
// Output page ...
|
||||
page_header($page_title);
|
||||
|
@@ -21,8 +21,8 @@
|
||||
# General Information about this style
|
||||
name = prosilver
|
||||
copyright = © phpBB Limited, 2007
|
||||
style_version = 3.3.5
|
||||
phpbb_version = 3.3.5
|
||||
style_version = 3.3.6
|
||||
phpbb_version = 3.3.6
|
||||
|
||||
# Defining a different template bitfield
|
||||
# template_bitfield = //g=
|
||||
|
@@ -71,7 +71,7 @@
|
||||
<dl>
|
||||
<dt><label for="lang">{L_DEST_LANG}{L_COLON}</label><br />
|
||||
<span>{L_DEST_LANG_EXPLAIN}</span></dt>
|
||||
<dd><select name="lang">{S_LANG_OPTIONS}</select></dd>
|
||||
<dd><select name="lang" id="lang">{S_LANG_OPTIONS}</select></dd>
|
||||
</dl>
|
||||
<!-- ENDIF -->
|
||||
<dl>
|
||||
|
@@ -39,7 +39,7 @@
|
||||
|
||||
(function(d) {
|
||||
var wf = d.createElement('script'), s = d.scripts[0];
|
||||
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
|
||||
wf.src = 'https://cdn.jsdelivr.net/npm/webfontloader@1.6.28/webfontloader.min.js';
|
||||
wf.async = true;
|
||||
s.parentNode.insertBefore(wf, s);
|
||||
})(document);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<dl>
|
||||
<dt><label for="fileupload">{L_FILENAME}{L_COLON}</label></dt>
|
||||
<dd>
|
||||
<input type="file" name="fileupload" id="fileupload" class="inputbox autowidth" />
|
||||
<input type="file" accept="{{ ALLOWED_ATTACHMENTS }}" name="fileupload" id="fileupload" class="inputbox autowidth" />
|
||||
<input type="submit" name="add_file" value="{L_ADD_FILE}" class="button2" onclick="upload = true;" />
|
||||
</dd>
|
||||
</dl>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
(function(d) {
|
||||
var wf = d.createElement('script'), s = d.scripts[0];
|
||||
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js';
|
||||
wf.src = 'https://cdn.jsdelivr.net/npm/webfontloader@1.6.28/webfontloader.min.js';
|
||||
wf.async = true;
|
||||
s.parentNode.insertBefore(wf, s);
|
||||
})(document);
|
||||
|
@@ -57,10 +57,12 @@
|
||||
<hr />
|
||||
|
||||
<!-- EVENT ucp_register_options_before -->
|
||||
{% if S_LANG_OPTIONS %}
|
||||
<dl>
|
||||
<dt><label for="lang">{L_LANGUAGE}{L_COLON}</label></dt>
|
||||
<dd><select name="lang" id="lang" onchange="change_language(this.value); return false;" tabindex="6" title="{L_LANGUAGE}">{S_LANG_OPTIONS}</select></dd>
|
||||
<dt><label for="lang">{{ lang('LANGUAGE') ~ lang('COLON') }}</label></dt>
|
||||
<dd><select name="lang" id="lang" onchange="change_language(this.value); return false;" tabindex="6" title="{{ lang('LANGUAGE') }}">{{ S_LANG_OPTIONS }}</select></dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
<!-- INCLUDE timezone_option.html -->
|
||||
|
||||
|
@@ -735,6 +735,10 @@ fieldset.polls dd div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.profile-rank img {
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
/* Post-profile avatars */
|
||||
.postprofile .has-avatar .avatar-container {
|
||||
margin-bottom: 3px;
|
||||
|
@@ -999,7 +999,7 @@ if (count($topic_list))
|
||||
'S_TOPIC_MOVED' => ($row['topic_status'] == ITEM_MOVED) ? true : false,
|
||||
|
||||
'U_NEWEST_POST' => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread' : false,
|
||||
'U_LAST_POST' => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'] : false,
|
||||
'U_LAST_POST' => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'] : false,
|
||||
'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
|
||||
'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
|
||||
'U_VIEW_TOPIC' => $view_topic_url,
|
||||
|
@@ -86,6 +86,17 @@ class phpbb_config_db_test extends phpbb_database_test_case
|
||||
$this->cache->checkVar($this, 'config', array('foo' => '23', 'foobar' => '5'));
|
||||
}
|
||||
|
||||
public function test_set_new_json()
|
||||
{
|
||||
$json_value = '{"menu":{"id":"file","value":"File"}}';
|
||||
$this->config->set('foobar_json', $json_value);
|
||||
$this->assertEquals($json_value, $this->config['foobar_json']);
|
||||
|
||||
// re-read config and populate cache
|
||||
$config2 = new \phpbb\config\db($this->db, $this->cache, 'phpbb_config');
|
||||
$this->cache->checkVar($this, 'config', ['foo' => '23', 'foobar_json' => $json_value]);
|
||||
}
|
||||
|
||||
public function test_set_new_uncached()
|
||||
{
|
||||
$this->config->set('foobar', '5', false);
|
||||
|
@@ -46,6 +46,13 @@ class phpbb_config_db_text_test extends phpbb_database_test_case
|
||||
$this->assertSame('phpbb', $this->config_text->get('barz'));
|
||||
}
|
||||
|
||||
public function test_set_new_get_json()
|
||||
{
|
||||
$json_value = '{"menu":{"id":"file","value":"File"}}';
|
||||
$this->config_text->set('foobar_json', $json_value);
|
||||
$this->assertEquals($json_value, $this->config_text->get('foobar_json'));
|
||||
}
|
||||
|
||||
public function test_set_replace_get()
|
||||
{
|
||||
$this->config_text->set('foo', '24');
|
||||
|
@@ -80,6 +80,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
|
||||
$this->db,
|
||||
$this->config,
|
||||
new phpbb\filesystem\filesystem(),
|
||||
new phpbb_mock_dummy_router(),
|
||||
'phpbb_ext',
|
||||
__DIR__ . '/../../phpBB/',
|
||||
'php',
|
||||
|
198
tests/dbal/migrator_tool_permission_role_test.php
Normal file
198
tests/dbal/migrator_tool_permission_role_test.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?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_migrator_tool_permission_role_test extends phpbb_database_test_case
|
||||
{
|
||||
/** @var \phpbb\auth\auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var \includes\acp\auth\auth_admin */
|
||||
protected $auth_admin;
|
||||
|
||||
/** @var \phpbb\db\migration\tool\permission */
|
||||
protected $tool;
|
||||
|
||||
public $group_ids = [
|
||||
'REGISTERED' => 2,
|
||||
'GLOBAL_MODERATORS' => 4,
|
||||
'ADMINISTRATORS' => 5,
|
||||
];
|
||||
|
||||
public $new_roles = [
|
||||
[
|
||||
'ROLE_ADMIN_NEW',
|
||||
'a_',
|
||||
'A new admin role',
|
||||
'a_new',
|
||||
],
|
||||
[
|
||||
'ROLE_MODERATOR_NEW',
|
||||
'm_',
|
||||
'A new mod role',
|
||||
'm_new',
|
||||
],
|
||||
[
|
||||
'ROLE_USER_NEW',
|
||||
'u_',
|
||||
'A new user role',
|
||||
'u_new',
|
||||
],
|
||||
];
|
||||
|
||||
public $new_role_ids = [];
|
||||
|
||||
public function getDataSet()
|
||||
{
|
||||
return $this->createXMLDataSet(__DIR__.'/fixtures/migrator_permission.xml');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Global $db and $cache are needed in acp/auth.php constructor
|
||||
global $phpbb_root_path, $phpEx, $db, $cache;
|
||||
|
||||
parent::setup();
|
||||
|
||||
$db = $this->db = $this->new_dbal();
|
||||
$cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);
|
||||
$this->auth = new \phpbb\auth\auth();
|
||||
|
||||
// Initialize this auth_admin instance later after adding new auth options via this->tool->add()
|
||||
if (!class_exists('auth_admin'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
|
||||
}
|
||||
|
||||
$this->tool = new \phpbb\db\migration\tool\permission($this->db, $this->cache, $this->auth, $phpbb_root_path, $phpEx);
|
||||
|
||||
$this->new_roles_add();
|
||||
}
|
||||
|
||||
public function new_roles_add()
|
||||
{
|
||||
foreach ($this->new_roles as $new_role_data)
|
||||
{
|
||||
$role_name = $new_role_data[0];
|
||||
$role_type = $new_role_data[1];
|
||||
$role_description = $new_role_data[2];
|
||||
$role_auth_option = $new_role_data[3];
|
||||
|
||||
$this->tool->add($role_auth_option);
|
||||
$this->new_role_ids[$role_name] = $this->tool->role_add($role_name, $role_type, $role_description);
|
||||
}
|
||||
|
||||
// Initialize external auth_admin instance here to keep acl_options array in sync with the one from the permission tool
|
||||
$this->auth_admin = new \auth_admin();
|
||||
}
|
||||
|
||||
public function data_test_new_role_exists()
|
||||
{
|
||||
return [
|
||||
['ROLE_ADMIN_NEW', true],
|
||||
['ROLE_MODERATOR_NEW', true],
|
||||
['ROLE_USER_NEW', true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_test_new_role_exists
|
||||
*/
|
||||
public function test_permission_new_role_exists($role_name, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, (bool) $this->tool->role_exists($role_name));
|
||||
}
|
||||
|
||||
public function data_test_permission_assign_new_roles()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'group',
|
||||
0,
|
||||
'ADMINISTRATORS',
|
||||
['a_new' => true],
|
||||
'ROLE_ADMIN_NEW',
|
||||
],
|
||||
[
|
||||
'group',
|
||||
0,
|
||||
'GLOBAL_MODERATORS',
|
||||
['m_new' => true],
|
||||
'ROLE_MODERATOR_NEW',
|
||||
],
|
||||
[
|
||||
'group',
|
||||
0,
|
||||
'REGISTERED',
|
||||
['u_new' => true],
|
||||
'ROLE_USER_NEW',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_test_permission_assign_new_roles
|
||||
*/
|
||||
public function test_permission_assign_new_roles($ug_type, $forum_id, $group_name, $auth, $role_name, $clear_prefetch = true)
|
||||
{
|
||||
$auth_option = key($auth);
|
||||
$group_id = (int) $this->group_ids[$group_name];
|
||||
$role_id = (int) $this->new_role_ids[$role_name];
|
||||
$expected = current($auth);
|
||||
|
||||
// Set auth options for each role
|
||||
$this->tool->permission_set($role_name, $auth_option, 'role', true);
|
||||
|
||||
// Assign roles to groups
|
||||
$this->auth_admin->acl_set($ug_type, $forum_id, $group_id, $auth, $role_id, $clear_prefetch);
|
||||
|
||||
// Test if role based group permissions assigned correctly
|
||||
$new_perm_state = $this->auth->acl_group_raw_data($group_id, $auth_option);
|
||||
$this->assertEquals($expected, !empty($new_perm_state), "$auth_option is " . ($expected ? 'empty' : 'not empty') . " for $group_name");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_test_permission_assign_new_roles
|
||||
* @depends test_permission_new_role_exists
|
||||
* @depends test_permission_assign_new_roles
|
||||
*/
|
||||
public function test_permission_new_role_remove($ug_type, $forum_id, $group_name, $auth, $role_name)
|
||||
{
|
||||
$auth_option = key($auth);
|
||||
$group_id = (int) $this->group_ids[$group_name];
|
||||
$role_id = (int) $this->new_role_ids[$role_name];
|
||||
|
||||
$sql = 'SELECT agt.auth_role_id
|
||||
FROM ' . ACL_GROUPS_TABLE . ' agt, ' . ACL_ROLES_TABLE . ' art
|
||||
WHERE agt.auth_role_id = art.role_id
|
||||
AND art.role_id = ' . $role_id;
|
||||
|
||||
// Set auth options for each role
|
||||
$this->tool->permission_set($role_name, $auth_option, 'role', true);
|
||||
|
||||
// Assign roles to groups
|
||||
$this->auth_admin->acl_set($ug_type, $forum_id, $group_id, $auth, $role_id);
|
||||
|
||||
// Check if the role is assigned to the group
|
||||
$result = $this->db->sql_query($sql);
|
||||
$this->assertEquals($role_id, $this->db->sql_fetchfield('auth_role_id'));
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$this->tool->role_remove($role_name);
|
||||
$this->assertFalse((bool) $this->tool->role_exists($role_name));
|
||||
|
||||
// Check if the role is unassigned
|
||||
$result = $this->db->sql_query($sql);
|
||||
$this->assertFalse($this->db->sql_fetchfield('auth_role_id'));
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
}
|
48
tests/email/headers_encoding_test.php
Normal file
48
tests/email/headers_encoding_test.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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_headers_encoding_test extends phpbb_test_case
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
global $phpbb_root_path, $phpEx;
|
||||
|
||||
if (!function_exists('mail_encode'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
|
||||
}
|
||||
}
|
||||
|
||||
public function headers_encoding_data()
|
||||
{
|
||||
return [
|
||||
['test@yourdomain.com <phpBB fake test email>', 'Q', 'US-ASCII'],
|
||||
['test@yourdomain.com <Несуществующий почтовый адрес phpBB>', 'B', 'UTF-8'],
|
||||
["\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88", 'B', 'UTF-8'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider headers_encoding_data
|
||||
*/
|
||||
public function test_headers_encoding($header, $scheme, $encoding)
|
||||
{
|
||||
$encoded_string = mail_encode($header);
|
||||
$this->assertStringStartsWith("=?$encoding?$scheme?", $encoded_string);
|
||||
$this->assertStringEndsWith('?=', $encoded_string);
|
||||
|
||||
// Result of iconv_mime_decode() on decoded header should be equal to initial header
|
||||
$decoded_string = iconv_mime_decode($encoded_string, 0, $encoding);
|
||||
$this->assertEquals(0, strcmp($header, $decoded_string));
|
||||
}
|
||||
}
|
@@ -30,6 +30,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->db = null;
|
||||
$this->extension_manager = $this->create_extension_manager();
|
||||
}
|
||||
|
||||
@@ -95,7 +96,12 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
|
||||
|
||||
$this->assertEquals(array('vendor2/foo'), array_keys($this->extension_manager->all_enabled()));
|
||||
$this->extension_manager->enable('vendor2/bar');
|
||||
$this->assertEquals(array('vendor2/bar', 'vendor2/foo'), array_keys($this->extension_manager->all_enabled()));
|
||||
|
||||
// We should not display the extension as being enabled in the same request
|
||||
$this->assertEquals(array('vendor2/foo'), array_keys($this->extension_manager->all_enabled()));
|
||||
// With a different request we should see the extension as being disabled
|
||||
$this->assertEquals(array('vendor2/bar', 'vendor2/foo'), array_keys($this->create_extension_manager()->all_enabled()));
|
||||
|
||||
$this->assertEquals(array('vendor/moo', 'vendor2/bar', 'vendor2/foo'), array_keys($this->extension_manager->all_configured()));
|
||||
|
||||
$this->assertEquals(4, vendor2\bar\ext::$state);
|
||||
@@ -119,7 +125,12 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
|
||||
|
||||
$this->assertEquals(array('vendor2/foo'), array_keys($this->extension_manager->all_enabled()));
|
||||
$this->extension_manager->disable('vendor2/foo');
|
||||
$this->assertEquals(array(), array_keys($this->extension_manager->all_enabled()));
|
||||
|
||||
// We should still display the extension as being enabled in the current request
|
||||
$this->assertEquals(array('vendor2/foo'), array_keys($this->extension_manager->all_enabled()));
|
||||
// With a different request we should see the extension as being disabled
|
||||
$this->assertEquals(array(), array_keys($this->create_extension_manager()->all_enabled()));
|
||||
|
||||
$this->assertEquals(array('vendor/moo', 'vendor2/foo'), array_keys($this->extension_manager->all_configured()));
|
||||
|
||||
$this->assertTrue(vendor2\foo\ext::$disabled);
|
||||
@@ -147,7 +158,6 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
|
||||
|
||||
protected function create_extension_manager($with_cache = true)
|
||||
{
|
||||
|
||||
$config = new \phpbb\config\config(array('version' => PHPBB_VERSION));
|
||||
$db = $this->new_dbal();
|
||||
$factory = new \phpbb\db\tools\factory();
|
||||
@@ -177,6 +187,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
|
||||
$db,
|
||||
$config,
|
||||
new \phpbb\filesystem\filesystem(),
|
||||
new phpbb_mock_dummy_router(),
|
||||
'phpbb_ext',
|
||||
__DIR__ . '/',
|
||||
$php_ext,
|
||||
|
@@ -98,6 +98,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
|
||||
$this->db,
|
||||
$this->config,
|
||||
new \phpbb\filesystem\filesystem(),
|
||||
new phpbb_mock_dummy_router(),
|
||||
'phpbb_ext',
|
||||
$this->phpbb_root_path,
|
||||
$this->phpEx,
|
||||
|
118
tests/functional/acp_attachments_test.php
Normal file
118
tests/functional/acp_attachments_test.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?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_acp_attachments_test extends phpbb_functional_test_case
|
||||
{
|
||||
private $path;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->path = __DIR__ . '/fixtures/files/';
|
||||
$this->add_lang('posting');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$iterator = new DirectoryIterator(__DIR__ . '/../../phpBB/files/');
|
||||
foreach ($iterator as $fileinfo)
|
||||
{
|
||||
if (
|
||||
$fileinfo->isDot()
|
||||
|| $fileinfo->isDir()
|
||||
|| $fileinfo->getFilename() === 'index.htm'
|
||||
|| $fileinfo->getFilename() === '.htaccess'
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unlink($fileinfo->getPathname());
|
||||
}
|
||||
}
|
||||
|
||||
private function upload_file($filename, $mimetype)
|
||||
{
|
||||
$crawler = self::$client->request(
|
||||
'GET',
|
||||
'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid
|
||||
);
|
||||
|
||||
$file_form_data = array_merge(['add_file' => $this->lang('ADD_FILE')], $this->get_hidden_fields($crawler, 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid));
|
||||
|
||||
$file = array(
|
||||
'tmp_name' => $this->path . $filename,
|
||||
'name' => $filename,
|
||||
'type' => $mimetype,
|
||||
'size' => filesize($this->path . $filename),
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
);
|
||||
|
||||
$crawler = self::$client->request(
|
||||
'POST',
|
||||
'posting.php?mode=reply&t=1&sid=' . $this->sid,
|
||||
$file_form_data,
|
||||
array('fileupload' => $file)
|
||||
);
|
||||
|
||||
return $crawler;
|
||||
}
|
||||
|
||||
public function test_orphaned_attachments()
|
||||
{
|
||||
$this->login();
|
||||
$this->add_lang(['common', 'acp/common', 'acp/attachments']);
|
||||
$crawler = $this->upload_file('valid.jpg', 'image/jpeg');
|
||||
|
||||
// Ensure there was no error message rendered
|
||||
$this->assertStringNotContainsString('<h2>' . $this->lang('INFORMATION') . '</h2>', $this->get_content());
|
||||
|
||||
// Also the file name should be in the first row of the files table
|
||||
$this->assertEquals('valid.jpg', $crawler->filter('span.file-name > a')->text());
|
||||
|
||||
$attach_link = $crawler->filter('span.file-name > a')->attr('href');
|
||||
$attach_id = $this->get_parameter_from_link($attach_link, 'id');
|
||||
|
||||
// Set file time older than 3 hours to consider it orphan
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET filetime = filetime - ' . 4*60*60 . '
|
||||
WHERE attach_id = ' . (int) $attach_id;
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$this->admin_login();
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_attachments&mode=orphan');
|
||||
$this->assertContainsLang('ACP_ORPHAN_ATTACHMENTS_EXPLAIN', $this->get_content());
|
||||
$this->assertStringContainsString('valid.jpg', $crawler->filter('tbody a')->text());
|
||||
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form([
|
||||
"post_id[$attach_id]" => 99999, // Random
|
||||
]);
|
||||
$form["add[$attach_id]"]->tick();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$this->assertContainsLang('UPLOADING_FILES', $this->get_content());
|
||||
$this->assertStringContainsString($this->lang('UPLOADING_FILE_TO', 'valid.jpg', 99999), $this->get_content());
|
||||
$this->assertStringContainsString($this->lang('UPLOAD_POST_NOT_EXIST', 'valid.jpg', 99999), $crawler->filter('span[class="error"]')->text());
|
||||
|
||||
// Delete the file
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
|
||||
$form["delete[$attach_id]"]->tick();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$this->assertContainsLang('NOTIFY', $crawler->filter('.successbox')->text());
|
||||
$this->assertStringContainsString(strip_tags($this->lang('LOG_ATTACH_ORPHAN_DEL', 'valid.jpg')), $crawler->filter('.successbox > p')->text());
|
||||
}
|
||||
}
|
@@ -101,7 +101,7 @@ class phpbb_functional_auth_test extends phpbb_functional_test_case
|
||||
$this->assertStringContainsString($this->lang('AUTH_PROVIDER_OAUTH_SERVICE_GOOGLE'), $crawler->filter('h3')->text());
|
||||
$form = $crawler->selectButton($this->lang('UCP_AUTH_LINK_LINK'))->form();
|
||||
$crawler = self::submit($form);
|
||||
$this->assertStringContainsString('Google Accounts', $crawler->filter('title')->text());
|
||||
$this->assertStringContainsString('accounts.google.com', $crawler->filter('base')->attr('href'));
|
||||
|
||||
// Test OAuth linking for registration
|
||||
$this->logout();
|
||||
@@ -111,7 +111,7 @@ class phpbb_functional_auth_test extends phpbb_functional_test_case
|
||||
$crawler = self::submit($form);
|
||||
$this->assertContainsLang('AUTH_PROVIDER_OAUTH_SERVICE_GOOGLE', $crawler->filter('a[class="button2"]')->text());
|
||||
$crawler = self::request('GET', 'ucp.php?mode=login&login=external&oauth_service=google');
|
||||
$this->assertStringContainsString('Google Accounts', $crawler->filter('title')->text());
|
||||
$this->assertStringContainsString('accounts.google.com', $crawler->filter('base')->attr('href'));
|
||||
|
||||
// Restore default auth method, but unset random keys first
|
||||
// Restart webclient as we were redirected to external site before
|
||||
|
@@ -43,8 +43,6 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case
|
||||
|
||||
$this->purge_cache();
|
||||
|
||||
$this->get_db();
|
||||
|
||||
// Clear the phpbb_ext table
|
||||
$this->db->sql_query('DELETE FROM phpbb_ext');
|
||||
|
||||
|
@@ -868,24 +868,6 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
|
||||
$this->set_flood_interval(15);
|
||||
}
|
||||
|
||||
protected function set_flood_interval($flood_interval)
|
||||
{
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
|
||||
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
|
||||
$values['config[flood_interval]'] = $flood_interval;
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
self::assertGreaterThan(0, $crawler->filter('.successbox')->count());
|
||||
|
||||
$this->logout();
|
||||
}
|
||||
|
||||
public function test_feeds_unapproved_topic_admin()
|
||||
{
|
||||
$this->load_ids(array(
|
||||
|
35
tests/functional/mcp/mcp_logs_test.php
Normal file
35
tests/functional/mcp/mcp_logs_test.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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_mcp_logs_test extends phpbb_functional_test_case
|
||||
{
|
||||
public function test_delete_logs()
|
||||
{
|
||||
$this->add_lang(['mcp', 'common']);
|
||||
|
||||
$this->login();
|
||||
$crawler = self::request('GET', "mcp.php?i=mcp_logs&mode=front&sid={$this->sid}");
|
||||
$this->assertGreaterThanOrEqual(1, $crawler->filter('input[type=checkbox]')->count());
|
||||
|
||||
$form = $crawler->selectButton($this->lang('DELETE_ALL'))->form();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$this->assertCount(0, $crawler->filter('input[type=checkbox]'));
|
||||
}
|
||||
}
|
319
tests/functional/mcp/mcp_main_test.php
Normal file
319
tests/functional/mcp/mcp_main_test.php
Normal file
@@ -0,0 +1,319 @@
|
||||
<?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_mcp_main_test extends phpbb_functional_test_case
|
||||
{
|
||||
public function test_create_topics()
|
||||
{
|
||||
$this->add_lang(['acp/common', 'acp/forums', 'common']);
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
|
||||
$this->set_flood_interval(0);
|
||||
|
||||
// Create a forum to move topics around
|
||||
$forum_name = 'MCP Test #1';
|
||||
$crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}");
|
||||
$form = $crawler->selectButton($this->lang('CREATE_FORUM'))->form([
|
||||
'forum_name' => $forum_name,
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form([
|
||||
'forum_parent_id' => 1,
|
||||
'forum_perm_from' => 2,
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertContainsLang('FORUM_CREATED', $crawler->text());
|
||||
|
||||
// Create topics to test with
|
||||
$post = [];
|
||||
$post[] = $this->create_topic(2, 'Test Topic 3', 'Testing forum moderation actions from MCP/View forum page.');
|
||||
$crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
|
||||
$this->assertStringContainsString('Testing forum moderation actions from MCP/View forum page.', $crawler->filter('html')->text());
|
||||
|
||||
$post[] = $this->create_topic(2, 'Topic to merge with', 'Testing merge topics moderation actions from MCP/View forum page.');
|
||||
$crawler = self::request('GET', "viewtopic.php?t={$post[1]['topic_id']}&sid={$this->sid}");
|
||||
$this->assertStringContainsString('Testing merge topics moderation actions from MCP/View forum page.', $crawler->filter('html')->text());
|
||||
|
||||
$this->set_flood_interval(15);
|
||||
|
||||
return $post;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @depends test_create_topics
|
||||
*/
|
||||
public function test_mcp_view_forum($post)
|
||||
{
|
||||
$this->add_lang(['common']);
|
||||
$this->login();
|
||||
|
||||
// Browse MCP main page from forum view (gives &f=2)
|
||||
$crawler = self::request('GET', "viewforum.php?f=2&sid={$this->sid}");
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
|
||||
|
||||
// Test forum moderation page has a list of topics to select
|
||||
$this->assertGreaterThanOrEqual(3, $crawler->filter('input[type=checkbox]')->count());
|
||||
|
||||
return $post;
|
||||
}
|
||||
|
||||
public function mcp_view_forum_actions_data()
|
||||
{
|
||||
// action, success message, require_confirmation
|
||||
return [
|
||||
['delete_topic', 'TOPIC_DELETED_SUCCESS', true],
|
||||
['restore_topic', 'TOPIC_RESTORED_SUCCESS', true],
|
||||
['fork', 'TOPIC_FORKED_SUCCESS', true],
|
||||
['lock', 'TOPIC_LOCKED_SUCCESS', true],
|
||||
['unlock', 'TOPIC_UNLOCKED_SUCCESS', true],
|
||||
['resync', 'TOPIC_RESYNC_SUCCESS', false],
|
||||
['make_global', 'TOPIC_TYPE_CHANGED', true],
|
||||
['make_announce', 'TOPIC_TYPE_CHANGED', true],
|
||||
['make_sticky', 'TOPIC_TYPE_CHANGED', true],
|
||||
['make_normal', 'TOPIC_TYPE_CHANGED', true],
|
||||
['merge_topics', 'POSTS_MERGED_SUCCESS', true],
|
||||
['move', 'TOPIC_MOVED_SUCCESS', true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_mcp_view_forum
|
||||
* @dataProvider mcp_view_forum_actions_data
|
||||
*/
|
||||
public function test_mcp_view_forum_actions($action, $message, $require_confirmation, $post)
|
||||
{
|
||||
$topic_id_1 = $post[0]['topic_id'];
|
||||
$topic_id_2 = $post[1]['topic_id'];
|
||||
|
||||
$this->add_lang(['common', 'mcp']);
|
||||
$this->login();
|
||||
|
||||
$crawler = self::request('GET', "viewforum.php?f=2&sid={$this->sid}");
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
|
||||
|
||||
// Test actions
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
|
||||
'action' => $action,
|
||||
'topic_id_list' => [$action == 'move' ? $topic_id_2 : $topic_id_1], // while moving, topic_id_1 has been already merged into topic_id_2
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
if ($require_confirmation)
|
||||
{
|
||||
if ($action == 'merge_topics')
|
||||
{
|
||||
// Merge topic_id_1 into topic_id_2
|
||||
$select_for_merge_link = $crawler->selectLink($this->lang('SELECT_MERGE'))->reduce(
|
||||
function ($node, $i) use ($topic_id_2)
|
||||
{
|
||||
return (bool) strpos($node->attr('href'), "to_topic_id=$topic_id_2");
|
||||
}
|
||||
)->link();
|
||||
|
||||
$crawler = self::$client->click($select_for_merge_link);
|
||||
}
|
||||
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
|
||||
if (in_array($action, ['fork', 'move']))
|
||||
{
|
||||
// Fork or move the topic to the 'MCP Test #1'
|
||||
$forum_id = $crawler->filter('select > option')->reduce(
|
||||
function ($node, $i)
|
||||
{
|
||||
return (bool) strpos($node->text(), 'MCP Test #1');
|
||||
}
|
||||
)->attr('value');
|
||||
$form['to_forum_id']->select($forum_id);
|
||||
}
|
||||
|
||||
$crawler = self::submit($form);
|
||||
}
|
||||
|
||||
$this->assertStringContainsString($this->lang($message), $crawler->filter('#message p')->text());
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_mcp_view_forum_actions
|
||||
*/
|
||||
public function test_mcp_view_forum_permanently_delete_topic()
|
||||
{
|
||||
$this->add_lang(['common', 'mcp']);
|
||||
$this->login();
|
||||
|
||||
// Get to the forum 'MCP Test #1' where the topic has been moved to in previous test
|
||||
$crawler = self::request('GET', "index.php?sid={$this->sid}");
|
||||
$crawler = self::$client->click($crawler->selectLink('MCP Test #1')->link());
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
|
||||
|
||||
// Get topic ids to delete (forked and moved topics in the previous test)
|
||||
$topic_link_1 = $crawler->selectLink('Test Topic 3')->attr('href');
|
||||
$topic_link_2 = $crawler->selectLink('Topic to merge with')->attr('href');
|
||||
$topic_ids = [
|
||||
(int) $this->get_parameter_from_link($topic_link_1, 't'),
|
||||
(int) $this->get_parameter_from_link($topic_link_2, 't'),
|
||||
];
|
||||
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
|
||||
'action' => 'delete_topic',
|
||||
'topic_id_list' => $topic_ids, // tick both topics in the list
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
$form['delete_permanent']->tick();
|
||||
$crawler = self::submit($form);
|
||||
$this->assertStringContainsString($this->lang('TOPICS_DELETED_SUCCESS'), $crawler->filter('#message p')->text());
|
||||
}
|
||||
|
||||
public function mcp_view_topic_actions_data()
|
||||
{
|
||||
// action, success message, require_confirmation
|
||||
return [
|
||||
['lock_post', 'POSTS_LOCKED_SUCCESS', true],
|
||||
['unlock_post', 'POSTS_UNLOCKED_SUCCESS', true],
|
||||
['resync', 'TOPIC_RESYNC_SUCCESS', false],
|
||||
['split_all', 'TOPIC_SPLIT_SUCCESS', true],
|
||||
['split_beyond', 'TOPIC_SPLIT_SUCCESS', true],
|
||||
['merge_posts', 'POSTS_MERGED_SUCCESS', true],
|
||||
['delete_post', 'POSTS_DELETED_SUCCESS', true],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_create_topic_with_replies()
|
||||
{
|
||||
$this->login();
|
||||
|
||||
// Create topic and replies to test with
|
||||
$post = [];
|
||||
$post[] = $this->create_topic(2, 'Test Topic 4', 'Testing topic moderation actions from MCP/View topic page.');
|
||||
$crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
|
||||
$this->assertStringContainsString('Testing topic moderation actions from MCP/View topic page.', $crawler->filter('html')->text());
|
||||
|
||||
// Create replies. Flood control was disabled above
|
||||
for ($i = 1; $i <= 15; $i++)
|
||||
{
|
||||
sleep(1);
|
||||
$post_text = "This is reply number $i to the Test Topic 4 to test moderation actions from MCP/View topic page.";
|
||||
$post[$i] = $this->create_post(2, $post[0]['topic_id'], 'Re: Test Topic 4', $post_text);
|
||||
$crawler = self::request('GET', "viewtopic.php?p={$post[$i]['post_id']}&sid={$this->sid}#p{$post[$i]['post_id']}");
|
||||
$this->assertStringContainsString($post_text, $crawler->filter('html')->text());
|
||||
}
|
||||
|
||||
return $post;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_create_topic_with_replies
|
||||
* @dataProvider mcp_view_topic_actions_data
|
||||
*/
|
||||
public function test_mcp_view_topic_actions($action, $message, $require_confirmation, $post)
|
||||
{
|
||||
$this->add_lang(['common', 'mcp']);
|
||||
$this->login();
|
||||
|
||||
$crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
|
||||
$this->assertLessThanOrEqual(count($post), $crawler->filter('input[type=checkbox]')->count());
|
||||
|
||||
// Test actions
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
|
||||
|
||||
// Set posts to select for actions
|
||||
$post_id_list = [];
|
||||
switch ($action)
|
||||
{
|
||||
case 'lock_post':
|
||||
case 'unlock_post':
|
||||
$post_id_list = [$post[1]['post_id'], $post[2]['post_id']];
|
||||
break;
|
||||
|
||||
case 'split_all':
|
||||
$post_id_list = [$post[13]['post_id'], $post[14]['post_id'], $post[15]['post_id']]; // Split last 3 replies
|
||||
$subject = '[Split] Topic 1';
|
||||
break;
|
||||
|
||||
case 'split_beyond':
|
||||
$post_id_list = [$post[10]['post_id']]; // Split from 10th reply
|
||||
$subject = '[Split] Topic 2';
|
||||
break;
|
||||
|
||||
case 'merge_posts':
|
||||
$post_id_list = [$post[7]['post_id'], $post[8]['post_id'], $post[9]['post_id']]; // Split replies 7, 8, 9
|
||||
break;
|
||||
|
||||
case 'delete_post':
|
||||
$post_id_list = [$post[4]['post_id'], $post[5]['post_id'], $post[6]['post_id']]; // Delete posts 4, 5, 6
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$form->disableValidation()->setValues([
|
||||
'action' => $action,
|
||||
'post_id_list' => $post_id_list, // tick post ids
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
if ($require_confirmation)
|
||||
{
|
||||
if ($action == 'merge_posts')
|
||||
{
|
||||
// Merge posts into '[Split] Topic 1'
|
||||
// Get topics list to select from
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('SELECT_TOPIC'))->link());
|
||||
|
||||
// Get '[Split] Topic 1' topic_id
|
||||
$to_topic_link = $crawler->selectLink('[Split] Topic 1')->attr('href');
|
||||
$to_topic_id = (int) $this->get_parameter_from_link($to_topic_link, 't');
|
||||
|
||||
// Select '[Split] Topic 1'
|
||||
$select_for_merge_link = $crawler->selectLink($this->lang('SELECT_MERGE'))->reduce(
|
||||
function ($node, $i) use ($to_topic_id)
|
||||
{
|
||||
return (bool) strpos($node->attr('href'), "to_topic_id=$to_topic_id");
|
||||
}
|
||||
)->link();
|
||||
|
||||
$crawler = self::$client->click($select_for_merge_link);
|
||||
|
||||
$this->assertEquals($to_topic_id, (int) $crawler->filter('#to_topic_id')->attr('value'));
|
||||
|
||||
// Reselect post ids to move
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues(['post_id_list' => $post_id_list]);
|
||||
$crawler = self::submit($form);
|
||||
}
|
||||
|
||||
if (in_array($action, ['split_all', 'split_beyond']))
|
||||
{
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
|
||||
'subject' => $subject,
|
||||
'post_id_list' => $post_id_list, // tick post ids
|
||||
'to_forum_id' => 2,
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
}
|
||||
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
$crawler = self::submit($form);
|
||||
}
|
||||
|
||||
$this->assertStringContainsString($this->lang($message), $crawler->filter('#message p')->text());
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
/**
|
||||
* @group functional
|
||||
*/
|
||||
class phpbb_functional_mcp_test extends phpbb_functional_test_case
|
||||
class phpbb_functional_mcp_quickmod_tools_test extends phpbb_functional_test_case
|
||||
{
|
||||
public function test_post_new_topic()
|
||||
{
|
||||
@@ -30,8 +30,8 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_post_new_topic
|
||||
*/
|
||||
* @depends test_post_new_topic
|
||||
*/
|
||||
public function test_handle_quickmod($crawler)
|
||||
{
|
||||
// Test moving a post
|
||||
@@ -39,10 +39,12 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_handle_quickmod
|
||||
*/
|
||||
* @depends test_handle_quickmod
|
||||
*/
|
||||
public function test_move_post_to_topic($crawler)
|
||||
{
|
||||
$this->add_lang('common');
|
||||
|
||||
// Select the post in MCP
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form(array(
|
||||
'to_topic_id' => 1,
|
||||
@@ -55,8 +57,8 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_move_post_to_topic
|
||||
*/
|
||||
* @depends test_move_post_to_topic
|
||||
*/
|
||||
public function test_confirm_result($crawler)
|
||||
{
|
||||
$this->add_lang('mcp');
|
||||
@@ -64,20 +66,4 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case
|
||||
$crawler = self::submit($form);
|
||||
$this->assertStringContainsString($this->lang('POSTS_MERGED_SUCCESS'), $crawler->text());
|
||||
}
|
||||
|
||||
public function test_delete_logs()
|
||||
{
|
||||
$this->login();
|
||||
$crawler = self::request('GET', "mcp.php?i=mcp_logs&mode=front&sid={$this->sid}");
|
||||
$this->assertGreaterThanOrEqual(1, $crawler->filter('input[type=checkbox]')->count());
|
||||
|
||||
$this->add_lang('mcp');
|
||||
$form = $crawler->selectButton($this->lang('DELETE_ALL'))->form();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$form = $crawler->selectButton('Yes')->form();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$this->assertCount(0, $crawler->filter('input[type=checkbox]'));
|
||||
}
|
||||
}
|
55
tests/functional/mcp/mcp_test.php
Normal file
55
tests/functional/mcp/mcp_test.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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_mcp_test extends phpbb_functional_test_case
|
||||
{
|
||||
public function test_all_mcp_module_links()
|
||||
{
|
||||
$this->login();
|
||||
$this->add_lang(['common', 'mcp']);
|
||||
|
||||
// Browse MCP main page
|
||||
$crawler = self::request('GET', 'index.php');
|
||||
$crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
|
||||
|
||||
// Get all MCP module URLs array
|
||||
$mcp_modules = $crawler->filter('.tabs a')->each(
|
||||
function ($node, $i)
|
||||
{
|
||||
return $node->link();
|
||||
}
|
||||
);
|
||||
|
||||
// Browse all MCP modules and get their mode URLs array
|
||||
$mcp_submodules = [];
|
||||
foreach ($mcp_modules as $module)
|
||||
{
|
||||
$crawler = self::$client->click($module);
|
||||
$mcp_submodules = array_merge($mcp_submodules, $crawler->filter('.cp-menu a')->each(
|
||||
function ($node, $i)
|
||||
{
|
||||
return $node->link();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// Browse all MCP submodules' modes
|
||||
foreach ($mcp_submodules as $mcp_submodule)
|
||||
{
|
||||
self::$client->click($mcp_submodule);
|
||||
}
|
||||
}
|
||||
}
|
@@ -300,4 +300,26 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
|
||||
$crawler->filter('#preview .content')->html()
|
||||
);
|
||||
}
|
||||
|
||||
public function nonexistent_post_id_data()
|
||||
{
|
||||
$nonexistent_post_id = 999999; // Random value
|
||||
return [
|
||||
['edit', $nonexistent_post_id],
|
||||
['delete', $nonexistent_post_id],
|
||||
['quote', $nonexistent_post_id],
|
||||
['soft_delete', $nonexistent_post_id],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonexistent_post_id_data
|
||||
*/
|
||||
public function test_nonexistent_post_id($mode, $nonexistent_post_id)
|
||||
{
|
||||
$this->add_lang('posting');
|
||||
$this->login();
|
||||
$crawler = self::request('GET', "posting.php?mode={$mode}&p={$nonexistent_post_id}&sid={$this->sid}");
|
||||
$this->assertContainsLang('NO_POST', $crawler->text());
|
||||
}
|
||||
}
|
||||
|
@@ -16,32 +16,80 @@
|
||||
*/
|
||||
abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
{
|
||||
protected function assert_search_found($keywords, $posts_found, $words_highlighted)
|
||||
protected function assert_search_found($keywords, $posts_found, $words_highlighted, $sort_key = '')
|
||||
{
|
||||
$crawler = self::request('GET', 'search.php?keywords=' . $keywords);
|
||||
$this->assertEquals($posts_found, $crawler->filter('.postbody')->count());
|
||||
$this->assertEquals($words_highlighted, $crawler->filter('.posthilit')->count());
|
||||
$this->purge_cache();
|
||||
$crawler = self::request('GET', 'search.php?keywords=' . $keywords . ($sort_key ? "&sk=$sort_key" : ''));
|
||||
$this->assertEquals($posts_found, $crawler->filter('.postbody')->count(), $this->search_backend);
|
||||
$this->assertEquals($words_highlighted, $crawler->filter('.posthilit')->count(), $this->search_backend);
|
||||
$this->assertStringContainsString("Search found $posts_found match", $crawler->filter('.searchresults-title')->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_found_topics($keywords, $topics_found, $sort_key = '')
|
||||
{
|
||||
$this->purge_cache();
|
||||
$crawler = self::request('GET', 'search.php?sr=topics&keywords=' . $keywords . ($sort_key ? "&sk=$sort_key" : ''));
|
||||
$this->assertEquals($topics_found, $crawler->filter('.row')->count(), $this->search_backend);
|
||||
$this->assertStringContainsString("Search found $topics_found match", $crawler->filter('.searchresults-title')->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_posts_by_author($author, $posts_found, $sort_key = '')
|
||||
{
|
||||
$this->purge_cache();
|
||||
$crawler = self::request('GET', 'search.php?author=' . $author . ($sort_key ? "&sk=$sort_key" : ''));
|
||||
$this->assertEquals($posts_found, $crawler->filter('.postbody')->count(), $this->search_backend);
|
||||
$this->assertStringContainsString("Search found $posts_found match", $crawler->filter('.searchresults-title')->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_topics_by_author($author, $topics_found, $sort_key = '')
|
||||
{
|
||||
$this->purge_cache();
|
||||
$crawler = self::request('GET', 'search.php?sr=topics&author=' . $author . ($sort_key ? "&sk=$sort_key" : ''));
|
||||
$this->assertEquals($topics_found, $crawler->filter('.row')->count(), $this->search_backend);
|
||||
$this->assertStringContainsString("Search found $topics_found match", $crawler->filter('.searchresults-title')->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_not_found($keywords)
|
||||
{
|
||||
$crawler = self::request('GET', 'search.php?keywords=' . $keywords);
|
||||
$this->assertEquals(0, $crawler->filter('.postbody')->count());
|
||||
$split_keywords_string = str_replace(array('+', '-'), ' ', $keywords);
|
||||
$this->assertEquals($split_keywords_string, $crawler->filter('#keywords')->attr('value'));
|
||||
$this->assertEquals(0, $crawler->filter('.postbody')->count(), $this->search_backend);
|
||||
$split_keywords_string = str_replace('+', ' ', $keywords);
|
||||
$this->assertEquals($split_keywords_string, $crawler->filter('#keywords')->attr('value'), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_for_author_not_found($author)
|
||||
{
|
||||
$this->add_lang('search');
|
||||
$crawler = self::request('GET', 'search.php?author=' . $author);
|
||||
$this->assertContainsLang('NO_SEARCH_RESULTS', $crawler->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
public function test_search_backend()
|
||||
{
|
||||
$this->add_lang('common');
|
||||
|
||||
// Create a new standard user if needed, topic and post to test searh for author
|
||||
if (!$this->user_exists('searchforauthoruser'))
|
||||
{
|
||||
$searchforauthoruser_id = $this->create_user('searchforauthoruser');
|
||||
}
|
||||
$this->remove_user_group('NEWLY_REGISTERED', ['searchforauthoruser']);
|
||||
$this->set_flood_interval(0);
|
||||
$this->login('searchforauthoruser');
|
||||
$topic_by_author = $this->create_topic(2, 'Test Topic from searchforauthoruser', 'This is a test topic posted by searchforauthoruser to test searching by author.');
|
||||
$this->create_post(2, $topic_by_author['topic_id'], 'Re: Test Topic from searchforauthoruser', 'This is a test post posted by searchforauthoruser');
|
||||
$this->logout();
|
||||
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
|
||||
$this->create_search_index('\phpbb\search\fulltext_native');
|
||||
|
||||
$post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.');
|
||||
$this->set_flood_interval(15);
|
||||
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=settings&sid=' . $this->sid);
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
|
||||
$values = $form->getValues();
|
||||
|
||||
if ($values["config[search_type]"] != $this->search_backend)
|
||||
@@ -50,7 +98,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$form = $crawler->selectButton('Yes')->form();
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
$values = $form->getValues();
|
||||
$crawler = self::submit($form);
|
||||
|
||||
@@ -58,6 +106,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
if ($crawler->filter('.errorbox')->count() > 0)
|
||||
{
|
||||
$this->delete_topic($post['topic_id']);
|
||||
$this->delete_topic($topic_by_author['topic_id']);
|
||||
$this->markTestSkipped("Search backend is not supported/running");
|
||||
}
|
||||
|
||||
@@ -65,47 +114,73 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
}
|
||||
|
||||
$this->logout();
|
||||
$this->assert_search_found('phpbb3+installation', 1, 3);
|
||||
$this->assert_search_found('foosubject+barsearch', 1, 2);
|
||||
|
||||
foreach (['', 'a', 't', 'f', 'i', 's'] as $sort_key)
|
||||
{
|
||||
$this->assert_search_found('phpbb3+installation', 1, 3, $sort_key);
|
||||
$this->assert_search_found('foosubject+barsearch', 1, 2, $sort_key);
|
||||
$this->assert_search_found('barsearch-testing', 1, 2, $sort_key); // test hyphen ignored
|
||||
$this->assert_search_found('barsearch+-+testing', 1, 2, $sort_key); // test hyphen wrapped with space ignored
|
||||
$this->assert_search_found_topics('phpbb3+installation', 1, $sort_key);
|
||||
$this->assert_search_found_topics('foosubject+barsearch', 1, $sort_key);
|
||||
|
||||
$this->assert_search_posts_by_author('searchforauthoruser', 2, $sort_key);
|
||||
$this->assert_search_topics_by_author('searchforauthoruser', 1, $sort_key);
|
||||
}
|
||||
|
||||
$this->assert_search_not_found('loremipsumdedo');
|
||||
$this->assert_search_not_found('barsearch+-testing'); // test excluding keyword
|
||||
$this->assert_search_for_author_not_found('authornotexists');
|
||||
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
$this->delete_search_index();
|
||||
$this->delete_topic($post['topic_id']);
|
||||
$this->delete_topic($topic_by_author['topic_id']);
|
||||
}
|
||||
|
||||
protected function create_search_index($backend = null)
|
||||
{
|
||||
$this->add_lang('acp/search');
|
||||
$search_type = $backend ?? $this->search_backend;
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
|
||||
$form = $crawler->selectButton('Create index')->form();
|
||||
$form = $crawler->selectButton($this->lang('CREATE_INDEX'))->form();
|
||||
$form_values = $form->getValues();
|
||||
$form_values = array_merge($form_values,
|
||||
array(
|
||||
'search_type' => ( ($backend === null) ? $this->search_backend : $backend ),
|
||||
[
|
||||
'search_type' => $search_type,
|
||||
'action' => 'create',
|
||||
)
|
||||
]
|
||||
);
|
||||
$form->setValues($form_values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertContainsLang('SEARCH_INDEX_CREATED', $crawler->text());
|
||||
|
||||
// Ensure search index has been actually created
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
|
||||
$posts_indexed = (int) $crawler->filter('#acp_search_index_' . $search_type . ' td')->eq(1)->text();
|
||||
$this->assertTrue($posts_indexed > 0);
|
||||
}
|
||||
|
||||
protected function delete_search_index()
|
||||
{
|
||||
$this->add_lang('acp/search');
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
|
||||
$form = $crawler->selectButton('Delete index')->form();
|
||||
$form = $crawler->selectButton($this->lang('DELETE_INDEX'))->form();
|
||||
$form_values = $form->getValues();
|
||||
$form_values = array_merge($form_values,
|
||||
array(
|
||||
[
|
||||
'search_type' => $this->search_backend,
|
||||
'action' => 'delete',
|
||||
)
|
||||
]
|
||||
);
|
||||
$form->setValues($form_values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertContainsLang('SEARCH_INDEX_REMOVED', $crawler->text());
|
||||
|
||||
// Ensure search index has been actually removed
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
|
||||
$posts_indexed = (int) $crawler->filter('#acp_search_index_' . $this->search_backend . ' td')->eq(1)->text();
|
||||
$this->assertEquals(0, $posts_indexed);
|
||||
}
|
||||
}
|
||||
|
@@ -255,19 +255,6 @@ class phpbb_functional_visibility_disapprove_test extends phpbb_functional_test_
|
||||
$this->assertEquals($details, $data, "Forum {$forum_id} does not match expected {$additional_error_message}");
|
||||
}
|
||||
|
||||
protected function set_flood_interval($flood_interval)
|
||||
{
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
|
||||
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
|
||||
$values["config[flood_interval]"] = $flood_interval;
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertGreaterThan(0, $crawler->filter('.successbox')->count());
|
||||
}
|
||||
|
||||
protected function load_ids($data)
|
||||
{
|
||||
$this->db = $this->get_db();
|
||||
|
@@ -351,19 +351,6 @@ class phpbb_functional_visibility_reapprove_test extends phpbb_functional_test_c
|
||||
$this->assertEquals($details, $data, "Forum {$forum_id} does not match expected {$additional_error_message}");
|
||||
}
|
||||
|
||||
protected function set_flood_interval($flood_interval)
|
||||
{
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
|
||||
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
|
||||
$values["config[flood_interval]"] = $flood_interval;
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertGreaterThan(0, $crawler->filter('.successbox')->count());
|
||||
}
|
||||
|
||||
protected function load_ids($data)
|
||||
{
|
||||
$this->db = $this->get_db();
|
||||
|
@@ -268,19 +268,6 @@ class phpbb_functional_visibility_unapproved_test extends phpbb_functional_test_
|
||||
$this->assertEquals($details, $data, "Forum {$forum_id} does not match expected {$additional_error_message}");
|
||||
}
|
||||
|
||||
protected function set_flood_interval($flood_interval)
|
||||
{
|
||||
$crawler = self::request('GET', "adm/index.php?sid={$this->sid}&i=acp_board&mode=post");
|
||||
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
|
||||
$values['config[flood_interval]'] = $flood_interval;
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertGreaterThan(0, $crawler->filter('.successbox')->count());
|
||||
}
|
||||
|
||||
protected function load_ids($data)
|
||||
{
|
||||
$this->db = $this->get_db();
|
||||
|
@@ -51,6 +51,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('USERNAME_TAKEN'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
array('USERNAME_ALPHA_ONLY', array(
|
||||
'foobar_allow' => array(),
|
||||
@@ -65,6 +66,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('INVALID_CHARS'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
array('USERNAME_ALPHA_SPACERS', array(
|
||||
'foobar_allow' => array(),
|
||||
@@ -79,6 +81,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('USERNAME_TAKEN'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
array('USERNAME_LETTER_NUM', array(
|
||||
'foobar_allow' => array(),
|
||||
@@ -93,6 +96,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('INVALID_CHARS'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
array('USERNAME_LETTER_NUM_SPACERS', array(
|
||||
'foobar_allow' => array(),
|
||||
@@ -107,6 +111,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('USERNAME_TAKEN'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
array('USERNAME_ASCII', array(
|
||||
'foobar_allow' => array(),
|
||||
@@ -121,6 +126,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'barfoo_disallow' => array('USERNAME_DISALLOWED'),
|
||||
'admin_taken' => array('USERNAME_TAKEN'),
|
||||
'group_taken' => array('USERNAME_TAKEN'),
|
||||
'a d m i n i strator' => array('INVALID_CHARS'),
|
||||
)),
|
||||
);
|
||||
}
|
||||
@@ -201,6 +207,11 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case
|
||||
'foobar_group',
|
||||
array('username'),
|
||||
),
|
||||
'a d m i n i strator' => array(
|
||||
$expected['a d m i n i strator'],
|
||||
'a d m i n i strator',
|
||||
array('username'),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
31
tests/mock/dummy_router.php
Normal file
31
tests/mock/dummy_router.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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_mock_dummy_router extends phpbb_mock_router
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function get_matcher()
|
||||
{
|
||||
$this->create_new_url_matcher();
|
||||
return parent::get_matcher();
|
||||
}
|
||||
|
||||
public function get_generator()
|
||||
{
|
||||
$this->create_new_url_generator();
|
||||
return parent::get_generator();
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
class phpbb_mock_extension_manager extends \phpbb\extension\manager
|
||||
{
|
||||
public function __construct($phpbb_root_path, $extensions = array(), $container = null)
|
||||
@@ -25,5 +26,6 @@ class phpbb_mock_extension_manager extends \phpbb\extension\manager
|
||||
$this->container = $container;
|
||||
$this->config = new \phpbb\config\config(array());
|
||||
$this->user = new \phpbb\user($lang,'\phpbb\datetime');
|
||||
$this->router = new phpbb_mock_dummy_router();
|
||||
}
|
||||
}
|
||||
|
@@ -125,4 +125,18 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
|
||||
// Run test
|
||||
$this->run_template('includecss.html', array(), array(), array(), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider template_data
|
||||
*/
|
||||
public function test_include_css_compilation($vars, $expected)
|
||||
{
|
||||
// Reset the engine state
|
||||
$this->setup_engine(array('assets_version' => 1));
|
||||
|
||||
$this->template->assign_vars($vars);
|
||||
|
||||
// Run test
|
||||
$this->run_template('includecss_twig.html', array(), array(), array(), $expected);
|
||||
}
|
||||
}
|
||||
|
@@ -106,4 +106,18 @@ class phpbb_template_template_includejs_test extends phpbb_template_template_tes
|
||||
// Run test
|
||||
$this->run_template('includejs.html', array_merge(array('PARENT' => 'parent_only.js', 'SUBDIR' => 'subdir', 'EXT' => 'js'), $vars), array(), array(), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider template_data
|
||||
*/
|
||||
public function test_include_js_compilation($vars, $expected)
|
||||
{
|
||||
// Reset the engine state
|
||||
$this->setup_engine(array('assets_version' => 1));
|
||||
|
||||
$this->template->assign_vars($vars);
|
||||
|
||||
// Run test
|
||||
$this->run_template('includejs_twig.html', array_merge(array('PARENT' => 'parent_only.js', 'SUBDIR' => 'subdir', 'EXT' => 'js'), $vars), array(), array(), $expected);
|
||||
}
|
||||
}
|
||||
|
10
tests/template/templates/includecss_twig.html
Normal file
10
tests/template/templates/includecss_twig.html
Normal file
@@ -0,0 +1,10 @@
|
||||
{% if TEST === 1 %}
|
||||
{% INCLUDECSS('child_only.css') %}
|
||||
{% elseif TEST === 2 %}
|
||||
{% INCLUDECSS('parent_only.css') %}
|
||||
{% elseif TEST === 3 %}
|
||||
{% INCLUDECSS('@include_css/test.css') %}
|
||||
{% elseif TEST === 4 %}
|
||||
{% INCLUDECSS('@include_css/child_only.css') %}
|
||||
{% endif %}
|
||||
{$STYLESHEETS}
|
36
tests/template/templates/includejs_twig.html
Normal file
36
tests/template/templates/includejs_twig.html
Normal file
@@ -0,0 +1,36 @@
|
||||
{% if TEST === 1 %}
|
||||
{% INCLUDEJS('parent_and_child.js') %}
|
||||
{% elseif TEST === 2 %}
|
||||
{% INCLUDEJS('parent_and_child.js?assets_version=0') %}
|
||||
{% elseif TEST === 3 %}
|
||||
{% INCLUDEJS('parent_and_child.js?test=1&assets_version=0') %}
|
||||
{% elseif TEST === 4 %}
|
||||
{% INCLUDEJS('parent_and_child.js?test=1&assets_version=0') %}
|
||||
{% elseif TEST === 6 %}
|
||||
{% INCLUDEJS(PARENT) %}
|
||||
{% elseif TEST === 7 %}
|
||||
{% set test_var = 'child_only.js' %}
|
||||
{% INCLUDEJS(test_var) %}
|
||||
{% elseif TEST === 8 %}
|
||||
{% INCLUDEJS('subdir/' ~ PARENT) %}
|
||||
{% elseif TEST === 9 %}
|
||||
{% INCLUDEJS(SUBDIR ~ '/subsubdir/' ~ PARENT) %}
|
||||
{% elseif TEST === 10 %}
|
||||
{% INCLUDEJS(SUBDIR ~ '/parent_only.' ~ EXT) %}
|
||||
{% elseif TEST === 11 %}
|
||||
{% set test_var = 'child_only.js?test1=1&test2=2#test3' %}
|
||||
{% INCLUDEJS(test_var) %}
|
||||
{% elseif TEST === 12 %}
|
||||
{% INCLUDEJS('parent_only.js?test1=1&test2=2#test3') %}
|
||||
{% elseif TEST === 14 %}
|
||||
{% INCLUDEJS('parent_only.js?test1="#test3') %}
|
||||
{% elseif TEST === 15 %}
|
||||
{% INCLUDEJS('http://phpbb.com/b.js?c=d#f') %}
|
||||
{% elseif TEST === 16 %}
|
||||
{% INCLUDEJS('http://phpbb.com/b.js?c=d&assets_version=2#f') %}
|
||||
{% elseif TEST === 17 %}
|
||||
{% INCLUDEJS('//phpbb.com/b.js') %}
|
||||
{% elseif TEST === 18 %}
|
||||
{% INCLUDEJS('parent_and_child.js?test=1&test2=0') %}
|
||||
{% endif %}
|
||||
{$SCRIPTS}
|
@@ -261,6 +261,7 @@ class phpbb_functional_test_case extends phpbb_test_case
|
||||
$db,
|
||||
$config,
|
||||
new phpbb\filesystem\filesystem(),
|
||||
new phpbb_mock_dummy_router(),
|
||||
self::$config['table_prefix'] . 'ext',
|
||||
__DIR__ . '/',
|
||||
$phpEx,
|
||||
@@ -1180,9 +1181,12 @@ class phpbb_functional_test_case extends phpbb_test_case
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = $crawler->selectLink($form_data['subject'])->link()->getUri();
|
||||
$post_link = $crawler->filter('.postbody a[title="Post"]')->last()->attr('href');
|
||||
$topic_link = $crawler->filter('h2[class="topic-title"] > a')->attr('href');
|
||||
|
||||
$post_id = $this->get_parameter_from_link($post_link, 'p');
|
||||
$topic_id = $this->get_parameter_from_link($topic_link, 't');
|
||||
|
||||
$topic_id = $this->get_parameter_from_link($url, 't');
|
||||
if (!$topic_id)
|
||||
{
|
||||
$topic_id = $form_data['topic_id'];
|
||||
@@ -1190,7 +1194,7 @@ class phpbb_functional_test_case extends phpbb_test_case
|
||||
|
||||
return array(
|
||||
'topic_id' => $topic_id,
|
||||
'post_id' => $this->get_parameter_from_link($url, 'p'),
|
||||
'post_id' => $post_id,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1433,4 +1437,87 @@ class phpbb_functional_test_case extends phpbb_test_case
|
||||
|
||||
return $file_form_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get username of currently logged in user
|
||||
*
|
||||
* @return string|bool username if logged in, false otherwise
|
||||
*/
|
||||
protected function get_logged_in_user()
|
||||
{
|
||||
$username_logged_in = false;
|
||||
$crawler = self::request('GET', 'index.php');
|
||||
$is_logged_in = strpos($crawler->filter('div[class="navbar"]')->text(), 'Login') === false;
|
||||
if ($is_logged_in)
|
||||
{
|
||||
$username_logged_in = $crawler->filter('li[id="username_logged_in"] > div > a > span')->text();
|
||||
}
|
||||
return $username_logged_in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Posting flood control
|
||||
*/
|
||||
protected function set_flood_interval($flood_interval)
|
||||
{
|
||||
$relogin_back = false;
|
||||
$logged_in_username = $this->get_logged_in_user();
|
||||
if ($logged_in_username && $logged_in_username !== 'admin')
|
||||
{
|
||||
$this->logout();
|
||||
$relogin_back = true;
|
||||
}
|
||||
|
||||
if (!$logged_in_username || $relogin_back)
|
||||
{
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
}
|
||||
|
||||
$this->add_lang('acp/common');
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_board&mode=post&sid=' . $this->sid);
|
||||
$form = $crawler->selectButton('submit')->form([
|
||||
'config[flood_interval]' => $flood_interval,
|
||||
]);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertContainsLang('CONFIG_UPDATED', $crawler->text());
|
||||
|
||||
// Get logged out back or get logged in in user back if needed
|
||||
if (!$logged_in_username)
|
||||
{
|
||||
$this->logout();
|
||||
}
|
||||
|
||||
if ($relogin_back)
|
||||
{
|
||||
$this->logout();
|
||||
$this->login($logged_in_username);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user exists by username or user_id
|
||||
*
|
||||
* @param string $username The username to check or empty if user_id is used
|
||||
* @param int $user_id The user id to check or empty if username is used
|
||||
*
|
||||
* @return bool Returns true if a user exists, false otherwise
|
||||
*/
|
||||
protected function user_exists($username, $user_id = null)
|
||||
{
|
||||
global $db;
|
||||
|
||||
$db = $this->get_db();
|
||||
|
||||
if (!function_exists('utf_clean_string'))
|
||||
{
|
||||
require_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php');
|
||||
}
|
||||
if (!function_exists('user_get_id_name'))
|
||||
{
|
||||
require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');
|
||||
}
|
||||
|
||||
return user_get_id_name($user_id, $username) ? false : true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user