mirror of
https://github.com/phpbb/phpbb.git
synced 2025-09-14 01:52:06 +02:00
Compare commits
234 Commits
release-3.
...
3.3.x
Author | SHA1 | Date | |
---|---|---|---|
|
b59bfadec7 | ||
|
f6269dde2d | ||
|
1633288447 | ||
|
081f2391cb | ||
|
0b242b9608 | ||
|
3b03f3a8f9 | ||
|
e47ba9e81d | ||
|
8d016bafa2 | ||
|
35221f8ba5 | ||
|
9219c03b36 | ||
|
72c3745868 | ||
|
579b4a8287 | ||
|
2f43c1facd | ||
|
d4a3311b76 | ||
|
8411da1819 | ||
|
8f8a93fa71 | ||
|
c726382d84 | ||
|
5deeea025f | ||
|
b6c42b3768 | ||
|
da2733a7d8 | ||
|
b8204d24f9 | ||
|
6947dc8c92 | ||
|
ddc7f1df34 | ||
|
478d119d42 | ||
|
b3478d83d1 | ||
|
7268859226 | ||
|
10947f3d49 | ||
|
04f2141a7d | ||
|
3d76a8bd09 | ||
|
1c399dcab7 | ||
|
e91c7d42a9 | ||
|
1b2ac50cfd | ||
|
779bec5fcf | ||
|
f512af1823 | ||
|
59e8875fa8 | ||
|
1ae9a49811 | ||
|
80a08d9c54 | ||
|
4140d50f6a | ||
|
dd53db1625 | ||
|
e5f599c43b | ||
|
705b5ca572 | ||
|
8d0d6c012c | ||
|
8c5e22f4d5 | ||
|
cac3d81e73 | ||
|
40608777f0 | ||
|
84a835a995 | ||
|
b8ea36a70f | ||
|
98a8999283 | ||
|
fabef37d71 | ||
|
b92ca5d1f8 | ||
|
fb46aa38b8 | ||
|
51465670f6 | ||
|
14a6322b4f | ||
|
cfa3a21e20 | ||
|
64dd8b668e | ||
|
57abba6be0 | ||
|
0826a41da8 | ||
|
1ea59731f0 | ||
|
9bdb88879d | ||
|
430200cbf6 | ||
|
d8aa6873b2 | ||
|
d9136469ea | ||
|
7fd634b420 | ||
|
bb3d41e193 | ||
|
94fde8fa23 | ||
|
66650cb0e2 | ||
|
d9e4ce6dde | ||
|
24fc7d5388 | ||
|
ae40c6365e | ||
|
63c110b511 | ||
|
be67bfbe63 | ||
|
cedbbb0c76 | ||
|
a5bf1ff165 | ||
|
08fd9caa11 | ||
|
746133d005 | ||
|
17480d7d07 | ||
|
c3bb5e1bec | ||
|
29730e49ce | ||
|
8adc853dea | ||
|
a223da37fb | ||
|
7181c4d591 | ||
|
2fa5da1454 | ||
|
77f83306b5 | ||
|
4f5ace858d | ||
|
f42c4be939 | ||
|
bfdf172992 | ||
|
6b5bb4d51f | ||
|
736ef320ed | ||
|
bf29596bad | ||
|
120ae90636 | ||
|
b157e1b0d2 | ||
|
cd47344ee2 | ||
|
a86f368f3d | ||
|
f9def4a725 | ||
|
3d6e63154f | ||
|
2f08d8eb72 | ||
|
059e82de8f | ||
|
c06bec87dc | ||
|
7540720c79 | ||
|
e73ba63590 | ||
|
1255febe6b | ||
|
911f8a5fb7 | ||
|
a4879e9249 | ||
|
922fde6d53 | ||
|
332ecb3d9c | ||
|
8978594d6d | ||
|
13945f56a9 | ||
|
253579761d | ||
|
7baba29d9d | ||
|
32a1d82969 | ||
|
5dc93ea51e | ||
|
0e8f4f89d8 | ||
|
4a98024474 | ||
|
5538b9a37b | ||
|
5d0b1661f2 | ||
|
c7e68fb572 | ||
|
150bd59c82 | ||
|
5c7cbbc6a8 | ||
|
72ae28d583 | ||
|
ff08756ea0 | ||
|
1f48926b1d | ||
|
b40cdb757f | ||
|
65e457d3d2 | ||
|
bf83c73a60 | ||
|
4194cb2228 | ||
|
7086fa746f | ||
|
eeede1ab6c | ||
|
be52902541 | ||
|
c252fb9bfb | ||
|
725cbd31c8 | ||
|
cefce7df54 | ||
|
c992272036 | ||
|
7c090c6e2a | ||
|
4c419c5acd | ||
|
eaa0c779a6 | ||
|
3c7bf782a7 | ||
|
aa21aff080 | ||
|
443d82d082 | ||
|
5abc36f651 | ||
|
f971d7ffcb | ||
|
ed145b8317 | ||
|
26e49d4b15 | ||
|
43ff56a7a7 | ||
|
6c35cea146 | ||
|
62f9f53f46 | ||
|
4a039d853f | ||
|
b1282fcbc7 | ||
|
58d87c7c06 | ||
|
fd58e4f338 | ||
|
8129208e56 | ||
|
ecceeab709 | ||
|
660f3d2b86 | ||
|
ae1d830e84 | ||
|
688c7cad49 | ||
|
44f04a91f3 | ||
|
db7b4c999d | ||
|
1b0c9b22e0 | ||
|
4217dc46ca | ||
|
46ea7a8ffd | ||
|
f80b41aa77 | ||
|
501ecf5dec | ||
|
13b267ca6f | ||
|
6db142b8ef | ||
|
4ba4b94fe0 | ||
|
7c95839951 | ||
|
cd619d350b | ||
|
fe4d8bfa7e | ||
|
283b4f8171 | ||
|
990cbe093b | ||
|
80957d12eb | ||
|
d8dc1204c2 | ||
|
d5e94f1d97 | ||
|
9ace4dc585 | ||
|
2ac9c0ae7c | ||
|
914383a581 | ||
|
45a43e85d8 | ||
|
08d184b0fa | ||
|
d6a17c1fe7 | ||
|
ba03a05d27 | ||
|
17d066a980 | ||
|
b574a0294c | ||
|
4fb06b00b7 | ||
|
3d70d87b57 | ||
|
f55d747bb4 | ||
|
c5f13dd327 | ||
|
e406308244 | ||
|
15556319d9 | ||
|
7a21119d17 | ||
|
5a09105c3c | ||
|
48c2ca9dfe | ||
|
d6ed21f3f2 | ||
|
929013388f | ||
|
d844f82f56 | ||
|
f7d16fc626 | ||
|
9eb30b5d8e | ||
|
544e0900e6 | ||
|
c26ded6025 | ||
|
1c73b7ab19 | ||
|
472b36877c | ||
|
66b6a5e1f3 | ||
|
8acba2db02 | ||
|
bf4e26a0b8 | ||
|
7c4b6cde8b | ||
|
7f08efb04c | ||
|
6ca926c146 | ||
|
a7b673a1b6 | ||
|
03f315f7b7 | ||
|
76752800c2 | ||
|
23f872d138 | ||
|
92730af7a4 | ||
|
80f4c07bc5 | ||
|
dc0561c8bf | ||
|
9c9dcb1e35 | ||
|
b083e223e2 | ||
|
88243d296c | ||
|
53c60419b4 | ||
|
45515b7072 | ||
|
cc4579ee04 | ||
|
6d0a965db2 | ||
|
629a909b65 | ||
|
331bea8b22 | ||
|
9b4743c028 | ||
|
6623e7fe1d | ||
|
9d64579dea | ||
|
092f583422 | ||
|
8b7f215309 | ||
|
31f0e7b882 | ||
|
ee3b351419 | ||
|
99861a8c10 | ||
|
8104facb30 | ||
|
e53db0775a | ||
|
8aef7b5659 | ||
|
9e11624693 | ||
|
e6bdecbfee |
1
.github/setup-exiftool.sh
vendored
1
.github/setup-exiftool.sh
vendored
@@ -10,5 +10,4 @@
|
||||
#
|
||||
set -e
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y parallel libimage-exiftool-perl
|
||||
|
143
.github/setup-sphinx.sh
vendored
Executable file
143
.github/setup-sphinx.sh
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
set -e
|
||||
set -x
|
||||
|
||||
sudo apt-get install -q -y sphinxsearch
|
||||
|
||||
DIR=$(dirname "$0")
|
||||
|
||||
SPHINX_DAEMON_HOST="localhost"
|
||||
SPHINX_DAEMON_PORT="9312"
|
||||
SPHINX_CONF="$DIR/sphinx.conf"
|
||||
SPHINX_DATA_DIR="/var/run/sphinxsearch"
|
||||
SPHINX_LOG="$SPHINX_DATA_DIR/log/searchd.log"
|
||||
SPHINX_QUERY_LOG="$SPHINX_DATA_DIR/log/sphinx-query.log"
|
||||
ID="gokw5rvjvvxp8kgj" # Randomly generated via phpBB unique_id()
|
||||
|
||||
PHPBB_TEST_DBHOST="0.0.0.0"
|
||||
PHPBB_TEST_DBNAME="phpbb_tests"
|
||||
PHPBB_TEST_DBUSER="root"
|
||||
PHPBB_TEST_DBPASSWD=""
|
||||
|
||||
sudo service sphinxsearch stop
|
||||
sudo mkdir -p "$SPHINX_DATA_DIR/log"
|
||||
sudo chown "sphinxsearch" "$SPHINX_DATA_DIR/log"
|
||||
|
||||
# Generate configuration file for Sphinx
|
||||
echo "
|
||||
source source_phpbb_${ID}_main
|
||||
{
|
||||
type = mysql # mysql or pgsql
|
||||
sql_host = $PHPBB_TEST_DBHOST
|
||||
sql_user = $PHPBB_TEST_DBUSER
|
||||
sql_pass = $PHPBB_TEST_DBPASSWD
|
||||
sql_db = $PHPBB_TEST_DBNAME
|
||||
sql_port =
|
||||
sql_query_pre = SET NAMES 'utf8'
|
||||
sql_query_pre = UPDATE phpbb_sphinx SET max_doc_id = (SELECT MAX(post_id) FROM phpbb_posts) WHERE counter_id = 1
|
||||
sql_query_range = SELECT MIN(post_id), MAX(post_id) FROM phpbb_posts
|
||||
sql_range_step = 5000
|
||||
sql_query = SELECT \
|
||||
p.post_id AS id, \
|
||||
p.forum_id, \
|
||||
p.topic_id, \
|
||||
p.poster_id, \
|
||||
p.post_visibility, \
|
||||
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \
|
||||
p.post_time, \
|
||||
p.post_subject, \
|
||||
p.post_subject as title, \
|
||||
p.post_text as data, \
|
||||
t.topic_last_post_time, \
|
||||
0 as deleted \
|
||||
FROM phpbb_posts p, phpbb_topics t \
|
||||
WHERE \
|
||||
p.topic_id = t.topic_id \
|
||||
AND p.post_id >= \$start AND p.post_id <= \$end
|
||||
sql_query_post =
|
||||
sql_query_post_index = UPDATE phpbb_sphinx SET max_doc_id = \$maxid WHERE counter_id = 1
|
||||
sql_attr_uint = forum_id
|
||||
sql_attr_uint = topic_id
|
||||
sql_attr_uint = poster_id
|
||||
sql_attr_uint = post_visibility
|
||||
sql_attr_bool = topic_first_post
|
||||
sql_attr_bool = deleted
|
||||
sql_attr_timestamp = post_time
|
||||
sql_attr_timestamp = topic_last_post_time
|
||||
sql_attr_string = post_subject
|
||||
}
|
||||
source source_phpbb_${ID}_delta : source_phpbb_${ID}_main
|
||||
{
|
||||
sql_query_pre = SET NAMES 'utf8'
|
||||
sql_query_range =
|
||||
sql_range_step =
|
||||
sql_query = SELECT \
|
||||
p.post_id AS id, \
|
||||
p.forum_id, \
|
||||
p.topic_id, \
|
||||
p.poster_id, \
|
||||
p.post_visibility, \
|
||||
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \
|
||||
p.post_time, \
|
||||
p.post_subject, \
|
||||
p.post_subject as title, \
|
||||
p.post_text as data, \
|
||||
t.topic_last_post_time, \
|
||||
0 as deleted \
|
||||
FROM phpbb_posts p, phpbb_topics t \
|
||||
WHERE \
|
||||
p.topic_id = t.topic_id \
|
||||
AND p.post_id >= ( SELECT max_doc_id FROM phpbb_sphinx WHERE counter_id=1 )
|
||||
sql_query_post_index =
|
||||
}
|
||||
index index_phpbb_${ID}_main
|
||||
{
|
||||
path = $SPHINX_DATA_DIR/index_phpbb_${ID}_main
|
||||
source = source_phpbb_${ID}_main
|
||||
docinfo = extern
|
||||
morphology = none
|
||||
stopwords =
|
||||
wordforms =
|
||||
exceptions =
|
||||
min_word_len = 2
|
||||
charset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF
|
||||
ignore_chars = U+0027, U+002C
|
||||
min_prefix_len = 3
|
||||
min_infix_len = 0
|
||||
html_strip = 1
|
||||
index_exact_words = 0
|
||||
blend_chars = U+23, U+24, U+25, U+26, U+40
|
||||
}
|
||||
index index_phpbb_${ID}_delta : index_phpbb_${ID}_main
|
||||
{
|
||||
path = $SPHINX_DATA_DIR/index_phpbb_${ID}_delta
|
||||
source = source_phpbb_${ID}_delta
|
||||
}
|
||||
indexer
|
||||
{
|
||||
mem_limit = 512M
|
||||
}
|
||||
searchd
|
||||
{
|
||||
listen = $SPHINX_DAEMON_PORT
|
||||
log = $SPHINX_LOG
|
||||
query_log = $SPHINX_QUERY_LOG
|
||||
read_timeout = 5
|
||||
max_children = 30
|
||||
pid_file = $SPHINX_DATA_DIR/searchd.pid
|
||||
binlog_path = $SPHINX_DATA_DIR
|
||||
}
|
||||
" > $SPHINX_CONF
|
||||
|
||||
sudo mv "$SPHINX_CONF" "/etc/sphinxsearch/sphinx.conf"
|
||||
sudo sed -i "s/START=no/START=yes/g" "/etc/default/sphinxsearch"
|
||||
sudo chmod 777 "/var/run/sphinxsearch"
|
1
.github/setup-unbuffer.sh
vendored
1
.github/setup-unbuffer.sh
vendored
@@ -10,5 +10,4 @@
|
||||
#
|
||||
set -e
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y expect-dev
|
||||
|
1
.github/setup-webserver.sh
vendored
1
.github/setup-webserver.sh
vendored
@@ -11,7 +11,6 @@
|
||||
set -e
|
||||
set -x
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y nginx coreutils
|
||||
|
||||
sudo service nginx stop
|
||||
|
70
.github/workflows/check_merge_to_master.yml
vendored
Normal file
70
.github/workflows/check_merge_to_master.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
name: Check merge to master
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [ opened, synchronize, reopened ]
|
||||
branches:
|
||||
- 3.3.x
|
||||
|
||||
jobs:
|
||||
merge-check:
|
||||
if: github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == '3.3.x'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Ensure full history is fetched
|
||||
|
||||
- name: Set up Git user
|
||||
run: |
|
||||
git config --global user.name "github-actions"
|
||||
git config --global user.email "github-actions@github.com"
|
||||
|
||||
- name: Fetch all branches
|
||||
run: git fetch origin
|
||||
|
||||
- name: Simulate merging PR into 3.3.x
|
||||
id: simulate_merge
|
||||
run: |
|
||||
git checkout 3.3.x
|
||||
git fetch origin pull/${{ github.event.pull_request.number }}/head
|
||||
git merge --no-ff FETCH_HEAD || exit 1
|
||||
|
||||
- name: Attempt to merge updated 3.3.x into master
|
||||
id: merge_master
|
||||
run: |
|
||||
git checkout master
|
||||
if git merge --no-ff 3.3.x --no-commit; then
|
||||
echo "mergeable=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "mergeable=false" >> $GITHUB_OUTPUT
|
||||
git merge --abort
|
||||
fi
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: The attempt to merge branch `3.3.x` into `master` has completed
|
||||
|
||||
- name: Post comment on PR
|
||||
if: always() # Ensure this step always runs, regardless of merge result
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
body: |
|
||||
The attempt to merge branch `3.3.x` into `master` has completed after considering the changes in this PR.
|
||||
|
||||
- Merge result: ${{ steps.merge_master.outputs.mergeable == 'true' && 'Success ✅' || 'Conflict ❌' }}
|
||||
|
||||
${{ steps.merge_master.outputs.mergeable == 'true' && 'This PR is ready to be merged.' || 'A separate PR will be needed to merge `3.3.x` into `master`.' }}
|
||||
|
||||
- name: Mark job as succeeded
|
||||
if: always()
|
||||
run: echo "Merge check completed. Ignoring the result to avoid failed status."
|
60
.github/workflows/merge_3.3.x_to_master.yml
vendored
Normal file
60
.github/workflows/merge_3.3.x_to_master.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: Merge 3.3.x into master
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 3.3.x
|
||||
|
||||
jobs:
|
||||
merge-branch:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.MERGE_MASTER_APP_ID }}
|
||||
private-key: ${{ secrets.MERGE_MASTER_SECRET }}
|
||||
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch full history for proper merging
|
||||
ref: 3.3.x # Checkout the 3.3.x branch
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Fetch the latest commit information
|
||||
id: get-commit-info
|
||||
run: |
|
||||
# Get the latest commit SHA and its author details
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
COMMIT_AUTHOR_NAME=$(git log -1 --pretty=format:'%an' $COMMIT_SHA)
|
||||
COMMIT_AUTHOR_EMAIL=$(git log -1 --pretty=format:'%ae' $COMMIT_SHA)
|
||||
|
||||
# Save them as output for later steps
|
||||
echo "commit_sha=$COMMIT_SHA" >> $GITHUB_ENV
|
||||
echo "commit_author_name=$COMMIT_AUTHOR_NAME" >> $GITHUB_ENV
|
||||
echo "commit_author_email=$COMMIT_AUTHOR_EMAIL" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Git with the pull request author's info
|
||||
run: |
|
||||
git config --global user.name "${{ env.commit_author_name }}"
|
||||
git config --global user.email "${{ env.commit_author_email }}"
|
||||
|
||||
- name: Fetch all branches
|
||||
run: git fetch --all
|
||||
|
||||
- name: Merge 3.3.x into master
|
||||
run: |
|
||||
git checkout master
|
||||
if git merge --no-ff 3.3.x; then
|
||||
echo "merge_failed=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "merge_failed=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Push changes to master if merge was successful
|
||||
if: env.merge_failed == 'false'
|
||||
run: git push origin master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
32
.github/workflows/tests.yml
vendored
32
.github/workflows/tests.yml
vendored
@@ -28,6 +28,10 @@ jobs:
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.db }}
|
||||
|
||||
steps:
|
||||
- name: Update Ubuntu package lists
|
||||
run: |
|
||||
sudo apt-get update -y --allow-releaseinfo-change
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -158,6 +162,10 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Update Ubuntu package lists
|
||||
run: |
|
||||
sudo apt-get update -y --allow-releaseinfo-change
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -211,6 +219,10 @@ jobs:
|
||||
run: |
|
||||
.github/setup-ldap.sh
|
||||
|
||||
- name: Setup SPHINX
|
||||
run: |
|
||||
.github/setup-sphinx.sh
|
||||
|
||||
- name: Lint tests
|
||||
if: ${{ matrix.SLOWTESTS != 1 && steps.database-type.outputs.db == 'mysql' }}
|
||||
run: phpBB/vendor/bin/phpunit tests/lint_test.php
|
||||
@@ -295,6 +307,10 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Update Ubuntu package lists
|
||||
run: |
|
||||
sudo apt-get update -y --allow-releaseinfo-change
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -358,17 +374,17 @@ jobs:
|
||||
- php: '7.2'
|
||||
db: "sqlite3"
|
||||
- php: '7.2'
|
||||
db: "mcr.microsoft.com/mssql/server:2017-latest"
|
||||
db_alias: 'MSSQL 2017'
|
||||
- php: '7.2'
|
||||
db: "mcr.microsoft.com/mssql/server:2019-latest"
|
||||
db: "mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04"
|
||||
db_alias: 'MSSQL 2019'
|
||||
- php: '7.2'
|
||||
db: "mcr.microsoft.com/mssql/server:2022-CU13-ubuntu-22.04"
|
||||
db_alias: 'MSSQL 2022'
|
||||
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.db_alias != '' && matrix.db_alias || matrix.db }}
|
||||
|
||||
services:
|
||||
mssql:
|
||||
image: ${{ matrix.db != 'mcr.microsoft.com/mssql/server:2017-latest' && matrix.db != 'mcr.microsoft.com/mssql/server:2019-latest' && 'mcr.microsoft.com/mssql/server:2017-latest' || matrix.db }}
|
||||
image: ${{ matrix.db != 'mcr.microsoft.com/mssql/server:2022-CU13-ubuntu-22.04' && matrix.db != 'mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04' && 'mcr.microsoft.com/mssql/server:2022-CU13-ubuntu-22.04' || matrix.db }}
|
||||
env:
|
||||
SA_PASSWORD: "Pssw0rd_12"
|
||||
ACCEPT_EULA: "y"
|
||||
@@ -393,6 +409,10 @@ jobs:
|
||||
|
||||
|
||||
steps:
|
||||
- name: Update Ubuntu package lists
|
||||
run: |
|
||||
sudo apt-get update -y --allow-releaseinfo-change
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -400,7 +420,7 @@ jobs:
|
||||
env:
|
||||
MATRIX_DB: ${{ matrix.db }}
|
||||
run: |
|
||||
if [ $MATRIX_DB == 'mcr.microsoft.com/mssql/server:2017-latest' ] || [ $MATRIX_DB == 'mcr.microsoft.com/mssql/server:2019-latest' ]
|
||||
if [ $MATRIX_DB == 'mcr.microsoft.com/mssql/server:2022-CU13-ubuntu-22.04' ] || [ $MATRIX_DB == 'mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04' ]
|
||||
then
|
||||
db='mssql'
|
||||
else
|
||||
|
@@ -42,8 +42,8 @@ We have unit and functional tests in order to prevent regressions. You can view
|
||||
|
||||
Branch | Description | GitHub Actions |
|
||||
------- | ----------- | -------------- |
|
||||
**master** | Latest development version |  |
|
||||
**3.3.x** | Development of version 3.3.x |  |
|
||||
**master** | Latest development version |  |
|
||||
**3.3.x** | Development of version 3.3.x |  |
|
||||
|
||||
## 📜 License
|
||||
|
||||
|
13
SECURITY.md
Normal file
13
SECURITY.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please do not post potential security vulnerabilities publicly. Instead, report them to the phpBB team.
|
||||
We take security very seriously and will respond to reports about potential security vulnerabilities as quickly as possible.
|
||||
There are multiple ways a potential security vulnerability can be reported:
|
||||
|
||||
- HackerOne: [phpBB | Vulnerability Disclosure Program | HackerOne](https://hackerone.com/phpbb)
|
||||
- Create a report in the security tracker: [Security Tracker](https://www.phpbb.com/security/)
|
||||
- Send an email: [security@phpbb.com](mailto:security@phpbb.com)
|
||||
|
||||
Please provide as much detail as possible when reporting a vulnerability. You can expect to receive an update on your report within a few days. If the vulnerability is accepted, we will work on a fix and keep you informed of the progress. If the vulnerability is declined, we will provide an explanation.
|
@@ -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.13-RC1" />
|
||||
<property name="prevversion" value="3.3.12" />
|
||||
<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, 3.3.5, 3.3.6, 3.3.7, 3.3.8, 3.3.9, 3.3.10, 3.3.11" />
|
||||
<property name="newversion" value="3.3.16-dev" />
|
||||
<property name="prevversion" value="3.3.15" />
|
||||
<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, 3.3.5, 3.3.6, 3.3.7, 3.3.8, 3.3.9, 3.3.10, 3.3.11, 3.3.12, 3.3.13, 3.3.14" />
|
||||
<!-- no configuration should be needed beyond this point -->
|
||||
|
||||
<property name="oldversions" value="${olderversions}, ${prevversion}" />
|
||||
|
@@ -11,6 +11,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\Sniffs\Commenting;
|
||||
|
||||
use PHP_CodeSniffer\Files\File;
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
|
||||
@@ -21,7 +23,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
* @package code_sniffer
|
||||
* @author Manuel Pichler <mapi@phpundercontrol.org>
|
||||
*/
|
||||
class phpbb_Sniffs_Commenting_FileCommentSniff implements Sniff
|
||||
class FileCommentSniff implements Sniff
|
||||
{
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
|
@@ -11,6 +11,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\Sniffs\ControlStructures;
|
||||
|
||||
use PHP_CodeSniffer\Files\File;
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
|
||||
@@ -18,7 +20,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
* Checks that the opening brace of a control structures is on the line after.
|
||||
* From Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff
|
||||
*/
|
||||
class phpbb_Sniffs_ControlStructures_OpeningBraceBsdAllmanSniff implements Sniff
|
||||
class OpeningBraceBsdAllmanSniff implements Sniff
|
||||
{
|
||||
/**
|
||||
* Registers the tokens that this sniff wants to listen for.
|
||||
|
@@ -10,6 +10,7 @@
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
namespace phpbb\Sniffs\ControlStructures;
|
||||
|
||||
use PHP_CodeSniffer\Files\File;
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
@@ -18,7 +19,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
* Checks that there is exactly one space between the keyword and the opening
|
||||
* parenthesis of a control structures.
|
||||
*/
|
||||
class phpbb_Sniffs_ControlStructures_OpeningParenthesisSniff implements Sniff
|
||||
class OpeningParenthesisSniff implements Sniff
|
||||
{
|
||||
/**
|
||||
* Registers the tokens that this sniff wants to listen for.
|
||||
|
@@ -11,6 +11,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\Sniffs\ControlStructures;
|
||||
|
||||
use PHP_CodeSniffer\Files\File;
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
|
||||
@@ -18,7 +20,7 @@ use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
* Checks that the visibility qualifiers are placed after the static keyword
|
||||
* according to the coding guidelines
|
||||
*/
|
||||
class phpbb_Sniffs_ControlStructures_StaticKeywordSniff implements Sniff
|
||||
class StaticKeywordSniff implements Sniff
|
||||
{
|
||||
/**
|
||||
* Registers the tokens that this sniff wants to listen for.
|
||||
|
@@ -11,13 +11,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\Sniffs\Namespaces;
|
||||
|
||||
use PHP_CodeSniffer\Files\File;
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
|
||||
/**
|
||||
* Checks that each use statement is used.
|
||||
*/
|
||||
class phpbb_Sniffs_Namespaces_UnusedUseSniff implements Sniff
|
||||
class UnusedUseSniff implements Sniff
|
||||
{
|
||||
const FIND = [
|
||||
T_NS_SEPARATOR,
|
||||
|
@@ -17,9 +17,6 @@
|
||||
<!-- There MUST not be more than one statement per line. -->
|
||||
<rule ref="Generic.Formatting.DisallowMultipleStatements" />
|
||||
|
||||
<!-- Call-time pass-by-reference MUST not be used. -->
|
||||
<rule ref="Generic.Functions.CallTimePassByReference.NotAllowed" />
|
||||
|
||||
<!-- Filenames MUST be lowercase. -->
|
||||
<rule ref="Generic.Files.LowercasedFilename" />
|
||||
|
||||
|
@@ -42,59 +42,52 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- IF .enabled -->
|
||||
<tr>
|
||||
<td class="row3" colspan="4"><strong>{L_EXTENSIONS_ENABLED}</strong><!-- EVENT acp_ext_list_enabled_title_after --></td>
|
||||
</tr>
|
||||
<!-- BEGIN enabled -->
|
||||
<tr class="ext_enabled row-highlight">
|
||||
<td><strong title="{enabled.NAME}">{enabled.META_DISPLAY_NAME}</strong><!-- EVENT acp_ext_list_enabled_name_after --></td>
|
||||
<td style="text-align: center;">
|
||||
<!-- IF enabled.S_VERSIONCHECK -->
|
||||
<strong class="<!-- IF enabled.S_UP_TO_DATE -->current-ext<!-- ELSE -->outdated-ext<!-- ENDIF -->">{enabled.META_VERSION}</strong>
|
||||
<!-- IF not enabled.S_UP_TO_DATE --><i class="fa fa-exclamation-circle outdated-ext" aria-hidden="true"></i><!-- ENDIF -->
|
||||
<!-- ELSE -->
|
||||
{enabled.META_VERSION}
|
||||
<!-- ENDIF -->
|
||||
</td>
|
||||
<td style="text-align: center;"><a href="{enabled.U_DETAILS}">{L_DETAILS}</a></td>
|
||||
<td style="text-align: center;">
|
||||
<!-- BEGIN actions -->
|
||||
<a href="{enabled.actions.U_ACTION}"<!-- IF enabled.actions.L_ACTION_EXPLAIN --> title="{enabled.actions.L_ACTION_EXPLAIN}"<!-- ENDIF -->>{enabled.actions.L_ACTION}</a>
|
||||
<!-- IF not enabled.actions.S_LAST_ROW --> | <!-- ENDIF -->
|
||||
<!-- END actions -->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END enabled -->
|
||||
<!-- ENDIF -->
|
||||
|
||||
<!-- IF .disabled -->
|
||||
<tr>
|
||||
<td class="row3" colspan="4"><strong>{L_EXTENSIONS_DISABLED}</strong><!-- EVENT acp_ext_list_disabled_title_after --></td>
|
||||
</tr>
|
||||
<!-- BEGIN disabled -->
|
||||
<tr class="ext_disabled row-highlight">
|
||||
<td><strong title="{disabled.NAME}">{disabled.META_DISPLAY_NAME}</strong><!-- EVENT acp_ext_list_disabled_name_after --></td>
|
||||
<td style="text-align: center;">
|
||||
<!-- IF disabled.S_VERSIONCHECK -->
|
||||
<strong class="<!-- IF disabled.S_UP_TO_DATE -->current-ext<!-- ELSE -->outdated-ext<!-- ENDIF -->">{disabled.META_VERSION}</strong>
|
||||
<!-- IF not disabled.S_UP_TO_DATE --><i class="fa fa-exclamation-circle outdated-ext" aria-hidden="true"></i><!-- ENDIF -->
|
||||
<!-- ELSE -->
|
||||
{disabled.META_VERSION}
|
||||
<!-- ENDIF -->
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
<!-- IF disabled.U_DETAILS --><a href="{disabled.U_DETAILS}">{L_DETAILS}</a><!-- ENDIF -->
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
<!-- BEGIN actions -->
|
||||
<a href="{disabled.actions.U_ACTION}"<!-- IF disabled.actions.L_ACTION_EXPLAIN --> title="{disabled.actions.L_ACTION_EXPLAIN}"<!-- ENDIF -->>{disabled.actions.L_ACTION}</a>
|
||||
<!-- IF not disabled.actions.S_LAST_ROW --> | <!-- ENDIF -->
|
||||
<!-- END actions -->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END disabled -->
|
||||
<!-- ENDIF -->
|
||||
{% for list in ['enabled', 'disabled', 'not_installed'] %}
|
||||
{% set blockname = attribute(loops, list) %}
|
||||
{% if blockname|length %}
|
||||
<tr>
|
||||
<td class="row3" colspan="4"><strong>{{ lang('EXTENSIONS_' ~ list|upper) }}</strong>
|
||||
{% if list == 'enabled' %}
|
||||
{% EVENT acp_ext_list_enabled_title_after %}
|
||||
{% elseif list == 'disabled' %}
|
||||
{% EVENT acp_ext_list_disabled_title_after %}
|
||||
{% elseif list == 'not_installed' %}
|
||||
{% EVENT acp_ext_list_not_installed_title_after %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% for data in blockname %}
|
||||
<tr class="ext_{{ list }} row-highlight">
|
||||
<td><strong title="{{ data.NAME }}">{{ data.META_DISPLAY_NAME }}</strong>
|
||||
{% if list == 'enabled' %}
|
||||
{% EVENT acp_ext_list_enabled_name_after %}
|
||||
{% elseif list == 'disabled' %}
|
||||
{% EVENT acp_ext_list_disabled_name_after %}
|
||||
{% elseif list == 'not_installed' %}
|
||||
{% EVENT acp_ext_list_not_installed_name_after %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
{% if data.S_VERSIONCHECK %}
|
||||
<strong class="{% if data.S_UP_TO_DATE %}current-ext{% else %}outdated-ext{% endif %}">{{ data.META_VERSION }}</strong>
|
||||
{% if not data.S_UP_TO_DATE %}<i class="fa fa-exclamation-circle outdated-ext" aria-hidden="true"></i>{% endif %}
|
||||
{% else %}
|
||||
{{ data.META_VERSION }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
{% if data.U_DETAILS %}<a href="{{ data.U_DETAILS }}">{{ lang ('DETAILS') }}</a>{% endif %}
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
{% for actions in data.actions %}
|
||||
<a href="{{ actions.U_ACTION }}"{% if actions.L_ACTION_EXPLAIN %} title="{{ actions.L_ACTION_EXPLAIN }}"{% endif %}>{{ actions.L_ACTION }}</a>
|
||||
{% if not actions.S_LAST_ROW %} | {% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@@ -44,7 +44,7 @@
|
||||
<div id="posts"<!-- IF S_SPECIAL_RANK --> style="display: none;"<!-- ENDIF -->>
|
||||
<dl>
|
||||
<dt><label for="min_posts">{L_RANK_MINIMUM}{L_COLON}</label></dt>
|
||||
<dd><input name="min_posts" type="number" id="min_posts" min="0" max="9999999999" value="{MIN_POSTS}" /></dd>
|
||||
<dd><input name="min_posts" type="number" id="min_posts" min="0" max="16777215" value="{MIN_POSTS}" /></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
/**
|
||||
* Parse document block
|
||||
*/
|
||||
function parse_document(container)
|
||||
function parse_document(container)
|
||||
{
|
||||
var test = document.createElement('div'),
|
||||
oldBrowser = (typeof test.style.borderRadius == 'undefined');
|
||||
@@ -90,7 +90,7 @@ function parse_document(container)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
headersLength = headers.length;
|
||||
|
||||
// Add header text to each cell as <dfn>
|
||||
@@ -121,8 +121,8 @@ function parse_document(container)
|
||||
}
|
||||
|
||||
if ((text.length && text !== '-') || cell.children().length) {
|
||||
if (headers[column] != '') {
|
||||
cell.prepend('<dfn style="display: none;">' + headers[column] + '</dfn>');
|
||||
if (headers[column].length) {
|
||||
cell.prepend($("<dfn>").css('display', 'none').text(headers[column]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -143,7 +143,7 @@ function parse_document(container)
|
||||
*/
|
||||
container.find('table.responsive > tbody').each(function() {
|
||||
var items = $(this).children('tr');
|
||||
if (items.length == 0)
|
||||
if (!items.length)
|
||||
{
|
||||
$(this).parent('table:first').addClass('responsive-hide');
|
||||
}
|
||||
@@ -157,7 +157,7 @@ function parse_document(container)
|
||||
if ($this.html() == ' ') {
|
||||
$this.addClass('responsive-hide');
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -184,7 +184,7 @@ function parse_document(container)
|
||||
var width = $body.width(),
|
||||
height = $this.height();
|
||||
|
||||
if (arguments.length == 0 && (!responsive || width <= lastWidth) && height <= maxHeight) {
|
||||
if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -235,14 +235,20 @@ function submitPermissions() {
|
||||
if ($alertBoxLink) {
|
||||
// Remove forum_id[] from URL
|
||||
$alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, ''));
|
||||
var previousPageForm = '<form action="' + $alertBoxLink.attr('href') + '" method="post">';
|
||||
$.each(forumIds, function (key, value) {
|
||||
previousPageForm += '<input type="text" name="forum_id[]" value="' + value + '" />';
|
||||
const $previousPageForm = $('<form>').attr({
|
||||
action: $alertBoxLink.attr('href'),
|
||||
method: 'post'
|
||||
});
|
||||
|
||||
$.each(forumIds, function (key, value) {
|
||||
$previousPageForm.append($('<input>').attr({
|
||||
type: 'text',
|
||||
name: 'forum_id[]',
|
||||
value: value
|
||||
}));
|
||||
});
|
||||
previousPageForm += '</form>';
|
||||
|
||||
$alertBoxLink.on('click', function (e) {
|
||||
var $previousPageForm = $(previousPageForm);
|
||||
$('body').append($previousPageForm);
|
||||
e.preventDefault();
|
||||
$previousPageForm.submit();
|
||||
@@ -257,12 +263,19 @@ function submitPermissions() {
|
||||
setTimeout(function () {
|
||||
// Create forum to submit using POST. This will prevent
|
||||
// exceeding the maximum length of URLs
|
||||
var form = '<form action="' + res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, '') + '" method="post">';
|
||||
$.each(forumIds, function (key, value) {
|
||||
form += '<input type="text" name="forum_id[]" value="' + value + '" />';
|
||||
const $form = $('<form>').attr({
|
||||
action: res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, ''),
|
||||
method: 'post'
|
||||
});
|
||||
form += '</form>';
|
||||
$form = $(form);
|
||||
|
||||
$.each(forumIds, function (key, value) {
|
||||
$form.append($('<input>').attr({
|
||||
type: 'text',
|
||||
name: 'forum_id[]',
|
||||
value: value
|
||||
}));
|
||||
});
|
||||
|
||||
$('body').append($form);
|
||||
|
||||
// Hide the alert even if we refresh the page, in case the user
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<form method="post" action="#" id="language_selector">
|
||||
<fieldset class="nobg">
|
||||
<label for="language">{L_SELECT_LANG}{L_COLON}</label>
|
||||
<select id="language" name="language">
|
||||
<select id="language" name="language">
|
||||
<!-- BEGIN language_select_item -->
|
||||
<option value="{language_select_item.VALUE}"<!-- IF language_select_item.SELECTED --> selected="selected"<!-- ENDIF -->>{language_select_item.NAME}</option>
|
||||
<!-- END language_select_item -->
|
||||
|
16
phpBB/composer.lock
generated
16
phpBB/composer.lock
generated
@@ -4702,16 +4702,16 @@
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.10.1",
|
||||
"version": "3.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
|
||||
"reference": "8f90f7a53ce271935282967f53d0894f8f1ff877"
|
||||
"reference": "65ff2489553b83b4597e89c3b8b721487011d186"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877",
|
||||
"reference": "8f90f7a53ce271935282967f53d0894f8f1ff877",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186",
|
||||
"reference": "65ff2489553b83b4597e89c3b8b721487011d186",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4776,9 +4776,13 @@
|
||||
{
|
||||
"url": "https://opencollective.com/php_codesniffer",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/phpcsstandards",
|
||||
"type": "thanks_dev"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-22T21:24:41+00:00"
|
||||
"time": "2025-05-11T03:36:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
@@ -5106,5 +5110,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "7.2"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.2.0"
|
||||
}
|
||||
|
@@ -50,6 +50,11 @@
|
||||
<ol>
|
||||
<li><a href="#changelog">Changelog</a>
|
||||
<ul>
|
||||
<li><a href="#v3315rc1">Changes since 3.3.15-RC1</a></li>
|
||||
<li><a href="#v3314">Changes since 3.3.14</a></li>
|
||||
<li><a href="#v3314rc1">Changes since 3.3.14-RC1</a></li>
|
||||
<li><a href="#v3313">Changes since 3.3.13</a></li>
|
||||
<li><a href="#v3313rc1">Changes since 3.3.13-RC1</a></li>
|
||||
<li><a href="#v3312">Changes since 3.3.12</a></li>
|
||||
<li><a href="#v3312rc1">Changes since 3.3.12-RC1</a></li>
|
||||
<li><a href="#v3311">Changes since 3.3.11</a></li>
|
||||
@@ -170,6 +175,84 @@
|
||||
<div class="inner">
|
||||
|
||||
<div class="content">
|
||||
<a name="v3315rc1"></a><h3>Changes since 3.3.15-RC1</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17480">PHPBB-17480</a>] - PHP fatal error in version check failure</li>
|
||||
</ul>
|
||||
<h4>Security Issue</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/SECURITY-283">SECURITY-283</a>] - Use jQuery to generate HTML from page data</li>
|
||||
</ul>
|
||||
|
||||
<a name="v3314"></a><h3>Changes since 3.3.14</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17227">PHPBB-17227</a>] - Member list sorting bug - repeating users on several pages</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17381">PHPBB-17381</a>] - 'topic_views' column overflow blocks access to the topic</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17417">PHPBB-17417</a>] - Day selection not visible when no results</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17422">PHPBB-17422</a>] - Ascending posts pagination</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17436">PHPBB-17436</a>] - PHP fatal error while converting from phpBB 2.0 with Attachment MOD</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17455">PHPBB-17455</a>] - PHP warning on MySQLi connection failure</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17463">PHPBB-17463</a>] - Extra & in unread posts search pagination </li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17468">PHPBB-17468</a>] - Reset password feature is not restricted to email</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17470">PHPBB-17470</a>] - Enable feeds setting not enforced</li>
|
||||
</ul>
|
||||
<h4>Improvement</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17429">PHPBB-17429</a>] - Adding event before users have been added to a group</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17431">PHPBB-17431</a>] - Add more vars to memberlist event</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17433">PHPBB-17433</a>] - Unclear instructions in ACP, Server settings</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17443">PHPBB-17443</a>] - Various Guzzle client issues for version checks</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17446">PHPBB-17446</a>] - Add acp_account_activation_edit_add event</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17461">PHPBB-17461</a>] - Add php events for ACP main actions</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17467">PHPBB-17467</a>] - Add TLS v.1.3 support to email messenger connection</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17471">PHPBB-17471</a>] - Forum feed link in forumlist_body does not return the correct URL</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17478">PHPBB-17478</a>] - Add security policy to repository</li>
|
||||
</ul>
|
||||
|
||||
<a name="v3314rc1"></a><h3>Changes since 3.3.14-RC1</h3>
|
||||
<h4>Improvement</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17421">PHPBB-17421</a>] - Rename section for not installed extensions to not installed</li>
|
||||
</ul>
|
||||
|
||||
<a name="v3313"></a><h3>Changes since 3.3.13</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17181">PHPBB-17181</a>] - If statement to highlight Reported PMS on the view message page doesn't work.</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17383">PHPBB-17383</a>] - HELO/EHLO error while using gethostbyaddr()</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17384">PHPBB-17384</a>] - Passing E_USER_ERROR to trigger_error() is deprecated in PHP 8.4</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17385">PHPBB-17385</a>] - Version check without SSL flag for CDB extensions fails</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17386">PHPBB-17386</a>] - Incorrect trace result while tracing user-based permissions</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17387">PHPBB-17387</a>] - PHP warnings in search results</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17390">PHPBB-17390</a>] - Missing buttons for approval of new messages</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17391">PHPBB-17391</a>] - PHP warnings on attempt to create user group having name already in use</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17398">PHPBB-17398</a>] - Ajax error on deleting cookies</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17405">PHPBB-17405</a>] - Function phpbb_gmgetdate() returns incorrect result for edge cases</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17410">PHPBB-17410</a>] - UCP tabs do not work when testing out another user's permissions</li>
|
||||
</ul>
|
||||
<h4>Improvement</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-16852">PHPBB-16852</a>] - Addition of a new PHP event concerning bump topics</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17359">PHPBB-17359</a>] - Distinct disabled and not installed extensions in the list</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17376">PHPBB-17376</a>] - Link reference to quote post is a poor accessibility experience</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17382">PHPBB-17382</a>] - Incorrect grammar on FAQ page regarding searching for members</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17388">PHPBB-17388</a>] - Add php event to bump_topic_allowed function</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17394">PHPBB-17394</a>] - Check mergeability of PR on GitHub Actions</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17396">PHPBB-17396</a>] - Automatically handle merges of 3.3.x into master</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17397">PHPBB-17397</a>] - Add event for forum_data query in viewforum</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17402">PHPBB-17402</a>] - Add possibility to force reparsing BBCode via CLI</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17407">PHPBB-17407</a>] - Limit mergeability check to single comment</li>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17411">PHPBB-17411</a>] - Add core event to search.php</li>
|
||||
</ul>
|
||||
|
||||
<a name="v3313rc1"></a><h3>Changes since 3.3.13-RC1</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
<li>[<a href="https://tracker.phpbb.com/browse/PHPBB-17377">PHPBB-17377</a>] - MSSQL builds on GitHub actions broken</li>
|
||||
</ul>
|
||||
|
||||
<a name="v3312"></a><h3>Changes since 3.3.12</h3>
|
||||
<h4>Bug</h4>
|
||||
<ul>
|
||||
|
@@ -94,6 +94,20 @@ acp_ext_list_enabled_title_after
|
||||
* Since: 3.1.11-RC1
|
||||
* Purpose: Add text after enabled extensions section title.
|
||||
|
||||
acp_ext_list_not_installed_name_after
|
||||
===
|
||||
* Location: adm/style/acp_ext_list.html
|
||||
* Since: 3.3.14-RC1
|
||||
* Changed: 3.3.14 Renamed from acp_ext_list_available_name_after
|
||||
* Purpose: Add content after the name of not installed extensions in the list
|
||||
|
||||
acp_ext_list_not_installed_title_after
|
||||
===
|
||||
* Location: adm/style/acp_ext_list.html
|
||||
* Since: 3.3.14-RC1
|
||||
* Changed: 3.3.14 Renamed from acp_ext_list_available_title_after
|
||||
* Purpose: Add text after not installed extensions section title.
|
||||
|
||||
acp_forums_custom_settings
|
||||
===
|
||||
* Location: adm/style/acp_forums.html
|
||||
@@ -2792,6 +2806,13 @@ ucp_pm_viewmessage_custom_fields_before
|
||||
* Purpose: Add data before the custom fields on the user profile when viewing
|
||||
a private message
|
||||
|
||||
ucp_pm_viewmessage_message_content_before
|
||||
===
|
||||
* Locations:
|
||||
+ styles/prosilver/template/ucp_pm_viewmessage.html
|
||||
* Since: 3.3.16-RC1
|
||||
* Purpose: Add content before the private message text
|
||||
|
||||
ucp_pm_viewmessage_options_before
|
||||
===
|
||||
* Locations:
|
||||
|
@@ -1077,7 +1077,7 @@ class acp_attachments
|
||||
$attachments_per_page = (int) $config['topics_per_page'];
|
||||
|
||||
// Get total number or orphans older than 3 hours
|
||||
$sql = 'SELECT COUNT(attach_id) as num_files, SUM(filesize) as total_size
|
||||
$sql = 'SELECT COUNT(attach_id) as num_files, SUM(' . $this->db->cast_expr_to_bigint('filesize') . ') as total_size
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 1
|
||||
AND filetime < ' . (time() - 3*60*60);
|
||||
|
@@ -386,7 +386,7 @@ class acp_board
|
||||
'vars' => array(
|
||||
'legend1' => 'ACP_SERVER_SETTINGS',
|
||||
'gzip_compress' => array('lang' => 'ENABLE_GZIP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
|
||||
'use_system_cron' => array('lang' => 'USE_SYSTEM_CRON', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
|
||||
'use_system_cron' => array('lang' => 'USE_SYSTEM_CRON', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
|
||||
|
||||
'legend2' => 'PATH_SETTINGS',
|
||||
'enable_mod_rewrite' => array('lang' => 'MOD_REWRITE_ENABLE', 'validate' => 'bool', 'type' => 'custom', 'method' => 'enable_mod_rewrite', 'explain' => true),
|
||||
@@ -921,7 +921,7 @@ class acp_board
|
||||
*/
|
||||
function select_acc_activation($selected_value, $value)
|
||||
{
|
||||
global $user, $config;
|
||||
global $user, $config, $phpbb_dispatcher;
|
||||
|
||||
$act_ary = array(
|
||||
'ACC_DISABLE' => array(true, USER_ACTIVATION_DISABLE),
|
||||
@@ -931,6 +931,18 @@ class acp_board
|
||||
);
|
||||
|
||||
$act_options = '';
|
||||
|
||||
/**
|
||||
* Event to add and/or modify account activation configurations
|
||||
*
|
||||
* @event core.acp_account_activation_edit_add
|
||||
* @var array act_ary Array of account activation methods
|
||||
* @var string act_options Options available in the activation method
|
||||
* @since 3.3.15-RC1
|
||||
*/
|
||||
$vars = ['act_ary', 'act_options'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_account_activation_edit_add', compact($vars)));
|
||||
|
||||
foreach ($act_ary as $key => $data)
|
||||
{
|
||||
list($available, $value) = $data;
|
||||
|
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
use phpbb\exception\exception_interface;
|
||||
use phpbb\exception\runtime_exception;
|
||||
use phpbb\exception\version_check_exception;
|
||||
|
||||
/**
|
||||
@@ -344,7 +345,7 @@ class acp_extensions
|
||||
|
||||
$this->template->assign_block_vars('updates_available', $updates_available);
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
catch (runtime_exception $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
|
||||
@@ -423,7 +424,7 @@ class acp_extensions
|
||||
$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true;
|
||||
$enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name'));
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
catch (runtime_exception $e)
|
||||
{
|
||||
// Ignore exceptions due to the version check
|
||||
}
|
||||
@@ -433,7 +434,7 @@ class acp_extensions
|
||||
$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
catch (runtime_exception $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
@@ -501,7 +502,7 @@ class acp_extensions
|
||||
{
|
||||
$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
catch (runtime_exception $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
@@ -572,10 +573,10 @@ class acp_extensions
|
||||
{
|
||||
$available_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
catch (runtime_exception $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
$this->template->assign_block_vars('not_installed', array(
|
||||
'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
|
||||
'S_VERSIONCHECK' => false,
|
||||
));
|
||||
@@ -589,9 +590,9 @@ class acp_extensions
|
||||
$block_vars['NAME'] = $name;
|
||||
$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name);
|
||||
|
||||
$this->template->assign_block_vars('disabled', $block_vars);
|
||||
$this->template->assign_block_vars('not_installed', $block_vars);
|
||||
|
||||
$this->output_actions('disabled', array(
|
||||
$this->output_actions('not_installed', array(
|
||||
'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name),
|
||||
));
|
||||
}
|
||||
|
@@ -2071,7 +2071,7 @@ class acp_forums
|
||||
|
||||
$config->set('num_files', (int) $row['stat'], false);
|
||||
|
||||
$sql = 'SELECT SUM(filesize) as stat
|
||||
$sql = 'SELECT SUM(' . $db->cast_expr_to_bigint('filesize') . ') as stat
|
||||
FROM ' . ATTACHMENTS_TABLE;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
|
@@ -396,7 +396,7 @@ class acp_groups
|
||||
$allow_desc_urls = $request->variable('desc_parse_urls', false);
|
||||
$allow_desc_smilies = $request->variable('desc_parse_smilies', false);
|
||||
|
||||
$submit_ary = array(
|
||||
$submit_ary = [
|
||||
'colour' => $request->variable('group_colour', ''),
|
||||
'rank' => $request->variable('group_rank', 0),
|
||||
'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0,
|
||||
@@ -406,7 +406,13 @@ class acp_groups
|
||||
'max_recipients' => $request->variable('group_max_recipients', 0),
|
||||
'founder_manage' => 0,
|
||||
'skip_auth' => $request->variable('group_skip_auth', 0),
|
||||
);
|
||||
|
||||
// Initialize avatar data
|
||||
'avatar' => $avatar_data['avatar'] ?? '',
|
||||
'avatar_type' => $avatar_data['avatar_type'] ?? '',
|
||||
'avatar_height' => $avatar_data['avatar_height'] ?? 0,
|
||||
'avatar_width' => $avatar_data['avatar_width'] ?? 0,
|
||||
];
|
||||
|
||||
if ($user->data['user_type'] == USER_FOUNDER)
|
||||
{
|
||||
|
@@ -100,6 +100,20 @@ class acp_main
|
||||
default:
|
||||
$confirm = true;
|
||||
$confirm_lang = 'CONFIRM_OPERATION';
|
||||
|
||||
/**
|
||||
* Event to add confirm box for custom ACP quick actions
|
||||
*
|
||||
* @event core.acp_main_add_actions_confirm
|
||||
* @var string id The module ID
|
||||
* @var string mode The module mode
|
||||
* @var string action Custom action type name
|
||||
* @var boolean confirm Do we display the confirm box to run the custom action
|
||||
* @var string confirm_lang Lang var name to display in confirm box
|
||||
* @since 3.3.15-RC1
|
||||
*/
|
||||
$vars = ['id', 'mode', 'action', 'confirm', 'confirm_lang'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_main_add_actions_confirm', compact($vars)));
|
||||
}
|
||||
|
||||
if ($confirm)
|
||||
@@ -168,7 +182,7 @@ class acp_main
|
||||
$config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT SUM(filesize) as stat
|
||||
$sql = 'SELECT SUM(' . $db->cast_expr_to_bigint('filesize') . ') as stat
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 0';
|
||||
$result = $db->sql_query($sql);
|
||||
@@ -423,6 +437,19 @@ class acp_main
|
||||
trigger_error('PURGE_SESSIONS_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/**
|
||||
* Event to add custom ACP quick actions
|
||||
*
|
||||
* @event core.acp_main_add_actions
|
||||
* @var string id The module ID
|
||||
* @var string mode The module mode
|
||||
* @var string action Custom action type name
|
||||
* @since 3.3.15-RC1
|
||||
*/
|
||||
$vars = ['id', 'mode', 'action'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_main_add_actions', compact($vars)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,7 +485,7 @@ class acp_main
|
||||
'UPGRADE_INSTRUCTIONS' => !empty($upgrades_available) ? $user->lang('UPGRADE_INSTRUCTIONS', $upgrades_available['current'], $upgrades_available['announcement']) : false,
|
||||
));
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
catch (\phpbb\exception\runtime_exception $e)
|
||||
{
|
||||
$message = call_user_func_array(array($user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$template->assign_vars(array(
|
||||
|
@@ -28,7 +28,7 @@ if (!defined('IN_PHPBB'))
|
||||
*/
|
||||
|
||||
// phpBB Version
|
||||
@define('PHPBB_VERSION', '3.3.13-RC1');
|
||||
@define('PHPBB_VERSION', '3.3.16-dev');
|
||||
|
||||
// QA-related
|
||||
// define('PHPBB_QA', 1);
|
||||
|
@@ -107,9 +107,17 @@ function phpbb_gmgetdate($time = false)
|
||||
}
|
||||
|
||||
// getdate() interprets timestamps in local time.
|
||||
// What follows uses the fact that getdate() and
|
||||
// date('Z') balance each other out.
|
||||
return getdate($time - date('Z'));
|
||||
// So use UTC timezone temporarily to get UTC date info array.
|
||||
$current_timezone = date_default_timezone_get();
|
||||
|
||||
// Set UTC timezone and get respective date info
|
||||
date_default_timezone_set('UTC');
|
||||
$date_info = getdate($time);
|
||||
|
||||
// Restore timezone back
|
||||
date_default_timezone_set($current_timezone);
|
||||
|
||||
return $date_info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -289,7 +289,27 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list
|
||||
*/
|
||||
function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_poster, $last_topic_poster)
|
||||
{
|
||||
global $config, $auth, $user;
|
||||
global $config, $auth, $user, $phpbb_dispatcher;
|
||||
|
||||
/**
|
||||
* Event to run code before the topic bump checks
|
||||
*
|
||||
* @event core.bump_topic_allowed_before
|
||||
* @var int forum_id ID of the forum
|
||||
* @var int topic_bumped Flag indicating if the topic was already bumped (0/1)
|
||||
* @var int last_post_time The time of the topic last post
|
||||
* @var int topic_poster User ID of the topic author
|
||||
* @var int last_topic_poster User ID of the topic last post author
|
||||
* @since 3.3.14-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'forum_id',
|
||||
'topic_bumped',
|
||||
'last_post_time',
|
||||
'topic_poster',
|
||||
'last_topic_poster',
|
||||
];
|
||||
extract($phpbb_dispatcher->trigger_event('core.bump_topic_allowed_before', compact($vars)));
|
||||
|
||||
// Check permission and make sure the last post was not already bumped
|
||||
if (!$auth->acl_get('f_bump', $forum_id) || $topic_bumped)
|
||||
@@ -312,6 +332,28 @@ function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_po
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event to run code after the topic bump checks
|
||||
*
|
||||
* @event core.bump_topic_allowed_after
|
||||
* @var int forum_id ID of the forum
|
||||
* @var int topic_bumped Flag indicating if the topic was already bumped (0/1)
|
||||
* @var int last_post_time The time of the topic last post
|
||||
* @var int topic_poster User ID of the topic author
|
||||
* @var int last_topic_poster User ID of the topic last post author
|
||||
* @var int bump_time Bump time range
|
||||
* @since 3.3.14-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'forum_id',
|
||||
'topic_bumped',
|
||||
'last_post_time',
|
||||
'topic_poster',
|
||||
'last_topic_poster',
|
||||
'bump_time',
|
||||
];
|
||||
extract($phpbb_dispatcher->trigger_event('core.bump_topic_allowed_after', compact($vars)));
|
||||
|
||||
// A bump time of 0 will completely disable the bump feature... not intended but might be useful.
|
||||
return $bump_time;
|
||||
}
|
||||
@@ -329,14 +371,14 @@ function get_context(string $text, array $words, int $length = 400): string
|
||||
{
|
||||
if ($length <= 0)
|
||||
{
|
||||
return '...';
|
||||
return $text;
|
||||
}
|
||||
|
||||
// we need to turn the entities back into their original form, to not cut the message in between them
|
||||
$text = html_entity_decode($text);
|
||||
// We need to turn the entities back into their original form, to not cut the message in between them
|
||||
$text = htmlspecialchars_decode($text);
|
||||
|
||||
// Replace all spaces/invisible characters with single spaces
|
||||
$text = preg_replace("/\s+/u", ' ', $text);
|
||||
$text = preg_replace("/[\p{Z}\h\v]+/u", ' ', $text);
|
||||
|
||||
$text_length = utf8_strlen($text);
|
||||
|
||||
@@ -351,7 +393,6 @@ function get_context(string $text, array $words, int $length = 400): string
|
||||
$word_indexes[$pos] = $word;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($word_indexes))
|
||||
{
|
||||
ksort($word_indexes);
|
||||
@@ -400,23 +441,21 @@ function get_context(string $text, array $words, int $length = 400): string
|
||||
$fragment_end = $end - $start + 1;
|
||||
|
||||
// Find the first valid alphanumeric character in the fragment to don't cut words
|
||||
if ($start > 0)
|
||||
if ($start > 0 && preg_match('/[^\p{L}\p{N}][\p{L}\p{N}]/u', $fragment, $matches, PREG_OFFSET_CAPTURE))
|
||||
{
|
||||
preg_match('/[^a-zA-Z0-9][a-zA-Z0-9]/u', $fragment, $matches, PREG_OFFSET_CAPTURE);
|
||||
$fragment_start = (int) $matches[0][1] + 1; // first valid alphanumeric character
|
||||
$fragment_start = utf8_strlen(substr($fragment, 0, (int) $matches[0][1])) + 1;
|
||||
}
|
||||
|
||||
// Find the last valid alphanumeric character in the fragment to don't cut words
|
||||
if ($end < $text_length - 1)
|
||||
if ($end < $text_length - 1 && preg_match_all('/[\p{L}\p{N}][^\p{L}\p{N}]/u', $fragment, $matches, PREG_OFFSET_CAPTURE))
|
||||
{
|
||||
preg_match_all('/[a-zA-Z0-9][^a-zA-Z0-9]/u', $fragment, $matches, PREG_OFFSET_CAPTURE);
|
||||
$fragment_end = end($matches[0])[1]; // last valid alphanumeric character
|
||||
$fragment_end = utf8_strlen(substr($fragment, 0, end($matches[0])[1]));
|
||||
}
|
||||
|
||||
$output[] = utf8_substr($fragment, $fragment_start, $fragment_end - $fragment_start + 1);
|
||||
}
|
||||
|
||||
return ($fragments[0][0] !== 0 ? '... ' : '') . htmlentities(implode(' ... ', $output)) . ($end < $text_length - 1 ? ' ...' : '');
|
||||
return ($fragments[0][0] !== 0 ? '... ' : '') . utf8_htmlspecialchars(implode(' ... ', $output)) . ($end < $text_length - 1 ? ' ...' : '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1998,7 +1998,7 @@ function update_dynamic_config()
|
||||
$config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT SUM(filesize) as stat
|
||||
$sql = 'SELECT SUM(' . $db->cast_expr_to_bigint('filesize') . ') as stat
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 0';
|
||||
$result = $db->sql_query($sql);
|
||||
|
@@ -1418,22 +1418,22 @@ class smtp_class
|
||||
global $user;
|
||||
|
||||
// Here we try to determine the *real* hostname (reverse DNS entry preferrably)
|
||||
$local_host = $user->host;
|
||||
|
||||
if (function_exists('php_uname'))
|
||||
if (function_exists('php_uname') && !empty($local_host = php_uname('n')))
|
||||
{
|
||||
$local_host = php_uname('n');
|
||||
|
||||
// Able to resolve name to IP
|
||||
if (($addr = @gethostbyname($local_host)) !== $local_host)
|
||||
{
|
||||
// Able to resolve IP back to name
|
||||
if (($name = @gethostbyaddr($addr)) !== $addr)
|
||||
if (!empty($name = @gethostbyaddr($addr)) && $name !== $addr)
|
||||
{
|
||||
$local_host = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$local_host = $user->host;
|
||||
}
|
||||
|
||||
// If we are authenticating through pop-before-smtp, we
|
||||
// have to login ones before we get authenticated
|
||||
@@ -1615,12 +1615,10 @@ class smtp_class
|
||||
$result = false;
|
||||
$stream_meta = stream_get_meta_data($this->socket);
|
||||
|
||||
if (socket_set_blocking($this->socket, 1))
|
||||
if (stream_set_blocking($this->socket, 1))
|
||||
{
|
||||
// https://secure.php.net/manual/en/function.stream-socket-enable-crypto.php#119122
|
||||
$crypto = (phpbb_version_compare(PHP_VERSION, '5.6.7', '<')) ? STREAM_CRYPTO_METHOD_TLS_CLIENT : STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
|
||||
$result = stream_socket_enable_crypto($this->socket, true, $crypto);
|
||||
socket_set_blocking($this->socket, (int) $stream_meta['blocked']);
|
||||
$result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
stream_set_blocking($this->socket, (int) $stream_meta['blocked']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@@ -502,8 +502,8 @@ class p_master
|
||||
$id = $this->p_class . '_' . $id;
|
||||
}
|
||||
|
||||
// Fallback to acp main page for special restore permission mode
|
||||
if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm'))
|
||||
// Fallback to acp main page for special test permission mode
|
||||
if ($this->p_class === 'acp' && $user->data['user_perm_from'] && $auth->acl_get('a_switchperm'))
|
||||
{
|
||||
$id = '';
|
||||
$mode = '';
|
||||
|
@@ -2759,6 +2759,28 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
|
||||
return 'GROUP_USERS_EXIST';
|
||||
}
|
||||
|
||||
/**
|
||||
* Event before users are added to a group
|
||||
*
|
||||
* @event core.group_add_user_before
|
||||
* @var int group_id ID of the group to which users are added
|
||||
* @var string group_name Name of the group
|
||||
* @var array user_id_ary IDs of the users to be added
|
||||
* @var array username_ary Names of the users to be added
|
||||
* @var int pending Pending setting, 1 if user(s) added are pending
|
||||
* @var array add_id_ary IDs of the users to be added who are not members yet
|
||||
* @since 3.3.15-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'group_id',
|
||||
'group_name',
|
||||
'user_id_ary',
|
||||
'username_ary',
|
||||
'pending',
|
||||
'add_id_ary',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.group_add_user_before', compact($vars)));
|
||||
|
||||
$db->sql_transaction('begin');
|
||||
|
||||
// Insert the new users
|
||||
|
@@ -284,6 +284,7 @@ class mcp_queue
|
||||
$post_data = array(
|
||||
'S_MCP_QUEUE' => true,
|
||||
'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id"),
|
||||
'S_CAN_APPROVE' => $auth->acl_get('m_approve', $post_info['forum_id']),
|
||||
'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']),
|
||||
'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']),
|
||||
'S_POST_REPORTED' => $post_info['post_reported'],
|
||||
|
@@ -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.13',
|
||||
'phpbb_version' => '3.3.15',
|
||||
'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>',
|
||||
'dbms' => $dbms,
|
||||
'dbhost' => $dbhost,
|
||||
|
@@ -1418,9 +1418,9 @@ function phpbb_attachment_extension_group_name()
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$extension_groups_updated = array();
|
||||
while ($lang_dir = $db->sql_fetchfield('lang_dir'))
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$lang_dir = basename($lang_dir);
|
||||
$lang_dir = basename($row['lang_dir']);
|
||||
$lang_file = $phpbb_root_path . 'language/' . $lang_dir . '/acp/attachments.' . $phpEx;
|
||||
|
||||
if (!file_exists($lang_file))
|
||||
|
@@ -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.13-RC1');
|
||||
define('PHPBB_VERSION', '3.3.15');
|
||||
$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.13-RC1');
|
||||
INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.3.16-dev');
|
||||
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');
|
||||
|
||||
|
@@ -493,8 +493,8 @@ $lang = array_merge($lang, array(
|
||||
'SMILIES_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/smilies</samp>.',
|
||||
'UPLOAD_ICONS_PATH' => 'Extension group icons storage path',
|
||||
'UPLOAD_ICONS_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/upload_icons</samp>.',
|
||||
'USE_SYSTEM_CRON' => 'Run periodic tasks from system cron',
|
||||
'USE_SYSTEM_CRON_EXPLAIN' => 'When off, phpBB will arrange for periodic tasks to be run automatically. When on, phpBB will not schedule any periodic tasks by itself; a system administrator must arrange for <code>bin/phpbbcli.php cron:run</code> to be run by the system cron facility at regular intervals (e.g. every 5 minutes).',
|
||||
'USE_SYSTEM_CRON' => 'Run periodic tasks from operating system cron',
|
||||
'USE_SYSTEM_CRON_EXPLAIN' => 'When disabled, phpBB will arrange for periodic tasks to be run automatically. When enabled, phpBB will not schedule any periodic tasks by itself; a system administrator must arrange for <code>bin/phpbbcli.php cron:run</code> to be run by the operating system cron facility at regular intervals (e.g. every 5 minutes).',
|
||||
));
|
||||
|
||||
// Security Settings
|
||||
|
@@ -47,8 +47,9 @@ $lang = array_merge($lang, array(
|
||||
|
||||
'DETAILS' => 'Details',
|
||||
|
||||
'EXTENSIONS_DISABLED' => 'Disabled Extensions',
|
||||
'EXTENSIONS_ENABLED' => 'Enabled Extensions',
|
||||
'EXTENSIONS_NOT_INSTALLED' => 'Not installed Extensions',
|
||||
'EXTENSIONS_DISABLED' => 'Disabled Extensions',
|
||||
'EXTENSIONS_ENABLED' => 'Enabled Extensions',
|
||||
|
||||
'EXTENSION_DELETE_DATA' => 'Delete data',
|
||||
'EXTENSION_DISABLE' => 'Disable',
|
||||
|
@@ -75,6 +75,7 @@ $lang = array_merge($lang, array(
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN' => 'Do not save any changes; just print what would happen',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_FORCE_BBCODE' => 'Re-parse all BBCodes without exception. Note that any previously disabled BBCodes will be reprocessed, enabled, and fully rendered.',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process',
|
||||
'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time',
|
||||
|
@@ -357,6 +357,7 @@ $lang = array_merge($lang, array(
|
||||
'HIDE_ME' => 'Hide my online status this session',
|
||||
'HOURS' => 'Hours',
|
||||
'HOME' => 'Home',
|
||||
'HTTP_HANDLER_NOT_FOUND' => 'The operation could not be completed because the cURL PHP extension and allow_url_fopen PHP ini setting have been disabled and no other HTTP handler could be found.',
|
||||
|
||||
'ICQ' => 'ICQ',
|
||||
'IF' => 'If',
|
||||
|
@@ -158,7 +158,7 @@ $lang = array_merge($lang, array(
|
||||
'HELP_FAQ_SEARCH_BLANK_QUESTION' => 'Why does my search return a blank page!?',
|
||||
'HELP_FAQ_SEARCH_FORUM_ANSWER' => 'Enter a search term in the search box located on the index, forum or topic pages. Advanced search can be accessed by clicking the “Advance Search” link which is available on all pages on the forum. How to access the search may depend on the style used.',
|
||||
'HELP_FAQ_SEARCH_FORUM_QUESTION' => 'How can I search a forum or forums?',
|
||||
'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => 'Visit to the “Members” page and click the “Find a member” link.',
|
||||
'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => 'Visit the memberlist and click the “Find a member” link.',
|
||||
'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => 'How do I search for members?',
|
||||
'HELP_FAQ_SEARCH_NO_RESULT_ANSWER' => 'Your search was probably too vague and included many common terms which are not indexed by phpBB. Be more specific and use the options available within Advanced search.',
|
||||
'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => 'Why does my search return no results?',
|
||||
|
@@ -42,7 +42,7 @@ $lang = array_merge($lang, array(
|
||||
<br><br>
|
||||
Our forums are powered by phpBB (hereinafter “they”, “them”, “their”, “phpBB software”, “www.phpbb.com”, “phpBB Limited”, “phpBB Teams”) which is a bulletin board solution released under the “<a href="http://opensource.org/licenses/gpl-2.0.php">GNU General Public License v2</a>” (hereinafter “GPL”) and can be downloaded from <a href="https://www.phpbb.com/">www.phpbb.com</a>. The phpBB software only facilitates internet based discussions; phpBB Limited is not responsible for what we allow and/or disallow as permissible content and/or conduct. For further information about phpBB, please see: <a href="https://www.phpbb.com/">https://www.phpbb.com/</a>.
|
||||
<br><br>
|
||||
You agree not to post any abusive, obscene, vulgar, slanderous, hateful, threatening, sexually-orientated or any other material that may violate any laws be it of your country, the country where “%1$s” is hosted or International Law. Doing so may lead to you being immediately and permanently banned, with notification of your Internet Service Provider if deemed required by us. The IP address of all posts are recorded to aid in enforcing these conditions. You agree that “%1$s” have the right to remove, edit, move or close any topic at any time should we see fit. As a user you agree to any information you have entered to being stored in a database. While this information will not be disclosed to any third party without your consent, neither “%1$s” nor phpBB shall be held responsible for any hacking attempt that may lead to the data being compromised.
|
||||
You agree not to post any abusive, obscene, vulgar, libellous, hateful, threatening, sexually-orientated or any other material that may violate any laws be it of your country, the country where “%1$s” is hosted or International Law. Doing so may lead to you being immediately and permanently banned, with notification of your Internet Service Provider if deemed required by us. The IP address of all posts are recorded to aid in enforcing these conditions. You agree that “%1$s” have the right to remove, edit, move or close any topic at any time should we see fit. As a user you agree to any information you have entered to being stored in a database. While this information will not be disclosed to any third party without your consent, neither “%1$s” nor phpBB shall be held responsible for any hacking attempt that may lead to the data being compromised.
|
||||
',
|
||||
|
||||
'PRIVACY_POLICY' => 'This policy explains in detail how “%1$s” along with its affiliated companies (hereinafter “we”, “us”, “our”, “%1$s”, “%2$s”) and phpBB (hereinafter “they”, “them”, “their”, “phpBB software”, “www.phpbb.com”, “phpBB Limited”, “phpBB Teams”) use any information collected during any session of usage by you (hereinafter “your information”).
|
||||
|
@@ -112,6 +112,7 @@ $lang = array_merge($lang, array(
|
||||
'VIEW_INFO' => 'Post details',
|
||||
'VIEW_NEXT_TOPIC' => 'Next topic',
|
||||
'VIEW_PREVIOUS_TOPIC' => 'Previous topic',
|
||||
'VIEW_QUOTED_POST' => 'View quoted post',
|
||||
'VIEW_RESULTS' => 'View results',
|
||||
'VIEW_TOPIC_POSTS' => array(
|
||||
1 => '%d post',
|
||||
|
@@ -816,11 +816,26 @@ switch ($mode)
|
||||
* Modify user's template vars before we display the profile
|
||||
*
|
||||
* @event core.memberlist_modify_view_profile_template_vars
|
||||
* @var array template_ary Array with user's template vars
|
||||
* @var array template_ary Array with user's template vars
|
||||
* @var int user_id The user ID
|
||||
* @var bool user_notes_enabled Is the mcp user notes module enabled?
|
||||
* @var bool warn_user_enabled Is the mcp warnings module enabled?
|
||||
* @var bool friends_enabled Is the ucp friends module enabled?
|
||||
* @var bool foes_enabled Is the ucp foes module enabled?
|
||||
* @var bool friend Is the user friend?
|
||||
* @var bool foe Is the user foe?
|
||||
* @since 3.2.6-RC1
|
||||
* @changed 3.3.15-RC1 Added vars user_id, user_notes_enabled, warn_user_enabled, friend, friends_enabled, foe, foes_enabled
|
||||
*/
|
||||
$vars = array(
|
||||
'template_ary',
|
||||
'user_id',
|
||||
'user_notes_enabled',
|
||||
'warn_user_enabled',
|
||||
'friend',
|
||||
'friends_enabled',
|
||||
'foe',
|
||||
'foes_enabled',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_view_profile_template_vars', compact($vars)));
|
||||
|
||||
@@ -1375,10 +1390,10 @@ switch ($mode)
|
||||
|
||||
$order_by .= $sort_key_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC');
|
||||
|
||||
// Unfortunately we must do this here for sorting by rank, else the sort order is applied wrongly
|
||||
if ($sort_key == 'm')
|
||||
// For sorting by non-unique columns (rank, posts) add unique sort key to avoid duplicated rows in results
|
||||
if ($sort_key == 'm' || $sort_key == 'd')
|
||||
{
|
||||
$order_by .= ', u.user_posts DESC';
|
||||
$order_by .= ', u.user_id ASC';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1797,6 +1812,18 @@ switch ($mode)
|
||||
$memberrow = array_merge($memberrow, $cp_row['row']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the memberrow data before template variables are assigned.
|
||||
*
|
||||
* @event core.memberlist_modify_memberrow
|
||||
* @var int user_id The current user ID.
|
||||
* @var array row Array of raw user data.
|
||||
* @var array memberrow Array of member template variables.
|
||||
* @since 3.3.16-RC1
|
||||
*/
|
||||
$vars = ['user_id', 'row', 'memberrow'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_memberrow', compact($vars)));
|
||||
|
||||
$template->assign_block_vars('memberrow', $memberrow);
|
||||
|
||||
if (isset($cp_row['blockrow']) && count($cp_row['blockrow']))
|
||||
|
@@ -776,7 +776,7 @@ class auth
|
||||
|
||||
$sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? 'group_id = ' . (int) $group_id : $db->sql_in_set('group_id', array_map('intval', $group_id))) : '';
|
||||
$sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : '';
|
||||
$sql_is_local = $forum_id !== false ? 'AND ao.is_local <> 0' : '';
|
||||
$sql_is_local = !empty($forum_id) ? 'AND ao.is_local <> 0' : '';
|
||||
|
||||
$sql_opts = '';
|
||||
$hold_ary = $sql_ary = array();
|
||||
|
@@ -92,6 +92,12 @@ class reparse extends \phpbb\console\command\command
|
||||
InputOption::VALUE_NONE,
|
||||
$this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN')
|
||||
)
|
||||
->addOption(
|
||||
'force-bbcode-reparsing',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
$this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_FORCE_BBCODE')
|
||||
)
|
||||
->addOption(
|
||||
'resume',
|
||||
null,
|
||||
@@ -222,13 +228,15 @@ class reparse extends \phpbb\console\command\command
|
||||
|
||||
// Start from $max and decrement $current by $size until we reach $min
|
||||
$current = $max;
|
||||
|
||||
$force_bbcode_reparsing = (bool) $this->get_option('force-bbcode-reparsing');
|
||||
while ($current >= $min)
|
||||
{
|
||||
$start = max($min, $current + 1 - $size);
|
||||
$end = max($min, $current);
|
||||
|
||||
$progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $reparser->get_name(), $start, $end));
|
||||
$reparser->reparse_range($start, $end);
|
||||
$reparser->reparse_range($start, $end, $force_bbcode_reparsing);
|
||||
|
||||
$current = $start - 1;
|
||||
$progress->setProgress($max + 1 - $start);
|
||||
|
@@ -59,14 +59,17 @@ class mysqli extends \phpbb\db\driver\mysql_base
|
||||
}
|
||||
}
|
||||
|
||||
$this->db_connect_id = mysqli_init();
|
||||
|
||||
if (!@mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS))
|
||||
if (!$this->db_connect_id = mysqli_init())
|
||||
{
|
||||
$this->db_connect_id = '';
|
||||
$this->connect_error = 'Failed to initialize MySQLi object.';
|
||||
|
||||
}
|
||||
else if (!@mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS))
|
||||
{
|
||||
$this->connect_error = 'Failed to establish a connection to the MySQL database engine. Please ensure MySQL server is running and the database configuration parameters are correct.';
|
||||
}
|
||||
|
||||
if ($this->db_connect_id && $this->dbname != '')
|
||||
if (!$this->connect_error && $this->db_connect_id && $this->dbname != '')
|
||||
{
|
||||
// Disable loading local files on client side
|
||||
@mysqli_options($this->db_connect_id, MYSQLI_OPT_LOCAL_INFILE, false);
|
||||
@@ -357,15 +360,8 @@ class mysqli extends \phpbb\db\driver\mysql_base
|
||||
if ($this->db_connect_id)
|
||||
{
|
||||
$error = [
|
||||
'message' => $this->db_connect_id->error,
|
||||
'code' => $this->db_connect_id->errno,
|
||||
];
|
||||
}
|
||||
else if (function_exists('mysqli_connect_error'))
|
||||
{
|
||||
$error = [
|
||||
'message' => $this->db_connect_id->connect_error,
|
||||
'code' => $this->db_connect_id->connect_errno,
|
||||
'message' => $this->db_connect_id->connect_error ?: $this->db_connect_id->error,
|
||||
'code' => $this->db_connect_id->connect_errno ?: $this->db_connect_id->errno,
|
||||
];
|
||||
}
|
||||
else
|
||||
|
@@ -17,7 +17,10 @@ class bot_update extends \phpbb\db\migration\migration
|
||||
{
|
||||
static public function depends_on()
|
||||
{
|
||||
return array('\phpbb\db\migration\data\v310\rc6');
|
||||
return array(
|
||||
'\phpbb\db\migration\data\v310\rc6',
|
||||
'\phpbb\db\migration\data\v310\avatars',
|
||||
);
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
|
47
phpBB/phpbb/db/migration/data/v33x/topic_views_update.php
Normal file
47
phpBB/phpbb/db/migration/data/v33x/topic_views_update.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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 topic_views_update extends \phpbb\db\migration\migration
|
||||
{
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v3314',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_schema(): array
|
||||
{
|
||||
// This extends the topic view count field so we can support much larger values.
|
||||
return [
|
||||
'change_columns' => [
|
||||
$this->table_prefix . 'topics' => [
|
||||
'topic_views' => ['ULINT', 0],
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function revert_schema(): array
|
||||
{
|
||||
return [
|
||||
'change_columns' => [
|
||||
$this->table_prefix . 'topics' => [
|
||||
'topic_views' => ['UINT', 0],
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v3313.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v3313.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 v3313 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.13', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v3313rc1',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.13']],
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v3314.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v3314.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 v3314 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.14', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v3314rc1',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.14']],
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v3314rc1.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v3314rc1.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 v3314rc1 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.14-RC1', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v3313',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.14-RC1']],
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v3315.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v3315.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 v3315 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.15', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\v3315rc1',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.15']],
|
||||
];
|
||||
}
|
||||
}
|
36
phpBB/phpbb/db/migration/data/v33x/v3315rc1.php
Normal file
36
phpBB/phpbb/db/migration/data/v33x/v3315rc1.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 v3315rc1 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return version_compare($this->config['version'], '3.3.15-RC1', '>=');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v33x\topic_views_update',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.update', ['version', '3.3.15-RC1']],
|
||||
];
|
||||
}
|
||||
}
|
@@ -551,7 +551,7 @@ class migrator
|
||||
$state['migration_data_state']['_total_time'] : 0.0;
|
||||
$elapsed_time = microtime(true);
|
||||
|
||||
$steps = array_merge($this->helper->reverse_update_data($migration->update_data()), $migration->revert_data());
|
||||
$steps = $migration->revert_data() ?: $this->helper->reverse_update_data($migration->update_data());
|
||||
$result = $this->process_data_step($steps, $state['migration_data_state']);
|
||||
|
||||
$elapsed_time = microtime(true) - $elapsed_time;
|
||||
|
@@ -134,6 +134,8 @@ class feed
|
||||
*/
|
||||
public function forums()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_overall_forums'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -151,6 +153,8 @@ class feed
|
||||
*/
|
||||
public function news()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
// Get at least one news forum
|
||||
$sql = 'SELECT forum_id
|
||||
FROM ' . FORUMS_TABLE . '
|
||||
@@ -176,6 +180,8 @@ class feed
|
||||
*/
|
||||
public function topics()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_topics_new'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -193,6 +199,8 @@ class feed
|
||||
*/
|
||||
public function topics_new()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
return $this->topics();
|
||||
}
|
||||
|
||||
@@ -205,6 +213,8 @@ class feed
|
||||
*/
|
||||
public function topics_active()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_topics_active'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -224,6 +234,8 @@ class feed
|
||||
*/
|
||||
public function forum($forum_id)
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_forum'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -243,6 +255,8 @@ class feed
|
||||
*/
|
||||
public function topic($topic_id)
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_topic'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -260,6 +274,8 @@ class feed
|
||||
*/
|
||||
public function overall()
|
||||
{
|
||||
$this->check_enabled();
|
||||
|
||||
if (!$this->config['feed_overall'])
|
||||
{
|
||||
$this->send_unavailable();
|
||||
@@ -407,6 +423,22 @@ class feed
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if feeds are enabled in the configuration.
|
||||
*
|
||||
* @throws http_exception If feeds are disabled.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function check_enabled()
|
||||
{
|
||||
// Feeds are disabled, no need to continue
|
||||
if (!$this->config['feed_enable'])
|
||||
{
|
||||
throw new http_exception(404, 'NO_FEED_ENABLED');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw and exception saying that the feed isn't available
|
||||
*
|
||||
|
@@ -13,91 +13,127 @@
|
||||
|
||||
namespace phpbb;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use phpbb\exception\runtime_exception;
|
||||
|
||||
class file_downloader
|
||||
{
|
||||
const OK = 200;
|
||||
const NOT_FOUND = 404;
|
||||
const REQUEST_TIMEOUT = 408;
|
||||
|
||||
/** @var string Error string */
|
||||
protected $error_string = '';
|
||||
|
||||
/** @var int Error number */
|
||||
protected $error_number = 0;
|
||||
|
||||
/**
|
||||
* Create new guzzle client
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected function create_client(string $host, int $port = 443, int $timeout = 6): Client
|
||||
{
|
||||
// Only set URL scheme if not specified in URL
|
||||
$url_parts = parse_url($host);
|
||||
if (!isset($url_parts['scheme']))
|
||||
{
|
||||
$host = (($port === 443) ? 'https://' : 'http://') . $host;
|
||||
}
|
||||
|
||||
// Initialize Guzzle client
|
||||
return new Client([
|
||||
'base_uri' => $host,
|
||||
'timeout' => $timeout,
|
||||
'headers' => [
|
||||
'user-agent' => 'phpBB/' . PHPBB_VERSION,
|
||||
'accept' => '*/*',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve contents from remotely stored file
|
||||
*
|
||||
* @param string $host File host
|
||||
* @param string $directory Directory file is in
|
||||
* @param string $filename Filename of file to retrieve
|
||||
* @param int $port Port to connect to; default: 80
|
||||
* @param int $timeout Connection timeout in seconds; default: 6
|
||||
* @param string $host File host
|
||||
* @param string $directory Directory file is in
|
||||
* @param string $filename Filename of file to retrieve
|
||||
* @param int $port Port to connect to; default: 443
|
||||
* @param int $timeout Connection timeout in seconds; default: 6
|
||||
*
|
||||
* @return mixed File data as string if file can be read and there is no
|
||||
* timeout, false if there were errors or the connection timed out
|
||||
* @return false|string File data as string if file can be read and there is no
|
||||
* timeout, false if there were errors or the connection timed out
|
||||
*
|
||||
* @throws \phpbb\exception\runtime_exception If data can't be retrieved and no error
|
||||
* message is returned
|
||||
* @throws runtime_exception If data can't be retrieved and no error
|
||||
* message is returned
|
||||
*/
|
||||
public function get($host, $directory, $filename, $port = 80, $timeout = 6)
|
||||
public function get(string $host, string $directory, string $filename, int $port = 443, int $timeout = 6)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Initialize Guzzle client
|
||||
$client = $this->create_client($host, $port, $timeout);
|
||||
}
|
||||
catch (\RuntimeException $exception)
|
||||
{
|
||||
throw new runtime_exception('HTTP_HANDLER_NOT_FOUND');
|
||||
}
|
||||
|
||||
// Set default values for error variables
|
||||
$this->error_number = 0;
|
||||
$this->error_string = '';
|
||||
|
||||
if (function_exists('fsockopen') &&
|
||||
$socket = @fsockopen(($port == 443 ? 'ssl://' : '') . $host, $port, $this->error_number, $this->error_string, $timeout)
|
||||
)
|
||||
try
|
||||
{
|
||||
@fputs($socket, "GET $directory/$filename HTTP/1.0\r\n");
|
||||
@fputs($socket, "HOST: $host\r\n");
|
||||
@fputs($socket, "Connection: close\r\n\r\n");
|
||||
$response = $client->request('GET', "$directory/$filename");
|
||||
|
||||
$timer_stop = time() + $timeout;
|
||||
stream_set_timeout($socket, $timeout);
|
||||
|
||||
$file_info = '';
|
||||
$get_info = false;
|
||||
|
||||
while (!@feof($socket))
|
||||
// Check if the response status code is 200 (OK)
|
||||
if ($response->getStatusCode() == self::OK)
|
||||
{
|
||||
if ($get_info)
|
||||
{
|
||||
$file_info .= @fread($socket, 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = @fgets($socket, 1024);
|
||||
if ($line == "\r\n")
|
||||
{
|
||||
$get_info = true;
|
||||
}
|
||||
else if (stripos($line, '404 not found') !== false)
|
||||
{
|
||||
throw new \phpbb\exception\runtime_exception('FILE_NOT_FOUND', array($filename));
|
||||
}
|
||||
}
|
||||
|
||||
$stream_meta_data = stream_get_meta_data($socket);
|
||||
|
||||
if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
|
||||
{
|
||||
throw new \phpbb\exception\runtime_exception('FSOCK_TIMEOUT');
|
||||
}
|
||||
}
|
||||
@fclose($socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->error_string)
|
||||
{
|
||||
$this->error_string = utf8_convert_message($this->error_string);
|
||||
return false;
|
||||
return $response->getBody()->getContents();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \phpbb\exception\runtime_exception('FSOCK_DISABLED');
|
||||
$this->error_number = $response->getStatusCode();
|
||||
throw new runtime_exception('FILE_NOT_FOUND', [$filename]);
|
||||
}
|
||||
}
|
||||
catch (RequestException $exception)
|
||||
{
|
||||
if ($exception->hasResponse())
|
||||
{
|
||||
$this->error_number = $exception->getResponse()->getStatusCode();
|
||||
|
||||
return $file_info;
|
||||
if ($this->error_number == self::NOT_FOUND)
|
||||
{
|
||||
throw new runtime_exception('FILE_NOT_FOUND', [$filename]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->error_number = self::REQUEST_TIMEOUT;
|
||||
throw new runtime_exception('FSOCK_TIMEOUT');
|
||||
}
|
||||
|
||||
$this->error_string = utf8_convert_message($exception->getMessage());
|
||||
return false;
|
||||
}
|
||||
catch (runtime_exception $exception)
|
||||
{
|
||||
// Rethrow runtime_exceptions, only handle unknown cases below
|
||||
throw $exception;
|
||||
}
|
||||
catch (\Throwable $exception)
|
||||
{
|
||||
$this->error_string = utf8_convert_message($exception->getMessage());
|
||||
throw new runtime_exception('FSOCK_DISABLED');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +141,7 @@ class file_downloader
|
||||
*
|
||||
* @return string Error string
|
||||
*/
|
||||
public function get_error_string()
|
||||
public function get_error_string(): string
|
||||
{
|
||||
return $this->error_string;
|
||||
}
|
||||
@@ -115,7 +151,7 @@ class file_downloader
|
||||
*
|
||||
* @return int Error number
|
||||
*/
|
||||
public function get_error_number()
|
||||
public function get_error_number(): int
|
||||
{
|
||||
return $this->error_number;
|
||||
}
|
||||
|
@@ -339,6 +339,14 @@ class helper
|
||||
protected function render_language_select($selected_language = null)
|
||||
{
|
||||
$langs = $this->lang_helper->get_available_languages();
|
||||
|
||||
// The first language will be selected by default. Unless a user has consciously included
|
||||
// other languages in the installation process, it will be British English anyway.
|
||||
if ($selected_language === null && count($langs))
|
||||
{
|
||||
$selected_language = $langs[0]['iso'];
|
||||
}
|
||||
|
||||
foreach ($langs as $lang)
|
||||
{
|
||||
$this->template->assign_block_vars('language_select_item', array(
|
||||
|
@@ -67,6 +67,20 @@ class language_file_helper
|
||||
);
|
||||
}
|
||||
|
||||
usort($available_languages, [$this, 'sort_by_local_name']);
|
||||
|
||||
return $available_languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the languages by their name instead of iso code
|
||||
*
|
||||
* @param mixed $a First language data
|
||||
* @param mixed $b Second language data
|
||||
* @return int
|
||||
*/
|
||||
private static function sort_by_local_name($a, $b): int
|
||||
{
|
||||
return $a['local_name'] <=> $b['local_name'];
|
||||
}
|
||||
}
|
||||
|
@@ -223,13 +223,13 @@ class path_helper
|
||||
*
|
||||
* The referer must be specified as a parameter in the query.
|
||||
*/
|
||||
if ($this->request->is_ajax() && $this->symfony_request->get('_referer'))
|
||||
if ($this->request->is_ajax() && $this->request->header('Referer'))
|
||||
{
|
||||
// We need to escape $absolute_board_url because it can be partially concatenated to the result.
|
||||
$absolute_board_url = $this->request->escape($this->symfony_request->getSchemeAndHttpHost() . $this->symfony_request->getBasePath(), true);
|
||||
|
||||
$referer_web_root_path = $this->get_web_root_path_from_ajax_referer(
|
||||
$this->symfony_request->get('_referer'),
|
||||
$this->request->header('Referer'),
|
||||
$absolute_board_url
|
||||
);
|
||||
return $this->web_root_path = $referer_web_root_path;
|
||||
|
@@ -70,12 +70,12 @@ class request implements \phpbb\request\request_interface
|
||||
|
||||
foreach ($this->super_globals as $const => $super_global)
|
||||
{
|
||||
$this->input[$const] = isset($GLOBALS[$super_global]) ? $GLOBALS[$super_global] : array();
|
||||
$this->input[$const] = isset($GLOBALS[$super_global]) ? (array) $GLOBALS[$super_global] : array();
|
||||
}
|
||||
|
||||
// simulate request_order = GP
|
||||
$this->original_request = $this->input[\phpbb\request\request_interface::REQUEST];
|
||||
$this->input[\phpbb\request\request_interface::REQUEST] = $this->input[\phpbb\request\request_interface::POST] + $this->input[\phpbb\request\request_interface::GET];
|
||||
$this->original_request = (array) $this->input[\phpbb\request\request_interface::REQUEST];
|
||||
$this->input[\phpbb\request\request_interface::REQUEST] = (array) $this->input[\phpbb\request\request_interface::POST] + (array) $this->input[\phpbb\request\request_interface::GET];
|
||||
|
||||
if ($disable_super_globals)
|
||||
{
|
||||
|
@@ -76,17 +76,16 @@ class base
|
||||
}
|
||||
}
|
||||
|
||||
// change the start to the actual end of the current request if the sort direction differs
|
||||
// from the dirction in the cache and reverse the ids later
|
||||
// If the sort direction differs from the direction in the cache, then recalculate array keys
|
||||
if ($reverse_ids)
|
||||
{
|
||||
$start = $result_count - $start - $per_page;
|
||||
|
||||
// the user requested a page past the last index
|
||||
if ($start < 0)
|
||||
{
|
||||
return SEARCH_RESULT_NOT_IN_CACHE;
|
||||
}
|
||||
$keys = array_keys($stored_ids);
|
||||
array_walk($keys, function (&$value, $key) use ($result_count)
|
||||
{
|
||||
$value = ($value >= 0) ? $result_count - $value - 1 : $value;
|
||||
}
|
||||
);
|
||||
$stored_ids = array_combine($keys, $stored_ids);
|
||||
}
|
||||
|
||||
for ($i = $start, $n = $start + $per_page; ($i < $n) && ($i < $result_count); $i++)
|
||||
@@ -102,11 +101,6 @@ class base
|
||||
}
|
||||
unset($stored_ids);
|
||||
|
||||
if ($reverse_ids)
|
||||
{
|
||||
$id_ary = array_reverse($id_ary);
|
||||
}
|
||||
|
||||
if (!$complete)
|
||||
{
|
||||
return SEARCH_RESULT_INCOMPLETE;
|
||||
@@ -142,6 +136,8 @@ class base
|
||||
}
|
||||
|
||||
$store_ids = array_slice($id_ary, 0, $length);
|
||||
$id_range = range($start, $start + $length - 1);
|
||||
$store_ids = array_combine($id_range, $store_ids);
|
||||
|
||||
// create a new resultset if there is none for this search_key yet
|
||||
// or add the ids to the existing resultset
|
||||
@@ -176,29 +172,26 @@ class base
|
||||
$db->sql_query($sql);
|
||||
|
||||
$store = array(-1 => $result_count, -2 => $sort_dir);
|
||||
$id_range = range($start, $start + $length - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we use one set of results for both sort directions so we have to calculate the indizes
|
||||
// for the reversed array and we also have to reverse the ids themselves
|
||||
// for the reversed array
|
||||
if ($store[-2] != $sort_dir)
|
||||
{
|
||||
$store_ids = array_reverse($store_ids);
|
||||
$id_range = range($store[-1] - $start - $length, $store[-1] - $start - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$id_range = range($start, $start + $length - 1);
|
||||
$keys = array_keys($store_ids);
|
||||
array_walk($keys, function (&$value, $key) use ($store) {
|
||||
$value = $store[-1] - $value - 1;
|
||||
});
|
||||
$store_ids = array_combine($keys, $store_ids);
|
||||
}
|
||||
}
|
||||
|
||||
$store_ids = array_combine($id_range, $store_ids);
|
||||
|
||||
// append the ids
|
||||
if (is_array($store_ids))
|
||||
{
|
||||
$store += $store_ids;
|
||||
ksort($store);
|
||||
|
||||
// if the cache is too big
|
||||
if (count($store) - 2 > 20 * $config['search_block_size'])
|
||||
|
@@ -609,7 +609,6 @@ 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))
|
||||
{
|
||||
@@ -635,10 +634,10 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
$id_ary[] = (int) $row[$field];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
|
||||
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
|
||||
$id_ary = array_slice($id_ary, 0, (int) $per_page);
|
||||
@@ -833,6 +832,8 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
// Build the query for really selecting the post_ids
|
||||
if ($type == 'posts')
|
||||
{
|
||||
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
|
||||
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
|
||||
$sql = "SELECT $sql_select
|
||||
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
|
||||
WHERE $sql_author
|
||||
@@ -896,10 +897,10 @@ class fulltext_mysql extends \phpbb\search\base
|
||||
$id_ary[] = (int) $row[$field];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
if (count($id_ary))
|
||||
{
|
||||
$this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
|
||||
|
@@ -1012,6 +1012,8 @@ class fulltext_native extends \phpbb\search\base
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
|
||||
$this->save_ids($search_key, $this->search_query, $author_ary, $total_results, $id_ary, $start, $sort_dir);
|
||||
$id_ary = array_slice($id_ary, 0, (int) $per_page);
|
||||
@@ -1249,6 +1251,8 @@ class fulltext_native extends \phpbb\search\base
|
||||
// Build the query for really selecting the post_ids
|
||||
if ($type == 'posts')
|
||||
{
|
||||
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
|
||||
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
|
||||
$sql = "SELECT $select
|
||||
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t' : '') . "
|
||||
WHERE $sql_author
|
||||
@@ -1313,6 +1317,8 @@ class fulltext_native extends \phpbb\search\base
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
if (count($id_ary))
|
||||
{
|
||||
$this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir);
|
||||
|
@@ -545,8 +545,6 @@ class fulltext_postgres 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)
|
||||
{
|
||||
@@ -576,10 +574,10 @@ class fulltext_postgres extends \phpbb\search\base
|
||||
$id_ary[] = $row[$field];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
|
||||
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
|
||||
$id_ary = array_slice($id_ary, 0, (int) $per_page);
|
||||
@@ -766,6 +764,8 @@ class fulltext_postgres extends \phpbb\search\base
|
||||
// Build the query for really selecting the post_ids
|
||||
if ($type == 'posts')
|
||||
{
|
||||
// For sorting by non-unique columns, add unique sort key to avoid duplicated rows in results
|
||||
$sql_sort .= ', p.post_id' . (($sort_dir == 'a') ? ' ASC' : ' DESC');
|
||||
$sql = "SELECT p.post_id
|
||||
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
|
||||
WHERE $sql_author
|
||||
@@ -858,10 +858,10 @@ class fulltext_postgres extends \phpbb\search\base
|
||||
$id_ary[] = (int) $row[$field];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
}
|
||||
|
||||
$id_ary = array_unique($id_ary);
|
||||
|
||||
if (count($id_ary))
|
||||
{
|
||||
$this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
|
||||
|
@@ -356,7 +356,7 @@ class fulltext_sphinx
|
||||
array('read_timeout', '5'),
|
||||
array('max_children', '30'),
|
||||
array('pid_file', $this->config['fulltext_sphinx_data_path'] . 'searchd.pid'),
|
||||
array('binlog_path', $this->config['fulltext_sphinx_data_path']),
|
||||
array('binlog_path', rtrim($this->config['fulltext_sphinx_data_path'], '/\\')), // Trim trailing slash
|
||||
),
|
||||
);
|
||||
|
||||
@@ -455,9 +455,47 @@ class fulltext_sphinx
|
||||
$this->sphinx->SetMatchMode(SPH_MATCH_ANY);
|
||||
}
|
||||
|
||||
if (strlen($keywords) > 0)
|
||||
// Split words
|
||||
$split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($keywords)));
|
||||
$matches = array();
|
||||
preg_match_all('#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u', $split_keywords, $matches);
|
||||
$this->split_words = $matches[1];
|
||||
|
||||
if ($terms == 'any')
|
||||
{
|
||||
$this->search_query = str_replace('"', '"', $keywords);
|
||||
$this->search_query = '';
|
||||
foreach ($this->split_words as $word)
|
||||
{
|
||||
if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0))
|
||||
{
|
||||
$word = substr($word, 1);
|
||||
}
|
||||
$this->search_query .= $word . ' ';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->search_query = '';
|
||||
foreach ($this->split_words as $word)
|
||||
{
|
||||
if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0))
|
||||
{
|
||||
$this->search_query .= $word . ' ';
|
||||
}
|
||||
else if (strpos($word, '|') === 0)
|
||||
{
|
||||
$this->search_query .= substr($word, 1) . ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->search_query .= '+' . $word . ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->search_query)
|
||||
{
|
||||
$this->search_query = str_replace('"', '"', $this->search_query);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -99,7 +99,10 @@ class twig extends \phpbb\template\base
|
||||
|
||||
foreach ($extensions as $extension)
|
||||
{
|
||||
$this->twig->addExtension($extension);
|
||||
if (!$this->twig->hasExtension(get_class($extension)))
|
||||
{
|
||||
$this->twig->addExtension($extension);
|
||||
}
|
||||
}
|
||||
|
||||
// Add admin namespace
|
||||
|
@@ -216,11 +216,11 @@ abstract class base implements reparser_interface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reparse_range($min_id, $max_id)
|
||||
public function reparse_range($min_id, $max_id, bool $force_bbcode_reparsing = false)
|
||||
{
|
||||
foreach ($this->get_records_by_range($min_id, $max_id) as $record)
|
||||
{
|
||||
$this->reparse_record($record);
|
||||
$this->reparse_record($record, $force_bbcode_reparsing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,16 +228,17 @@ abstract class base implements reparser_interface
|
||||
* Reparse given record
|
||||
*
|
||||
* @param array $record Associative array containing the record's data
|
||||
* @param bool $force_bbcode_reparsing Flag indicating if BBCode should be reparsed unconditionally
|
||||
*/
|
||||
protected function reparse_record(array $record)
|
||||
protected function reparse_record(array $record, bool $force_bbcode_reparsing = false)
|
||||
{
|
||||
// Guess magic URL state based on actual record content before adding fields
|
||||
$record['enable_magic_url'] = $this->guess_magic_url($record);
|
||||
$record = $this->add_missing_fields($record);
|
||||
|
||||
$flags = ($record['enable_bbcode']) ? OPTION_FLAG_BBCODE : 0;
|
||||
$flags |= ($record['enable_smilies']) ? OPTION_FLAG_SMILIES : 0;
|
||||
$flags |= ($record['enable_magic_url']) ? OPTION_FLAG_LINKS : 0;
|
||||
$flags = ($record['enable_bbcode'] || $force_bbcode_reparsing) ? OPTION_FLAG_BBCODE : 0;
|
||||
$flags |= ($record['enable_smilies'] || $force_bbcode_reparsing) ? OPTION_FLAG_SMILIES : 0;
|
||||
$flags |= ($record['enable_magic_url'] || $force_bbcode_reparsing) ? OPTION_FLAG_LINKS : 0;
|
||||
$unparsed = array_merge(
|
||||
$record,
|
||||
generate_text_for_edit($record['text'], $record['bbcode_uid'], $flags)
|
||||
@@ -252,13 +253,13 @@ abstract class base implements reparser_interface
|
||||
$unparsed['bbcode_uid'],
|
||||
$bitfield,
|
||||
$flags,
|
||||
$unparsed['enable_bbcode'],
|
||||
$unparsed['enable_magic_url'],
|
||||
$unparsed['enable_smilies'],
|
||||
$unparsed['enable_img_bbcode'],
|
||||
$unparsed['enable_bbcode'] || $force_bbcode_reparsing,
|
||||
$unparsed['enable_magic_url'] || $force_bbcode_reparsing,
|
||||
$unparsed['enable_smilies'] || $force_bbcode_reparsing,
|
||||
$unparsed['enable_img_bbcode'] || $force_bbcode_reparsing,
|
||||
$unparsed['enable_flash_bbcode'],
|
||||
$unparsed['enable_quote_bbcode'],
|
||||
$unparsed['enable_url_bbcode'],
|
||||
$unparsed['enable_quote_bbcode'] || $force_bbcode_reparsing,
|
||||
$unparsed['enable_url_bbcode'] || $force_bbcode_reparsing,
|
||||
'text_reparser.' . $this->get_name()
|
||||
);
|
||||
|
||||
|
@@ -41,6 +41,7 @@ interface reparser_interface
|
||||
*
|
||||
* @param integer $min_id Lower bound
|
||||
* @param integer $max_id Upper bound
|
||||
* @param bool $force_bbcode_reparsing Flag indicating if BBCode should be reparsed unconditionally
|
||||
*/
|
||||
public function reparse_range($min_id, $max_id);
|
||||
public function reparse_range($min_id, $max_id, bool $force_bbcode_reparsing = false);
|
||||
}
|
||||
|
@@ -272,7 +272,7 @@ class reset_password
|
||||
], false)
|
||||
]);
|
||||
|
||||
$messenger->send($user_row['user_notify_type']);
|
||||
$messenger->send(NOTIFY_EMAIL);
|
||||
|
||||
return $this->helper->message($message);
|
||||
}
|
||||
|
@@ -381,7 +381,7 @@ class version_helper
|
||||
}
|
||||
else if ($info === false || $force_update)
|
||||
{
|
||||
$info = $this->file_downloader->get($this->host, $this->path, $this->file, $this->use_ssl ? 443 : 80);
|
||||
$info = $this->file_downloader->get($this->host, $this->path, $this->file, $this->use_ssl ? 443 : 80, 30);
|
||||
$error_string = $this->file_downloader->get_error_string();
|
||||
|
||||
if (!empty($error_string))
|
||||
|
@@ -90,8 +90,21 @@ switch ($search_id)
|
||||
break;
|
||||
}
|
||||
|
||||
$search_auth_check_override = false;
|
||||
/**
|
||||
* This event allows you to override search auth checks
|
||||
*
|
||||
* @event core.search_auth_check_override
|
||||
* @var bool search_auth_check_override Whether or not the search auth check overridden
|
||||
* @since 3.3.14-RC1
|
||||
*/
|
||||
$vars = [
|
||||
'search_auth_check_override',
|
||||
];
|
||||
extract($phpbb_dispatcher->trigger_event('core.search_auth_check_override', compact($vars)));
|
||||
|
||||
// Is user able to search? Has search been disabled?
|
||||
if (!$auth->acl_get('u_search') || !$auth->acl_getf_global('f_search') || !$config['load_search'])
|
||||
if (!$search_auth_check_override && (!$auth->acl_get('u_search') || !$auth->acl_getf_global('f_search') || !$config['load_search']))
|
||||
{
|
||||
$template->assign_var('S_NO_SEARCH', true);
|
||||
trigger_error('NO_SEARCH');
|
||||
@@ -684,10 +697,10 @@ if ($keywords || $author || $author_id || $search_id || $submit)
|
||||
$hilit = str_replace(' ', '|', $hilit);
|
||||
|
||||
$u_hilit = urlencode(html_entity_decode(str_replace('|', ' ', $hilit), ENT_COMPAT));
|
||||
$u_show_results = '&sr=' . $show_results;
|
||||
$u_show_results = 'sr=' . $show_results;
|
||||
$u_search_forum = implode('&fid%5B%5D=', $search_forum);
|
||||
|
||||
$u_search = append_sid("{$phpbb_root_path}search.$phpEx", $u_sort_param . $u_show_results);
|
||||
$u_search = append_sid("{$phpbb_root_path}search.$phpEx", (($u_sort_param) ? $u_sort_param . '&' : '') . $u_show_results);
|
||||
$u_search .= ($search_id) ? '&search_id=' . $search_id : '';
|
||||
$u_search .= ($u_hilit) ? '&keywords=' . urlencode(html_entity_decode($keywords, ENT_COMPAT)) : '';
|
||||
$u_search .= ($search_terms != 'all') ? '&terms=' . $search_terms : '';
|
||||
|
@@ -21,8 +21,8 @@
|
||||
# General Information about this style
|
||||
name = prosilver
|
||||
copyright = © phpBB Limited, 2007
|
||||
style_version = 3.3.13
|
||||
phpbb_version = 3.3.13
|
||||
style_version = 3.3.15
|
||||
phpbb_version = 3.3.15
|
||||
|
||||
# Defining a different template bitfield
|
||||
# template_bitfield = //g=
|
||||
|
@@ -38,11 +38,11 @@
|
||||
<xsl:value-of select="$L_COLON"/>
|
||||
<xsl:if test="@post_url">
|
||||
<xsl:text> </xsl:text>
|
||||
<a href="{@post_url}" data-post-id="{@post_id}" onclick="if(document.getElementById(hash.substr(1)))href=hash">↑</a>
|
||||
<a href="{@post_url}" aria-label="{L_VIEW_QUOTED_POST}" data-post-id="{@post_id}" onclick="if(document.getElementById(hash.substr(1)))href=hash"><i class="icon fa-arrow-circle-up fa-fw" aria-hidden="true"></i></a>
|
||||
</xsl:if>
|
||||
<xsl:if test="@msg_url">
|
||||
<xsl:text> </xsl:text>
|
||||
<a href="{@msg_url}" data-msg-id="{@msg_id}">↑</a>
|
||||
<a href="{@msg_url}" aria-label="{L_VIEW_QUOTED_POST}" data-msg-id="{@msg_id}"><i class="icon fa-arrow-circle-up fa-fw" aria-hidden="true"></i></a>
|
||||
</xsl:if>
|
||||
<xsl:if test="@date">
|
||||
<span class="responsive-hide"><xsl:value-of select="@date"/></span>
|
||||
|
@@ -650,7 +650,7 @@ function parseDocument($container) {
|
||||
html = $children.html();
|
||||
}
|
||||
|
||||
$block.append((first ? '' : '<br />') + html);
|
||||
$block.append((first ? '' : '<br>') + html);
|
||||
|
||||
first = false;
|
||||
});
|
||||
@@ -670,7 +670,7 @@ function parseDocument($container) {
|
||||
|
||||
// Find all headers, get contents
|
||||
$list.prev('.topiclist').find('li.header dd').not('.mark').each(function() {
|
||||
headers.push($(this).text());
|
||||
headers.push($("<div>").text($(this).text()).html());
|
||||
headersLength++;
|
||||
});
|
||||
|
||||
@@ -707,7 +707,7 @@ function parseDocument($container) {
|
||||
html = headers[i] + ': <strong>' + html + '</strong>';
|
||||
}
|
||||
|
||||
$block.append((first ? '' : '<br />') + html);
|
||||
$block.append((first ? '' : '<br>') + html);
|
||||
|
||||
first = false;
|
||||
});
|
||||
@@ -773,7 +773,9 @@ function parseDocument($container) {
|
||||
}
|
||||
|
||||
if ((text.length && text !== '-') || cell.children().length) {
|
||||
cell.prepend('<dfn style="display: none;">' + headers[column] + '</dfn>');
|
||||
if (headers[column].length) {
|
||||
cell.prepend($("<dfn>").css('display', 'none').text(headers[column]));
|
||||
}
|
||||
} else {
|
||||
cell.addClass('empty');
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@
|
||||
<div class="list-inner">
|
||||
<!-- IF S_ENABLE_FEEDS and forumrow.S_FEED_ENABLED -->
|
||||
<!--
|
||||
<a class="feed-icon-forum" title="{L_FEED} - {forumrow.FORUM_NAME}" href="{U_FEED}?f={forumrow.FORUM_ID}">
|
||||
<a class="feed-icon-forum" title="{L_FEED} - {forumrow.FORUM_NAME}" href="{{ path('phpbb_feed_forum', { forum_id : forumrow.FORUM_ID } ) }}">
|
||||
<i class="icon fa-rss-square fa-fw icon-orange" aria-hidden="true"></i><span class="sr-only">{L_FEED} - {forumrow.FORUM_NAME}</span>
|
||||
</a>
|
||||
-->
|
||||
|
@@ -22,13 +22,13 @@
|
||||
{% endapply %}
|
||||
<!-- EVENT overall_footer_breadcrumb_append -->
|
||||
</li>
|
||||
<!-- IF U_WATCH_FORUM_LINK and not S_IS_BOT -->
|
||||
{% if U_WATCH_FORUM_LINK && !S_IS_BOT %}
|
||||
<li data-last-responsive="true">
|
||||
<a href="{U_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="toggle_link" data-toggle-class="icon <!-- IF S_WATCHING_FORUM -->fa-check-square-o<!-- ELSE -->fa-square-o<!-- ENDIF --> fa-fw" data-toggle-text="{S_WATCH_FORUM_TOGGLE}" data-toggle-url="{U_WATCH_FORUM_TOGGLE}">
|
||||
<i class="icon <!-- IF S_WATCHING_FORUM -->fa-square-o<!-- ELSE -->fa-check-square-o<!-- ENDIF --> fa-fw" aria-hidden="true"></i><span>{S_WATCH_FORUM_TITLE}</span>
|
||||
<a href="{{ U_WATCH_FORUM_LINK }}" title="{{ S_WATCH_FORUM_TITLE }}" data-ajax="toggle_link" data-toggle-class="icon {{ !S_WATCHING_FORUM ? 'fa-check-square-o' : 'fa-square-o' }} fa-fw" data-toggle-text="{{ S_WATCH_FORUM_TOGGLE }}" data-toggle-url="{{ U_WATCH_FORUM_TOGGLE }}">
|
||||
<i class="icon {{ S_WATCHING_FORUM ? 'fa-check-square-o' : 'fa-square-o' }} fa-fw" aria-hidden="true"></i><span>{{ S_WATCH_FORUM_TITLE }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- ENDIF -->
|
||||
{% endif %}
|
||||
|
||||
<!-- EVENT overall_footer_timezone_before -->
|
||||
<li class="rightside">{S_TIMEZONE}</li>
|
||||
|
@@ -226,7 +226,7 @@
|
||||
<!-- ENDIF -->
|
||||
|
||||
<div class="action-bar bottom">
|
||||
<!-- IF .searchresults and (S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY) -->
|
||||
<!-- IF S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY -->
|
||||
<form method="post" action="{S_SEARCH_ACTION}">
|
||||
<!-- INCLUDE display_options.html -->
|
||||
</form>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
<!-- ENDIF -->
|
||||
|
||||
|
||||
<div id="post-{MESSAGE_ID}" class="post pm has-profile<!-- IF S_POST_UNAPPROVED or S_POST_REPORTED --> reported<!-- ENDIF --><!-- IF S_ONLINE --> online<!-- ENDIF -->">
|
||||
<div id="post-{MESSAGE_ID}" class="post pm has-profile<!-- IF S_ONLINE --> online<!-- ENDIF -->">
|
||||
<div class="inner">
|
||||
|
||||
<dl class="postprofile" id="profile{MESSAGE_ID}">
|
||||
@@ -130,6 +130,7 @@
|
||||
<!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}"<!-- IF bcc_recipient.COLOUR --> style="color:{bcc_recipient.COLOUR};"<!-- ENDIF -->><strong>{bcc_recipient.NAME}</strong></a><!-- ENDIF --> <!-- END bcc_recipient --><!-- ENDIF -->
|
||||
</p>
|
||||
|
||||
{% EVENT ucp_pm_viewmessage_message_content_before %}
|
||||
|
||||
<div class="content">{MESSAGE}</div>
|
||||
|
||||
|
@@ -8,13 +8,13 @@
|
||||
<div class="pointer"><div class="pointer-inner"></div></div>
|
||||
<ul class="dropdown-contents">
|
||||
<!-- EVENT viewtopic_topic_tools_before -->
|
||||
<!-- IF U_WATCH_TOPIC -->
|
||||
{% if U_WATCH_TOPIC %}
|
||||
<li>
|
||||
<a href="{U_WATCH_TOPIC}" class="watch-topic-link" title="{S_WATCH_TOPIC_TITLE}" data-ajax="toggle_link" data-toggle-class="icon <!-- IF S_WATCHING_TOPIC -->fa-check-square-o<!-- ELSE -->fa-square-o<!-- ENDIF --> fa-fw" data-toggle-text="{S_WATCH_TOPIC_TOGGLE}" data-toggle-url="{U_WATCH_TOPIC_TOGGLE}" data-update-all=".watch-topic-link">
|
||||
<i class="icon <!-- IF S_WATCHING_TOPIC -->fa-square-o<!-- ELSE -->fa-check-square-o<!-- ENDIF --> fa-fw" aria-hidden="true"></i><span>{S_WATCH_TOPIC_TITLE}</span>
|
||||
<a href="{{ U_WATCH_TOPIC }}" class="watch-topic-link" title="{{ S_WATCH_TOPIC_TITLE }}" data-ajax="toggle_link" data-toggle-class="icon {{ !S_WATCHING_TOPIC ? 'fa-check-square-o' : 'fa-square-o' }} fa-fw" data-toggle-text="{{ S_WATCH_TOPIC_TOGGLE }}" data-toggle-url="{{ U_WATCH_TOPIC_TOGGLE }}" data-update-all=".watch-topic-link">
|
||||
<i class="icon {{ S_WATCHING_TOPIC ? 'fa-check-square-o' : 'fa-square-o' }} fa-fw" aria-hidden="true"></i><span>{{ S_WATCH_TOPIC_TITLE }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- ENDIF -->
|
||||
{% endif %}
|
||||
<!-- IF U_BOOKMARK_TOPIC -->
|
||||
<li>
|
||||
<a href="{U_BOOKMARK_TOPIC}" class="bookmark-link" title="{L_BOOKMARK_TOPIC}" data-ajax="alt_text" data-alt-text="{S_BOOKMARK_TOGGLE}" data-update-all=".bookmark-link">
|
||||
|
@@ -47,27 +47,45 @@ if (!$forum_id)
|
||||
trigger_error('NO_FORUM');
|
||||
}
|
||||
|
||||
$sql_from = FORUMS_TABLE . ' f';
|
||||
$sql_ary = [
|
||||
'SELECT' => 'f.*',
|
||||
'FROM' => [
|
||||
FORUMS_TABLE => 'f',
|
||||
],
|
||||
'WHERE' => 'f.forum_id = ' . $forum_id,
|
||||
];
|
||||
|
||||
$lastread_select = '';
|
||||
|
||||
// Grab appropriate forum data
|
||||
if ($config['load_db_lastread'] && $user->data['is_registered'])
|
||||
{
|
||||
$sql_from .= ' LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . '
|
||||
AND ft.forum_id = f.forum_id)';
|
||||
$lastread_select .= ', ft.mark_time';
|
||||
$sql_ary['LEFT_JOIN'][] = [
|
||||
'FROM' => [FORUMS_TRACK_TABLE => 'ft'],
|
||||
'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id',
|
||||
];
|
||||
$sql_ary['SELECT'] .= ', ft.mark_time';
|
||||
}
|
||||
|
||||
if ($user->data['is_registered'])
|
||||
{
|
||||
$sql_from .= ' LEFT JOIN ' . FORUMS_WATCH_TABLE . ' fw ON (fw.forum_id = f.forum_id AND fw.user_id = ' . $user->data['user_id'] . ')';
|
||||
$lastread_select .= ', fw.notify_status';
|
||||
$sql_ary['LEFT_JOIN'][] = [
|
||||
'FROM' => [FORUMS_WATCH_TABLE => 'fw'],
|
||||
'ON' => 'fw.forum_id = f.forum_id AND fw.user_id = ' . $user->data['user_id'],
|
||||
];
|
||||
$sql_ary['SELECT'] .= ', fw.notify_status';
|
||||
}
|
||||
|
||||
$sql = "SELECT f.* $lastread_select
|
||||
FROM $sql_from
|
||||
WHERE f.forum_id = $forum_id";
|
||||
$result = $db->sql_query($sql);
|
||||
/**
|
||||
* You can use this event to modify the sql that selects the forum on the viewforum page.
|
||||
*
|
||||
* @event core.viewforum_modify_sql
|
||||
* @var array sql_ary The SQL array to get the data for a forum
|
||||
* @since 3.3.14-RC1
|
||||
*/
|
||||
$vars = ['sql_ary'];
|
||||
extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_sql', compact($vars)));
|
||||
$result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
|
||||
$forum_data = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
|
142
tests/cron/wrapper_test.php
Normal file
142
tests/cron/wrapper_test.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../template/template_test_case.php';
|
||||
|
||||
class phpbb_cron_wrapper_test extends phpbb_template_template_test_case
|
||||
{
|
||||
private $task;
|
||||
private $routing_helper;
|
||||
private $wrapper;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
// Test the engine can be used
|
||||
$this->setup_engine([], $phpbb_root_path . 'styles/all/template');
|
||||
|
||||
$this->template->clear_cache();
|
||||
|
||||
global $phpbb_filesystem;
|
||||
|
||||
$phpbb_filesystem = new \phpbb\filesystem\filesystem();
|
||||
|
||||
$this->task = $this->createMock(\phpbb\cron\task\task::class);
|
||||
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
|
||||
|
||||
$this->wrapper = new \phpbb\cron\task\wrapper(
|
||||
$this->task,
|
||||
$this->routing_helper,
|
||||
'/phpbb/',
|
||||
'php',
|
||||
$this->template
|
||||
);
|
||||
}
|
||||
|
||||
public function test_generate_template_pagination()
|
||||
{
|
||||
$this->task = $this->createMock(\phpbb\cron\task\parametrized::class);
|
||||
$this->task->expects($this->any())
|
||||
->method('get_parameters')
|
||||
->willReturn(['f' => '5']);
|
||||
$this->task->expects($this->any())
|
||||
->method('get_name')
|
||||
->willReturn('test_task');
|
||||
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
|
||||
$this->routing_helper->expects($this->any())
|
||||
->method('route')
|
||||
->with('phpbb_cron_run', ['cron_type' => 'test_task', 'f' => '5'])
|
||||
->willReturn('app.php/cron/foo?f=5');
|
||||
|
||||
$this->wrapper = new \phpbb\cron\task\wrapper(
|
||||
$this->task,
|
||||
$this->routing_helper,
|
||||
'/phpbb/',
|
||||
'php',
|
||||
$this->template
|
||||
);
|
||||
|
||||
$this->assertEquals('<img class="sr-only" aria-hidden="true" src="app.php/cron/foo?f=5" width="1" height="1" alt="">', str_replace(["\n", "\t"], '', $this->wrapper->get_html_tag()));
|
||||
}
|
||||
|
||||
public function test_is_parametrized_false()
|
||||
{
|
||||
$this->assertFalse($this->wrapper->is_parametrized());
|
||||
}
|
||||
|
||||
public function test_is_ready()
|
||||
{
|
||||
$this->task->method('is_runnable')->willReturn(true);
|
||||
$this->task->method('should_run')->willReturn(true);
|
||||
|
||||
$this->assertTrue($this->wrapper->is_ready());
|
||||
}
|
||||
|
||||
public function test_get_url_non_parametrized()
|
||||
{
|
||||
$this->task->method('get_name')->willReturn('test_task');
|
||||
$this->routing_helper->expects($this->once())
|
||||
->method('route')
|
||||
->with('phpbb_cron_run', ['cron_type' => 'test_task'])
|
||||
->willReturn('/cron/url');
|
||||
|
||||
$this->assertEquals('/cron/url', $this->wrapper->get_url());
|
||||
}
|
||||
|
||||
public function test_get_html_tag()
|
||||
{
|
||||
$this->template = $this->createMock(\phpbb\template\template::class);
|
||||
$this->wrapper = new \phpbb\cron\task\wrapper(
|
||||
$this->task,
|
||||
$this->routing_helper,
|
||||
'/phpbb/',
|
||||
'php',
|
||||
$this->template
|
||||
);
|
||||
|
||||
$this->template->expects($this->once())
|
||||
->method('set_filenames');
|
||||
$this->template->expects($this->once())
|
||||
->method('assign_var');
|
||||
$this->template->expects($this->once())
|
||||
->method('assign_display')
|
||||
->willReturn('<img src="cron">');
|
||||
|
||||
$this->assertEquals('<img src="cron">', $this->wrapper->get_html_tag());
|
||||
}
|
||||
|
||||
public function test_call_forwards_to_task()
|
||||
{
|
||||
$this->task = $this->getMockBuilder(\phpbb\cron\task\task::class)
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['get_name', 'run', 'is_runnable', 'should_run', 'some_method'])
|
||||
->getMock();
|
||||
$this->routing_helper = $this->createMock(\phpbb\routing\helper::class);
|
||||
|
||||
$this->wrapper = new \phpbb\cron\task\wrapper(
|
||||
$this->task,
|
||||
$this->routing_helper,
|
||||
'/phpbb/',
|
||||
'php',
|
||||
$this->template
|
||||
);
|
||||
$this->task->expects($this->once())
|
||||
->method('some_method')
|
||||
->with('arg1', 'arg2')
|
||||
->willReturn('result');
|
||||
|
||||
$result = $this->wrapper->some_method('arg1', 'arg2');
|
||||
$this->assertEquals('result', $result);
|
||||
}
|
||||
}
|
@@ -123,4 +123,20 @@ class phpbb_functional_acp_groups_test extends phpbb_functional_common_groups_te
|
||||
$this->assertEquals((bool) $tick_teampage, (bool) ($this->form_data['group_teampage'] ?? false));
|
||||
}
|
||||
}
|
||||
|
||||
public function test_acp_groups_create_existing_name()
|
||||
{
|
||||
$this->group_manage_login();
|
||||
|
||||
$crawler = self::request('GET', 'adm/index.php?i=groups&mode=manage&sid=' . $this->sid);
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form([
|
||||
'group_name' => 'Guests', // 'Guests' is the group name already in use for predefined Guests group
|
||||
]);
|
||||
|
||||
$crawler = self::submit($form);
|
||||
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
|
||||
$crawler = self::submit($form); // Just submit the form with selected group name
|
||||
|
||||
$this->assertStringContainsString($this->lang('GROUP_NAME_TAKEN'), $crawler->text());
|
||||
}
|
||||
}
|
||||
|
@@ -149,4 +149,26 @@ class phpbb_functional_acp_permissions_test extends phpbb_functional_test_case
|
||||
$this->assertContainsLang('ACL_M_EDIT', $page_text);
|
||||
$this->assertContainsLang('ACL_M_MOVE', $page_text);
|
||||
}
|
||||
|
||||
public function test_tracing_user_based_permissions()
|
||||
{
|
||||
$this->create_user('newlyregistereduser');
|
||||
|
||||
// Open user-based permissions masks page
|
||||
$crawler = self::request('GET', "adm/index.php?i=acp_permissions&icat=16&mode=view_user_global&sid=" . $this->sid);
|
||||
|
||||
// Select newlyregistereduser
|
||||
$form = $crawler->filter('#add_user')->form(['username' => ['newlyregistereduser']]);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
// Test 1st "Yes" permission tracing result match
|
||||
$trace_link_yes = $crawler->filter('td.yes')->eq(0)->siblings()->filter('th > a.trace')->link();
|
||||
$crawler_trace_yes = self::$client->click($trace_link_yes);
|
||||
$this->assertEquals(1, $crawler_trace_yes->filter('tr.row2 > td.yes')->count());
|
||||
|
||||
// Test 1st "Never" permission tracing result match
|
||||
$trace_link_never = $crawler->filter('td.never')->eq(0)->siblings()->filter('th > a.trace')->link();
|
||||
$crawler_trace_never = self::$client->click($trace_link_never);
|
||||
$this->assertEquals(1, $crawler_trace_never->filter('tr.row2 > td.never')->count());
|
||||
}
|
||||
}
|
||||
|
@@ -84,7 +84,8 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case
|
||||
$crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid);
|
||||
|
||||
$this->assertCount(1, $crawler->filter('.ext_enabled'));
|
||||
$this->assertCount(7, $crawler->filter('.ext_disabled'));
|
||||
$this->assertCount(3, $crawler->filter('.ext_disabled'));
|
||||
$this->assertCount(4, $crawler->filter('.ext_not_installed'));
|
||||
|
||||
$this->assertStringContainsString('phpBB Foo Extension', $crawler->filter('.ext_enabled')->eq(0)->text());
|
||||
$this->assertContainsLang('EXTENSION_DISABLE', $crawler->filter('.ext_enabled')->eq(0)->text());
|
||||
@@ -98,9 +99,9 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case
|
||||
|
||||
$this->assertStringContainsString('The “vendor/test3” extension is not valid.', $crawler->filter('.ext_disabled')->eq(1)->text());
|
||||
|
||||
$this->assertStringContainsString('phpBB Bar Extension', $crawler->filter('.ext_disabled')->eq(3)->text());
|
||||
$this->assertContainsLang('DETAILS', $crawler->filter('.ext_disabled')->eq(3)->text());
|
||||
$this->assertContainsLang('EXTENSION_ENABLE', $crawler->filter('.ext_disabled')->eq(3)->text());
|
||||
$this->assertStringContainsString('phpBB Bar Extension', $crawler->filter('.ext_not_installed')->eq(0)->text());
|
||||
$this->assertContainsLang('DETAILS', $crawler->filter('.ext_not_installed')->eq(0)->text());
|
||||
$this->assertContainsLang('EXTENSION_ENABLE', $crawler->filter('.ext_not_installed')->eq(0)->text());
|
||||
|
||||
// Check that invalid extensions are not listed.
|
||||
$this->assertStringNotContainsString('phpBB BarFoo Extension', $crawler->filter('.table1')->text());
|
||||
|
@@ -261,6 +261,29 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
|
||||
$this->data['topics']['Feeds #exclude - Topic #1'] = (int) $post['topic_id'];
|
||||
}
|
||||
|
||||
public function test_feeds_disabled()
|
||||
{
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
|
||||
// Disable feeds in ACP
|
||||
$crawler = self::request('GET', "adm/index.php?sid={$this->sid}&i=acp_board&mode=feed");
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$crawler = self::submit($form, ['config[feed_enable]' => 0]);
|
||||
self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
|
||||
|
||||
// Assert that feeds aren't available
|
||||
$crawler = self::request('GET', 'app.php/feed/overall', array(), false);
|
||||
self::assert_response_status_code(404);
|
||||
$this->assertContainsLang('NO_FEED_ENABLED', $crawler->text());
|
||||
|
||||
// Enable feeds again in ACP
|
||||
$crawler = self::request('GET', "adm/index.php?sid={$this->sid}&i=acp_board&mode=feed");
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$crawler = self::submit($form, ['config[feed_enable]' => 1]);
|
||||
self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
|
||||
}
|
||||
|
||||
public function test_feeds_exclude()
|
||||
{
|
||||
$this->load_ids(array(
|
||||
|
@@ -49,6 +49,30 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
$this->assertStringContainsString("Search found $topics_found match", $crawler->filter('.searchresults-title')->text(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function assert_search_posts_by_author_id($author_id, $posts_found, $sort_key = '', $sort_dir = '')
|
||||
{
|
||||
// Test obtaining data from cache if sorting direction is set
|
||||
if (!$sort_dir)
|
||||
{
|
||||
$this->purge_cache();
|
||||
}
|
||||
$crawler = self::request('GET', 'search.php?author_id=' . $author_id . ($sort_key ? "&sk=$sort_key" : '') . ($sort_dir ? "&sk=$sort_dir" : ''));
|
||||
$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_id($author_id, $topics_found, $sort_key = '', $sort_dir = '')
|
||||
{
|
||||
// Test obtaining data from cache if sorting direction is set
|
||||
if (!$sort_dir)
|
||||
{
|
||||
$this->purge_cache();
|
||||
}
|
||||
$crawler = self::request('GET', 'search.php?sr=topics&author_id=' . $author_id . ($sort_key ? "&sk=$sort_key" : '') . ($sort_dir ? "&sk=$sort_dir" : ''));
|
||||
$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_in_topic($topic_id, $keywords, $posts_found, $sort_key = '')
|
||||
{
|
||||
$this->purge_cache();
|
||||
@@ -93,10 +117,14 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
$this->add_lang('common');
|
||||
|
||||
// Create a new standard user if needed, topic and post to test searh for author
|
||||
if (!$this->user_exists('searchforauthoruser'))
|
||||
if (!$searchforauthoruser_id = $this->user_exists('searchforauthoruser'))
|
||||
{
|
||||
$searchforauthoruser_id = $this->create_user('searchforauthoruser');
|
||||
}
|
||||
else
|
||||
{
|
||||
$searchforauthoruser_id = key($searchforauthoruser_id);
|
||||
}
|
||||
$this->remove_user_group('NEWLY_REGISTERED', ['searchforauthoruser']);
|
||||
$this->set_flood_interval(0);
|
||||
$this->login('searchforauthoruser');
|
||||
@@ -122,8 +150,19 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
if ($values["config[search_type]"] != $this->search_backend)
|
||||
{
|
||||
$values["config[search_type]"] = $this->search_backend;
|
||||
|
||||
if (strpos($this->search_backend, 'fulltext_sphinx'))
|
||||
{
|
||||
// Set board Sphinx id in according to respective setup-sphinx.sh $ID value
|
||||
$sql = 'UPDATE ' . CONFIG_TABLE . "
|
||||
SET config_value = '" . $this->db->sql_escape('gokw5rvjvvxp8kgj') . "'
|
||||
WHERE config_name = '" . $this->db->sql_escape('fulltext_sphinx_id') . "'";
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->purge_cache();
|
||||
|
||||
$form = $crawler->selectButton($this->lang('YES'))->form();
|
||||
$values = $form->getValues();
|
||||
@@ -161,6 +200,11 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
|
||||
$this->assert_search_posts_by_author('searchforauthoruser', 2, $sort_key);
|
||||
$this->assert_search_topics_by_author('searchforauthoruser', 1, $sort_key);
|
||||
|
||||
$this->assert_search_posts_by_author_id($searchforauthoruser_id, 2, $sort_key);
|
||||
$this->assert_search_topics_by_author_id($searchforauthoruser_id, 1, $sort_key);
|
||||
$this->assert_search_posts_by_author_id($searchforauthoruser_id, 2, $sort_key, 'a'); //search asc order
|
||||
$this->assert_search_topics_by_author_id($searchforauthoruser_id, 1, $sort_key, 'a'); // search asc order
|
||||
}
|
||||
|
||||
$this->assert_search_not_found('loremipsumdedo');
|
||||
@@ -177,6 +221,159 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
$this->delete_topic($topic_multiple_results_count2['topic_id']);
|
||||
}
|
||||
|
||||
public function test_caching_search_results()
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
// Sphinx search doesn't use phpBB search results caching
|
||||
if (strpos($this->search_backend, 'fulltext_sphinx'))
|
||||
{
|
||||
$this->markTestSkipped("Sphinx search doesn't use phpBB search results caching");
|
||||
}
|
||||
|
||||
$this->purge_cache();
|
||||
$this->login();
|
||||
$this->admin_login();
|
||||
|
||||
$crawler = self::request('GET', 'search.php?author_id=2&sr=posts');
|
||||
$posts_found_text = $crawler->filter('.searchresults-title')->text();
|
||||
|
||||
// Get total user's post count
|
||||
preg_match('!(\d+)!', $posts_found_text, $matches);
|
||||
$posts_count = (int) $matches[1];
|
||||
|
||||
$this->assertStringContainsString("Search found $posts_count matches", $posts_found_text, $this->search_backend);
|
||||
|
||||
// Set this value to cache less results than total count
|
||||
$sql = 'UPDATE ' . CONFIG_TABLE . '
|
||||
SET config_value = ' . floor($posts_count / 3) . "
|
||||
WHERE config_name = '" . $this->db->sql_escape('search_block_size') . "'";
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
// Temporarily set posts_per_page to the value allowing to get several pages (4+)
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
$current_posts_per_page = $values['config[posts_per_page]'];
|
||||
$values['config[posts_per_page]'] = floor($posts_count / 10);
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertEquals(1, $crawler->filter('.successbox')->count(), $this->search_backend);
|
||||
|
||||
// Now actually test caching search results
|
||||
$this->purge_cache();
|
||||
|
||||
// Default sort direction is 'd' (descending), browse the 1st page
|
||||
$crawler = self::request('GET', 'search.php?author_id=2&sr=posts');
|
||||
$pagination = $crawler->filter('.pagination')->eq(0);
|
||||
$posts_found_text = $pagination->text();
|
||||
|
||||
$this->assertStringContainsString("Search found $posts_count matches", $posts_found_text, $this->search_backend);
|
||||
|
||||
// Filter all search result page links on the 1st page
|
||||
$pagination = $pagination->filter('li > a')->reduce(
|
||||
function ($node, $i)
|
||||
{
|
||||
return ($node->attr('class') == 'button');
|
||||
}
|
||||
);
|
||||
|
||||
// Get last page number
|
||||
$last_page = (int) $pagination->last()->text();
|
||||
|
||||
// Browse the last search page
|
||||
$crawler = self::$client->click($pagination->selectLink($last_page)->link());
|
||||
$pagination = $crawler->filter('.pagination')->eq(0);
|
||||
|
||||
// Filter all search result page links on the last page
|
||||
$pagination = $pagination->filter('li > a')->reduce(
|
||||
function ($node, $i)
|
||||
{
|
||||
return ($node->attr('class') == 'button');
|
||||
}
|
||||
);
|
||||
|
||||
// Now change sort direction to ascending
|
||||
$form = $crawler->selectButton('sort')->form();
|
||||
$values = $form->getValues();
|
||||
$values['sd'] = 'a';
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
|
||||
$pagination = $crawler->filter('.pagination')->eq(0);
|
||||
|
||||
// Filter all search result page links on the 1st page with new sort direction
|
||||
$pagination = $pagination->filter('li > a')->reduce(
|
||||
function ($node, $i)
|
||||
{
|
||||
return ($node->attr('class') == 'button');
|
||||
}
|
||||
);
|
||||
|
||||
// Browse the rest of search results pages with new sort direction
|
||||
$pages = range(2, $last_page);
|
||||
foreach ($pages as $page_number)
|
||||
{
|
||||
$crawler = self::$client->click($pagination->selectLink($page_number)->link());
|
||||
$pagination = $crawler->filter('.pagination')->eq(0);
|
||||
$pagination = $pagination->filter('li > a')->reduce(
|
||||
function ($node, $i)
|
||||
{
|
||||
return ($node->attr('class') == 'button');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Get search results cache varname
|
||||
$finder = new \Symfony\Component\Finder\Finder();
|
||||
$finder
|
||||
->name('data_search_results_*.php')
|
||||
->files()
|
||||
->in($phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT);
|
||||
$iterator = $finder->getIterator();
|
||||
$iterator->rewind();
|
||||
$cache_filename = $iterator->current();
|
||||
$cache_varname = substr($cache_filename->getBasename('.php'), 4);
|
||||
|
||||
// Get cached post ids data
|
||||
$cache = $this->get_cache_driver();
|
||||
$post_ids_cached = $cache->get($cache_varname);
|
||||
|
||||
$cached_results_count = count($post_ids_cached) - 2; // Don't count '-1' and '-2' indexes
|
||||
|
||||
$post_ids_cached_backup = $post_ids_cached;
|
||||
|
||||
// Cached data still should have initial 'd' sort direction
|
||||
$this->assertTrue($post_ids_cached[-2] === 'd', $this->search_backend);
|
||||
|
||||
// Cached search results count should be equal to displayed on search results page
|
||||
$this->assertEquals($posts_count, $post_ids_cached[-1], $this->search_backend);
|
||||
|
||||
// Actual cached data array count should be equal to displayed on search results page too
|
||||
$this->assertEquals($posts_count, $cached_results_count, $this->search_backend);
|
||||
|
||||
// Cached data array shouldn't change after removing duplicates. That is, it shouldn't have any duplicates.
|
||||
unset($post_ids_cached[-2], $post_ids_cached[-1]);
|
||||
unset($post_ids_cached_backup[-2], $post_ids_cached_backup[-1]);
|
||||
$post_ids_cached = array_unique($post_ids_cached);
|
||||
$this->assertEquals($post_ids_cached_backup, $post_ids_cached, $this->search_backend);
|
||||
|
||||
// Restore this value to default
|
||||
$sql = 'UPDATE ' . CONFIG_TABLE . "
|
||||
SET config_value = 250
|
||||
WHERE config_name = '" . $this->db->sql_escape('search_block_size') . "'";
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
// Restore posts_per_page value
|
||||
$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post');
|
||||
$form = $crawler->selectButton('Submit')->form();
|
||||
$values = $form->getValues();
|
||||
$values['config[posts_per_page]'] = $current_posts_per_page;
|
||||
$form->setValues($values);
|
||||
$crawler = self::submit($form);
|
||||
$this->assertEquals(1, $crawler->filter('.successbox')->count(), $this->search_backend);
|
||||
}
|
||||
|
||||
protected function create_search_index($backend = null)
|
||||
{
|
||||
$this->add_lang('acp/search');
|
||||
@@ -211,7 +408,12 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
|
||||
// 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();
|
||||
$posts_indexed = (int) $crawler->filter('#acp_search_index_' . $search_type . ' td')->reduce(
|
||||
function ($node, $i) {
|
||||
// Find the value of total posts indexed
|
||||
return (strpos($node->text(), $this->lang('FULLTEXT_MYSQL_TOTAL_POSTS')) !== false || strpos($node->text(), $this->lang('TOTAL_WORDS')) !== false);
|
||||
})
|
||||
->nextAll()->eq(0)->text();
|
||||
$this->assertTrue($posts_indexed > 0);
|
||||
}
|
||||
|
||||
@@ -248,7 +450,12 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
|
||||
|
||||
// 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();
|
||||
$posts_indexed = (int) $crawler->filter('#acp_search_index_' . $this->search_backend . ' td')->reduce(
|
||||
function ($node, $i) {
|
||||
// Find the value of total posts indexed
|
||||
return (strpos($node->text(), $this->lang('FULLTEXT_MYSQL_TOTAL_POSTS')) !== false || strpos($node->text(), $this->lang('TOTAL_WORDS')) !== false);
|
||||
})
|
||||
->nextAll()->eq(0)->text();
|
||||
$this->assertEquals(0, $posts_indexed);
|
||||
}
|
||||
}
|
||||
|
@@ -20,8 +20,31 @@ class phpbb_functional_search_sphinx_test extends phpbb_functional_search_base
|
||||
{
|
||||
protected $search_backend = '\phpbb\search\fulltext_sphinx';
|
||||
|
||||
protected function create_search_index($backend = null)
|
||||
{
|
||||
parent::create_search_index($backend);
|
||||
$this->purge_cache();
|
||||
|
||||
if (!$backend || $this->search_backend == $backend)
|
||||
{
|
||||
$output = $retval = null;
|
||||
|
||||
// After creating phpBB search index, build Sphinx index
|
||||
exec('sudo -S service sphinxsearch stop', $output, $retval); // Attempt to stop sphinxsearch service in case it's running
|
||||
exec('sudo -S indexer --all', $output, $retval); // Run sphinxsearch indexer
|
||||
exec('sudo -S service sphinxsearch start', $output, $retval); // Attempt to start sphinxsearch service again
|
||||
}
|
||||
}
|
||||
|
||||
public function test_search_backend()
|
||||
{
|
||||
$this->markTestIncomplete('Sphinx Tests are not supported');
|
||||
if ($this->db->sql_layer != 'mysqli') // Sphinx test runs on MySQL/MariaDB only so far
|
||||
{
|
||||
$this->markTestIncomplete('Sphinx Tests are not supported');
|
||||
}
|
||||
else
|
||||
{
|
||||
parent::test_search_backend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ class phpbb_functional_switch_permissions_test extends phpbb_functional_test_cas
|
||||
$this->add_lang(['common', 'ucp']);
|
||||
}
|
||||
|
||||
public function test_switch_permissions()
|
||||
public function test_switch_permissions_acp()
|
||||
{
|
||||
$user_id = $this->create_user(self::TEST_USER);
|
||||
|
||||
@@ -67,4 +67,53 @@ class phpbb_functional_switch_permissions_test extends phpbb_functional_test_cas
|
||||
$crawler->text()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends test_switch_permissions_acp
|
||||
*/
|
||||
public function test_switch_permissions_ucp()
|
||||
{
|
||||
$db = $this->get_db();
|
||||
$sql = 'SELECT user_id
|
||||
FROM ' . USERS_TABLE . "
|
||||
WHERE username = '" . self::TEST_USER . "'";
|
||||
$result = $db->sql_query($sql);
|
||||
$user_id = $db->sql_fetchfield('user_id');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// Open memberlist profile page for user
|
||||
$crawler = self::request('GET', "memberlist.php?mode=viewprofile&u={$user_id}&sid={$this->sid}");
|
||||
|
||||
// Use permissions
|
||||
$link = $crawler->selectLink($this->lang('USE_PERMISSIONS'))->link();
|
||||
$crawler = self::$client->click($link);
|
||||
|
||||
// Check that we switched permissions to test user
|
||||
$this->assertStringContainsString(
|
||||
str_replace('<br />', '<br>', $this->lang('PERMISSIONS_TRANSFERRED', self::TEST_USER)),
|
||||
$crawler->html()
|
||||
);
|
||||
|
||||
// Check that UCP pages don't get forced to UCP main with restore permission info
|
||||
$this->add_lang(['memberlist', 'ucp']);
|
||||
$crawler = self::request('GET', "ucp.php?i=ucp_profile&mode=profile_info&sid={$this->sid}");
|
||||
$this->assertStringContainsString(
|
||||
$this->lang('EDIT_PROFILE'),
|
||||
$crawler->text()
|
||||
);
|
||||
|
||||
// Check that restore permissions link exists
|
||||
$crawler = self::$client->request('GET', 'index.php?sid=' . $this->sid);
|
||||
$this->assertStringContainsString(
|
||||
$this->lang('RESTORE_PERMISSIONS'),
|
||||
$crawler->text()
|
||||
);
|
||||
|
||||
// Check that restore permissions works
|
||||
$crawler = self::$client->request('GET', 'ucp.php?mode=restore_perm&sid=' . $this->sid);
|
||||
$this->assertStringContainsString(
|
||||
$this->lang('PERMISSIONS_RESTORED'),
|
||||
$crawler->text()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -601,7 +601,16 @@ class phpbb_functional_visibility_softdelete_test extends phpbb_functional_test_
|
||||
// Assert new topic title is indexed as well
|
||||
$this->add_lang('search');
|
||||
self::request('GET', "search.php?keywords=bang&sid={$this->sid}");
|
||||
$this->assertStringContainsString(sprintf($this->lang['FOUND_SEARCH_MATCHES'][1], 1), self::get_content());
|
||||
|
||||
// Sphinx search doesn't apply to unapproved or softdeleted posts
|
||||
if (strpos($this->get_search_type(), 'fulltext_sphinx'))
|
||||
{
|
||||
$this->assertStringContainsString(sprintf($this->lang['FOUND_SEARCH_MATCHES'][2], 0), self::get_content());
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->assertStringContainsString(sprintf($this->lang['FOUND_SEARCH_MATCHES'][1], 1), self::get_content());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_move_topic_back()
|
||||
|
@@ -81,13 +81,13 @@ class phpbb_functions_content_get_context_test extends TestCase
|
||||
'text' => 'This is a sample text.',
|
||||
'words' => ['sample'],
|
||||
'length' => 0,
|
||||
'expected' => '...',
|
||||
'expected' => 'This is a sample text.',
|
||||
],
|
||||
'negative length' => [
|
||||
'text' => 'This is a sample text.',
|
||||
'words' => ['sample'],
|
||||
'length' => -10,
|
||||
'expected' => '...',
|
||||
'expected' => 'This is a sample text.',
|
||||
],
|
||||
'ellipses_beginning' => [
|
||||
'text' => 'foo foo foo foo foo foo foo foo bar',
|
||||
@@ -112,12 +112,120 @@ class phpbb_functions_content_get_context_test extends TestCase
|
||||
'words' => ['word1', 'word2'],
|
||||
'length' => 10,
|
||||
'expected' => 'word1 ... word2',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for unicode get_context test cases.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data_get_context_unicode(): array
|
||||
{
|
||||
return [
|
||||
'text contains words and length greater than text' => [
|
||||
'text' => 'Это пример текста, содержащего разнообразные слова, включая пример, текст и слова.',
|
||||
'words' => ['пример', 'слова'],
|
||||
'length' => 100,
|
||||
'expected' => 'Это пример текста, содержащего разнообразные слова, включая пример, текст и слова.',
|
||||
],
|
||||
'text contains words and length less than text' => [
|
||||
'text' => 'Это пример текста, содержащего разнообразные слова, включая шаблон, текст и слова.',
|
||||
'words' => ['пример', 'слова'],
|
||||
'length' => 50,
|
||||
'expected' => 'Это пример текста, содержащего разнообразные слова ...',
|
||||
],
|
||||
'text does not contain words' => [
|
||||
'text' => 'Это пример текста, содержащего разнообразные слова, но ни одно из них не совпадает с искомыми.',
|
||||
'words' => ['nonexistent'],
|
||||
'length' => 50,
|
||||
'expected' => 'Это пример текста, содержащего разнообразные слова ...',
|
||||
],
|
||||
'desired length equal to text length' => [
|
||||
'text' => 'Текст точной длины.',
|
||||
'words' => ['Текст', 'точной'],
|
||||
'length' => 19,
|
||||
'expected' => 'Текст точной длины.',
|
||||
],
|
||||
'text with html entities' => [
|
||||
'text' => 'Это пример текста, содержащего & и < и > лексемы.',
|
||||
'words' => ['пример', 'содержащего'],
|
||||
'length' => 40,
|
||||
'expected' => 'Это пример текста, содержащего & и < и ...',
|
||||
],
|
||||
'text with html entities and contains last word' => [
|
||||
'text' => 'Это пример текста, содержащего & и < и > лексемы.',
|
||||
'words' => ['пример', 'лексемы'],
|
||||
'length' => 40,
|
||||
'expected' => 'Это пример текста ... и < и > лексемы.',
|
||||
],
|
||||
'text with multiple spaces and special characters' => [
|
||||
'text' => 'Это пример текста, содержащего разнообразные слова.',
|
||||
'words' => ['пример', 'разнообразные'],
|
||||
'length' => 50,
|
||||
'expected' => 'Это пример текста, содержащего разнообразные слова.',
|
||||
],
|
||||
'empty text' => [
|
||||
'text' => '',
|
||||
'words' => ['пример', 'слова'],
|
||||
'length' => 50,
|
||||
'expected' => '',
|
||||
],
|
||||
'empty words array' => [
|
||||
'text' => 'Это пример текста, содержащего разнообразные слова.',
|
||||
'words' => [],
|
||||
'length' => 50,
|
||||
'expected' => 'Это пример текста, содержащего разнообразные слова.',
|
||||
],
|
||||
'zero length' => [
|
||||
'text' => 'Это пример текста.',
|
||||
'words' => ['пример'],
|
||||
'length' => 0,
|
||||
'expected' => 'Это пример текста.',
|
||||
],
|
||||
'negative length' => [
|
||||
'text' => 'Это пример текста.',
|
||||
'words' => ['sample'],
|
||||
'length' => -10,
|
||||
'expected' => 'Это пример текста.',
|
||||
],
|
||||
'ellipses_beginning' => [
|
||||
'text' => 'раз раз раз раз раз раз раз раз два',
|
||||
'words' => ['два'],
|
||||
'length' => 10,
|
||||
'expected' => '... раз раз два',
|
||||
],
|
||||
'ellipsis_end' => [
|
||||
'text' => 'два раз раз раз раз раз раз раз раз',
|
||||
'words' => ['два'],
|
||||
'length' => 10,
|
||||
'expected' => 'два раз раз ...',
|
||||
],
|
||||
'ellipsis_middle' => [
|
||||
'text' => 'раз слово1 раз раз раз раз раз раз раз раз раз слово2 раз',
|
||||
'words' => ['слово1', 'слово2'],
|
||||
'length' => 15,
|
||||
'expected' => '... слово1 ... слово2 ...',
|
||||
],
|
||||
'ellipsis_middle2' => [
|
||||
'text' => 'слово1 foo foo foo foo foo foo foo foo foo слово2',
|
||||
'words' => ['слово1', 'слово2'],
|
||||
'length' => 10,
|
||||
'expected' => 'слово1 ... слово2',
|
||||
],
|
||||
'fruits_spanish' => [
|
||||
'text' => 'Manzana,plátano,naranja,fresa,mango,uva,piña,pera,kiwi,cereza,sandía,melón,papaya,arándano,durazno',
|
||||
'words' => ['piña'],
|
||||
'length' => 20,
|
||||
'expected' => '... uva,piña,pera ...',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_get_context
|
||||
* @dataProvider data_get_context_unicode
|
||||
*/
|
||||
public function test_get_context($text, $words, $length, $expected)
|
||||
{
|
||||
|
@@ -470,9 +470,6 @@ class phpbb_path_helper_test extends phpbb_test_case
|
||||
->setConstructorArgs([new phpbb_mock_request()])
|
||||
->setMethods(['get', 'getSchemeAndHttpHost', 'getBasePath', 'getPathInfo'])
|
||||
->getMock();
|
||||
$symfony_request->method('get')
|
||||
->with('_referer')
|
||||
->willReturn('http://www.phpbb.com/community/route1/route2/');
|
||||
$symfony_request->method('getSchemeAndHttpHost')
|
||||
->willReturn('http://www.phpbb.com');
|
||||
$symfony_request->method('getBasePath')
|
||||
@@ -486,6 +483,9 @@ class phpbb_path_helper_test extends phpbb_test_case
|
||||
->willReturn(true);
|
||||
$request->method('escape')
|
||||
->willReturnArgument(0);
|
||||
$request->method('header')
|
||||
->with('Referer')
|
||||
->willReturn('http://www.phpbb.com/community/route1/route2/');
|
||||
|
||||
$path_helper = new \phpbb\path_helper(
|
||||
$symfony_request,
|
||||
|
@@ -15,7 +15,7 @@ require_once __DIR__ . '/template_test_case.php';
|
||||
|
||||
class phpbb_template_extension_test extends phpbb_template_template_test_case
|
||||
{
|
||||
protected function setup_engine(array $new_config = array())
|
||||
protected function setup_engine(array $new_config = array(), string $template_path = '')
|
||||
{
|
||||
global $config, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
|
||||
|
||||
|
@@ -21,7 +21,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
|
||||
/** @var string */
|
||||
protected $parent_template_path;
|
||||
|
||||
protected function setup_engine(array $new_config = array())
|
||||
protected function setup_engine(array $new_config = array(), string $template_path = '')
|
||||
{
|
||||
global $phpbb_root_path, $phpEx, $user;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user