aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--build/build.xml52
-rw-r--r--phpBB/adm/style/acp_posting_buttons.html1
-rw-r--r--phpBB/docs/CREDITS.txt9
-rw-r--r--phpBB/docs/events.md71
-rw-r--r--phpBB/docs/lighttpd.sample.conf13
-rw-r--r--phpBB/includes/acp/acp_database.php8
-rw-r--r--phpBB/includes/acp/acp_forums.php24
-rw-r--r--phpBB/includes/acp/acp_icons.php18
-rw-r--r--phpBB/includes/acp/acp_language.php7
-rw-r--r--phpBB/includes/acp/acp_modules.php30
-rw-r--r--phpBB/includes/acp/acp_permission_roles.php9
-rw-r--r--phpBB/includes/acp/acp_profile.php29
-rw-r--r--phpBB/includes/acp/acp_reasons.php9
-rw-r--r--phpBB/includes/acp/acp_search.php18
-rw-r--r--phpBB/includes/functions_admin.php24
-rw-r--r--phpBB/includes/functions_content.php22
-rw-r--r--phpBB/includes/functions_download.php2
-rw-r--r--phpBB/includes/functions_messenger.php38
-rw-r--r--phpBB/includes/functions_user.php48
-rw-r--r--phpBB/includes/mcp/mcp_forum.php2
-rw-r--r--phpBB/includes/mcp/mcp_main.php18
-rw-r--r--phpBB/includes/ucp/ucp_main.php129
-rw-r--r--phpBB/index.php4
-rw-r--r--phpBB/install/database_update.php7
-rw-r--r--phpBB/install/install_install.php4
-rw-r--r--phpBB/language/en/acp/search.php2
-rw-r--r--phpBB/language/en/install.php4
-rw-r--r--phpBB/language/en/migrator.php4
-rw-r--r--phpBB/language/en/posting.php10
-rw-r--r--phpBB/phpbb/content_visibility.php112
-rw-r--r--phpBB/phpbb/db/migration/helper.php32
-rw-r--r--phpBB/phpbb/db/migration/tool/config.php5
-rw-r--r--phpBB/phpbb/db/migration/tool/config_text.php5
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php188
-rw-r--r--phpBB/phpbb/db/migration/tool/permission.php5
-rw-r--r--phpBB/phpbb/db/migrator.php169
-rw-r--r--phpBB/phpbb/db/migrator_output_handler_interface.php10
-rw-r--r--phpBB/phpbb/notification/method/messenger_base.php2
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php4
-rw-r--r--phpBB/phpbb/search/fulltext_native.php2
-rw-r--r--phpBB/phpbb/session.php20
-rw-r--r--phpBB/posting.php4
-rw-r--r--phpBB/search.php69
-rw-r--r--phpBB/styles/prosilver/template/confirm_delete_body.html4
-rw-r--r--phpBB/styles/prosilver/template/mcp_topic.html5
-rw-r--r--phpBB/styles/prosilver/template/memberlist_email.html2
-rw-r--r--phpBB/styles/prosilver/template/posting_editor.html6
-rw-r--r--phpBB/styles/prosilver/template/posting_topic_review.html3
-rw-r--r--phpBB/styles/prosilver/template/viewforum_body.html4
-rw-r--r--phpBB/styles/subsilver2/template/mcp_topic.html4
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_email.html2
-rw-r--r--phpBB/styles/subsilver2/template/posting_body.html6
-rw-r--r--phpBB/styles/subsilver2/template/posting_topic_review.html2
-rw-r--r--phpBB/styles/subsilver2/template/viewforum_body.html4
-rw-r--r--tests/dbal/fixtures/migrator_module.xml54
-rw-r--r--tests/dbal/migration/if.php4
-rw-r--r--tests/dbal/migrator_test.php8
-rw-r--r--tests/dbal/migrator_tool_module_test.php38
-rw-r--r--tests/functional/search/base.php8
-rw-r--r--tests/migrator/reverse_update_data_test.php56
61 files changed, 1194 insertions, 262 deletions
diff --git a/.travis.yml b/.travis.yml
index 14cf3e6d6c..a46d825612 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,12 +22,9 @@ matrix:
env: DB=mysqli
- php: 5.6
env: DB=mysqli
- - php: 7.0
- env: DB=mysqli
- php: hhvm
env: DB=mysqli
allow_failures:
- - php: 7.0
- php: hhvm
fast_finish: true
diff --git a/build/build.xml b/build/build.xml
index c412a747ac..2bece48edc 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -49,7 +49,7 @@
-->
<target name="composer">
<exec dir="phpBB"
- command="php ../composer.phar install --dev"
+ command="php ../composer.phar install"
checkreturn="true"
passthru="true" />
</target>
@@ -143,6 +143,7 @@
<phingcall target="export">
<property name="revision" value="release-${version}" />
<property name="dir" value="build/old_versions/release-${version}" />
+ <property name="skip-composer" value="true" />
</phingcall>
<phingcall target="clean-diff-dir">
@@ -251,26 +252,35 @@
<equals arg1="${composer-has-dependencies}" arg2="1" trim="true" />
<then>
<!-- We have non-dev composer dependencies -->
- <exec dir="."
- command="git ls-tree ${revision} composer.phar"
- checkreturn="true"
- outputProperty='composer-ls-tree-output' />
<if>
- <equals arg1="${composer-ls-tree-output}" arg2="" trim="true" />
+ <not><isset property="skip-composer" /></not>
<then>
- <fail message="There are composer dependencies, but composer.phar is missing." />
- </then>
- <else>
- <!-- Export the phar, install dependencies, delete phar. -->
<exec dir="."
- command="git archive ${revision} composer.phar | tar -xf - -C ${dir}"
- checkreturn="true" />
- <exec dir="${dir}"
- command="php composer.phar install --no-dev --optimize-autoloader"
+ command="git ls-tree ${revision} composer.phar"
checkreturn="true"
- passthru="true" />
- <delete file="${dir}/composer.phar" />
- </else>
+ outputProperty='composer-ls-tree-output' />
+ <if>
+ <equals arg1="${composer-ls-tree-output}" arg2="" trim="true" />
+ <then>
+ <fail message="There are composer dependencies, but composer.phar is missing." />
+ </then>
+ <else>
+ <!-- Export the phar, install dependencies, delete phar. -->
+ <exec dir="."
+ command="git archive ${revision} composer.phar | tar -xf - -C ${dir}"
+ checkreturn="true" />
+ <exec dir="${dir}"
+ command="php composer.phar install --no-dev --optimize-autoloader"
+ checkreturn="true"
+ passthru="true" />
+ <delete file="${dir}/composer.phar" />
+
+ <phingcall target="clean-vendor-dir">
+ <property name="dir" value="${dir}" />
+ </phingcall>
+ </else>
+ </if>
+ </then>
</if>
</then>
<else>
@@ -287,10 +297,6 @@
<delete dir="${dir}/develop" />
<delete dir="${dir}/install/data" />
- <phingcall target="clean-vendor-dir">
- <property name="dir" value="${dir}" />
- </phingcall>
-
<echo msg="Setting permissions for checkout of ${revision} in ${dir}" />
<!-- set permissions of all files to 644, directories to 755 -->
<exec dir="${dir}" command="find . -type f|xargs chmod 644" escape="false" />
@@ -307,6 +313,7 @@
<delete dir="${dir}/vendor/lusitanian/oauth/examples" />
<delete dir="${dir}/vendor/lusitanian/oauth/tests" />
<delete file="${dir}/vendor/lusitanian/oauth/.gitignore" />
+ <delete file="${dir}/vendor/lusitanian/oauth/.scrutinizer.yml" />
<delete file="${dir}/vendor/lusitanian/oauth/.travis.yml" />
<delete file="${dir}/vendor/lusitanian/oauth/phpunit.xml.dist" />
<delete file="${dir}/vendor/lusitanian/oauth/README.md" />
@@ -381,10 +388,9 @@
<delete file="${dir}/vendor/twig/twig/.editorconfig" />
<delete file="${dir}/vendor/twig/twig/.gitignore" />
<delete file="${dir}/vendor/twig/twig/.travis.yml" />
- <delete file="${dir}/vendor/twig/twig/AUTHORS" />
<delete file="${dir}/vendor/twig/twig/CHANGELOG" />
<delete file="${dir}/vendor/twig/twig/phpunit.xml.dist" />
- <delete file="${dir}/vendor/twig/twig/README.markdown" />
+ <delete file="${dir}/vendor/twig/twig/README.rst" />
</target>
<target name="clean-diff-dir">
diff --git a/phpBB/adm/style/acp_posting_buttons.html b/phpBB/adm/style/acp_posting_buttons.html
index 70b6259689..c3c42f8e82 100644
--- a/phpBB/adm/style/acp_posting_buttons.html
+++ b/phpBB/adm/style/acp_posting_buttons.html
@@ -63,6 +63,7 @@
<!-- ENDIF -->
<!-- ENDIF -->
</select>
+ <!-- EVENT acp_posting_buttons_custom_tags_before -->
<!-- BEGIN custom_tags -->
<input type="button" class="button2" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}" />
<!-- END custom_tags -->
diff --git a/phpBB/docs/CREDITS.txt b/phpBB/docs/CREDITS.txt
index deb36339b0..471e6b3c88 100644
--- a/phpBB/docs/CREDITS.txt
+++ b/phpBB/docs/CREDITS.txt
@@ -1,6 +1,6 @@
/**
*
-* phpBB © Copyright phpBB Limited 2003-2014
+* phpBB © Copyright phpBB Limited 2003-2016
* http://www.phpbb.com
*
* phpBB is free software. You can redistribute it and/or modify it
@@ -20,13 +20,13 @@
phpBB Project Manager: Marshalrusty (Yuriy Rusko)
-phpBB Lead Developer: naderman (Nils Adermann)
+phpBB Product Manager: naderman (Nils Adermann)
+
+phpBB Lead Developer: Marc (Marc Alexander)
phpBB Developers: bantu (Andreas Fischer)
CHItA (Máté Bartus)
- dhruv.goel92 (Dhruv Goel)
Elsensee (Oliver Schramm)
- marc1706 (Marc Alexander)
nickvergessen (Joas Schilling)
Nicofuma (Tristan Darricau)
prototech (Cesar Gallegos)
@@ -54,6 +54,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010]
ckwalsh (Cullen Walsh) [01/2010 - 07/2011]
DavidMJ (David M.) [12/2005 - 08/2009]
dhn (Dominik Dröscher) [05/2007 - 01/2011]
+ dhruv.goel92 (Dhruv Goel) [04/2013 - 05/2016]
EXreaction (Nathan Guse) [07/2012 - 05/2014]
GrahamJE (Graham Eames) [09/2005 - 11/2006]
igorw (Igor Wiedler) [08/2010 - 02/2013]
diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md
index 1fe8b915f1..abe702eb25 100644
--- a/phpBB/docs/events.md
+++ b/phpBB/docs/events.md
@@ -343,6 +343,13 @@ acp_posting_buttons_before
* Since: 3.1.0-b4
* Purpose: Add content before BBCode posting buttons in the ACP
+acp_posting_buttons_custom_tags_before
+===
+* Locations:
+ + adm/style/acp_posting_buttons.html
+* Since: 3.1.10-RC1
+* Purpose: Add content before the custom BBCodes in the ACP
+
acp_profile_contact_before
===
* Locations:
@@ -875,6 +882,22 @@ mcp_topic_options_before
* Since: 3.1.6-RC1
* Purpose: Add some options (field, checkbox, ...) before the subject field when split a subject
+mcp_topic_postrow_post_details_after
+===
+* Locations:
+ + styles/prosilver/template/mcp_topic.html
+ + styles/subsilver2/template/mcp_topic.html
+* Since: 3.1.10-RC1
+* Purpose: Add content after post details in topic moderation
+
+mcp_topic_postrow_post_details_before
+===
+* Locations:
+ + styles/prosilver/template/mcp_topic.html
+ + styles/subsilver2/template/mcp_topic.html
+* Since: 3.1.10-RC1
+* Purpose: Add content before post details in topic moderation
+
mcp_topic_topic_title_after
===
* Locations:
@@ -959,6 +982,14 @@ memberlist_body_username_prepend
* Purpose: Add information before every username in the memberlist. Works in
all display modes (leader, group and normal memberlist).
+memberlist_email_before
+===
+* Locations:
+ + styles/prosilver/template/memberlist_email.html
+ + styles/subsilver2/template/memberlist_email.html
+* Since: 3.1.10-RC1
+* Purpose: Allow adding customizations before the memberlist_email form.
+
memberlist_search_fields_after
===
* Locations:
@@ -1495,6 +1526,14 @@ posting_editor_subject_after
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen after the subject
+posting_editor_subject_append
+===
+* Locations:
+ + styles/prosilver/template/posting_editor.html
+ + styles/subsilver2/template/posting_body.html
+* Since: 3.1.10-RC1
+* Purpose: Add field, text, etc. to the posting after the subject text box
+
posting_editor_subject_before
===
* Locations:
@@ -1503,6 +1542,14 @@ posting_editor_subject_before
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen before the subject
+posting_editor_subject_prepend
+===
+* Locations:
+ + styles/prosilver/template/posting_editor.html
+ + styles/subsilver2/template/posting_body.html
+* Since: 3.1.10-RC1
+* Purpose: Add field, text, etc. to the posting before the subject text box
+
posting_editor_submit_buttons
===
* Locations:
@@ -1564,6 +1611,22 @@ posting_preview_poll_after
* Since: 3.1.7-RC1
* Purpose: Add content after the poll preview block
+posting_topic_review_row_post_details_after
+===
+* Locations:
+ + styles/prosilver/template/posting_topic_review.html
+ + styles/subsilver2/template/posting_topic_review.html
+* Since: 3.1.10-RC1
+* Purpose: Add content after post details in topic review
+
+posting_topic_review_row_post_details_before
+===
+* Locations:
+ + styles/prosilver/template/posting_topic_review.html
+ + styles/subsilver2/template/posting_topic_review.html
+* Since: 3.1.10-RC1
+* Purpose: Add content before post details in topic review
+
posting_topic_title_after
===
* Locations:
@@ -2247,6 +2310,14 @@ viewforum_body_topic_row_prepend
* Since: 3.1.7-RC1
* Purpose: Add content at the end of the topic list item.
+viewforum_body_topicrow_row_before
+===
+* Locations:
+ + styles/prosilver/template/viewforum_body.html
+ + styles/subsilver2/template/viewforum_body.html
+* Since: 3.1.10-RC1
+* Purpose: Add content before list of topics.
+
viewforum_buttons_bottom_before
===
* Locations:
diff --git a/phpBB/docs/lighttpd.sample.conf b/phpBB/docs/lighttpd.sample.conf
index 5862cb319d..5b04122267 100644
--- a/phpBB/docs/lighttpd.sample.conf
+++ b/phpBB/docs/lighttpd.sample.conf
@@ -1,7 +1,7 @@
# Sample lighttpd configuration file for phpBB.
# Global settings have been removed, copy them
# from your system's lighttpd.conf.
-# Tested with lighttpd 1.4.26
+# Tested with lighttpd 1.4.35
# If you want to use the X-Sendfile feature,
# uncomment the 'allow-x-send-file' for the fastcgi
@@ -16,6 +16,7 @@
server.modules += (
"mod_access",
"mod_fastcgi",
+ "mod_rewrite",
"mod_accesslog"
)
@@ -49,7 +50,15 @@ $HTTP["host"] == "www.myforums.com" {
$HTTP["url"] =~ "/\.htaccess|/\.htpasswd|/\.htgroups" {
url.access-deny = ( "" )
}
-
+
+ # The following 3 lines will rewrite URLs passed through the front controller
+ # to not require app.php in the actual URL. In other words, a controller is
+ # by default accessed at /app.php/my/controller, but can also be accessed at
+ # /my/controller
+ url.rewrite-if-not-file = (
+ "^/(.*)$" => "/app.php/$1"
+ )
+
fastcgi.server = ( ".php" =>
((
"bin-path" => "/usr/bin/php-cgi",
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index 9666ac5b6e..16655ff4cb 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -39,6 +39,14 @@ class acp_database
$action = request_var('action', '');
$submit = (isset($_POST['submit'])) ? true : false;
+ $form_key = 'acp_database';
+ add_form_key($form_key);
+
+ if ($submit && !check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$template->assign_vars(array(
'MODE' => $mode
));
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index 98273f06d9..1e69a4ad20 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -842,9 +842,26 @@ class acp_forums
ORDER BY left_id";
$result = $db->sql_query($sql);
- if ($row = $db->sql_fetchrow($result))
+ $rowset = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $rowset[(int) $row['forum_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ /**
+ * Modify the forum list data
+ *
+ * @event core.acp_manage_forums_modify_forum_list
+ * @var array rowset Array with the forums list data
+ * @since 3.1.10-RC1
+ */
+ $vars = array('rowset');
+ extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_modify_forum_list', compact($vars)));
+
+ if (!empty($rowset))
{
- do
+ foreach ($rowset as $row)
{
$forum_type = $row['forum_type'];
@@ -888,7 +905,6 @@ class acp_forums
'U_SYNC' => $url . '&amp;action=sync')
);
}
- while ($row = $db->sql_fetchrow($result));
}
else if ($this->parent_id)
{
@@ -904,7 +920,7 @@ class acp_forums
'U_SYNC' => $url . '&amp;action=sync')
);
}
- $db->sql_freeresult($result);
+ unset($rowset);
$template->assign_vars(array(
'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '',
diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php
index 9265415dd1..e9bc02d88b 100644
--- a/phpBB/includes/acp/acp_icons.php
+++ b/phpBB/includes/acp/acp_icons.php
@@ -40,6 +40,15 @@ class acp_icons
$action = (isset($_POST['edit'])) ? 'edit' : $action;
$action = (isset($_POST['import'])) ? 'import' : $action;
$icon_id = request_var('id', 0);
+ $submit = $request->is_set_post('submit', false);
+
+ $form_key = 'acp_icons';
+ add_form_key($form_key);
+
+ if ($submit && !check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
$mode = ($mode == 'smilies') ? 'smilies' : 'icons';
@@ -811,6 +820,11 @@ class acp_icons
case 'move_up':
case 'move_down':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_icons'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
// Get current order id...
$sql = "SELECT {$fields}_order as current_order
FROM $table
@@ -928,8 +942,8 @@ class acp_icons
'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '',
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row[$fields . '_id'],
'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row[$fields . '_id'],
- 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start,
- 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start,
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start . '&amp;hash=' . generate_link_hash('acp_icons'),
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start . '&amp;hash=' . generate_link_hash('acp_icons'),
));
if (!$spacer && !$row['display_on_posting'])
diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php
index 3888a411f0..bddc2be9cb 100644
--- a/phpBB/includes/acp/acp_language.php
+++ b/phpBB/includes/acp/acp_language.php
@@ -244,6 +244,11 @@ class acp_language
break;
case 'install':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_language'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$lang_iso = request_var('iso', '');
$lang_iso = basename($lang_iso);
@@ -423,7 +428,7 @@ class acp_language
'ISO' => htmlspecialchars($lang_ary['iso']),
'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'),
'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'),
- 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;iso=' . urlencode($lang_ary['iso']))
+ 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;iso=' . urlencode($lang_ary['iso']) . '&amp;hash=' . generate_link_hash('acp_language'))
);
}
}
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 55ea26b9d3..9d14614417 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -46,6 +46,9 @@ class acp_modules
$user->add_lang('acp/modules');
$this->tpl_name = 'acp_modules';
+ $form_key = 'acp_modules';
+ add_form_key($form_key);
+
// module class
$this->module_class = $mode;
@@ -119,6 +122,11 @@ class acp_modules
trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
+ if (!check_link_hash($request->variable('hash', ''), 'acp_modules'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
$sql = 'SELECT *
FROM ' . MODULES_TABLE . "
WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
@@ -150,6 +158,11 @@ class acp_modules
trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
+ if (!check_link_hash($request->variable('hash', ''), 'acp_modules'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
$sql = 'SELECT *
FROM ' . MODULES_TABLE . "
WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
@@ -273,6 +286,11 @@ class acp_modules
if ($submit)
{
+ if (!check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
if (!$module_data['module_langname'])
{
trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
@@ -460,12 +478,12 @@ class acp_modules
'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false,
'U_MODULE' => $this->u_action . '&amp;parent_id=' . $row['module_id'],
- 'U_MOVE_UP' => $url . '&amp;action=move_up',
- 'U_MOVE_DOWN' => $url . '&amp;action=move_down',
+ 'U_MOVE_UP' => $url . '&amp;action=move_up&amp;hash=' . generate_link_hash('acp_modules'),
+ 'U_MOVE_DOWN' => $url . '&amp;action=move_down&amp;hash=' . generate_link_hash('acp_modules'),
'U_EDIT' => $url . '&amp;action=edit',
'U_DELETE' => $url . '&amp;action=delete',
- 'U_ENABLE' => $url . '&amp;action=enable',
- 'U_DISABLE' => $url . '&amp;action=disable')
+ 'U_ENABLE' => $url . '&amp;action=enable&amp;hash=' . generate_link_hash('acp_modules'),
+ 'U_DISABLE' => $url . '&amp;action=disable&amp;hash=' . generate_link_hash('acp_modules'))
);
}
while ($row = $db->sql_fetchrow($result));
@@ -484,8 +502,8 @@ class acp_modules
'U_EDIT' => $url . '&amp;action=edit',
'U_DELETE' => $url . '&amp;action=delete',
- 'U_ENABLE' => $url . '&amp;action=enable',
- 'U_DISABLE' => $url . '&amp;action=disable')
+ 'U_ENABLE' => $url . '&amp;action=enable&amp;hash=' . generate_link_hash('acp_modules'),
+ 'U_DISABLE' => $url . '&amp;action=disable&amp;hash=' . generate_link_hash('acp_modules'))
);
}
$db->sql_freeresult($result);
diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php
index be4ab4676a..0796b36fef 100644
--- a/phpBB/includes/acp/acp_permission_roles.php
+++ b/phpBB/includes/acp/acp_permission_roles.php
@@ -366,6 +366,11 @@ class acp_permission_roles
case 'move_up':
case 'move_down':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_permission_roles'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$sql = 'SELECT role_order
FROM ' . ACL_ROLES_TABLE . "
WHERE role_id = $role_id";
@@ -440,8 +445,8 @@ class acp_permission_roles
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;role_id=' . $row['role_id'],
'U_REMOVE' => $this->u_action . '&amp;action=remove&amp;role_id=' . $row['role_id'],
- 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;role_id=' . $row['role_id'],
- 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;role_id=' . $row['role_id'],
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;role_id=' . $row['role_id'] . '&amp;hash=' . generate_link_hash('acp_permission_roles'),
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;role_id=' . $row['role_id'] . '&amp;hash=' . generate_link_hash('acp_permission_roles'),
'U_DISPLAY_ITEMS' => ($row['role_id'] == $display_item) ? '' : $this->u_action . '&amp;display_item=' . $row['role_id'] . '#assigned_to')
);
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index 8c7691538c..485f849f51 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -53,6 +53,9 @@ class acp_profile
$error = array();
$s_hidden_fields = '';
+ $form_key = 'acp_profile';
+ add_form_key($form_key);
+
if (!$field_id && in_array($action, array('delete','activate', 'deactivate', 'move_up', 'move_down', 'edit')))
{
trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
@@ -161,6 +164,11 @@ class acp_profile
case 'activate':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$sql = 'SELECT lang_id
FROM ' . LANG_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
@@ -201,6 +209,11 @@ class acp_profile
case 'deactivate':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
SET field_active = 0
WHERE field_id = $field_id";
@@ -230,6 +243,11 @@ class acp_profile
case 'move_up':
case 'move_down':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$sql = 'SELECT field_order
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_id = $field_id";
@@ -579,6 +597,11 @@ class acp_profile
if (!sizeof($error))
{
+ if (!check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
if (($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save))
{
$this->save_profile_field($cp, $field_type, $action);
@@ -735,12 +758,12 @@ class acp_profile
'FIELD_TYPE' => $profile_field->get_name(),
'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang],
- 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&amp;action=$active_value&amp;field_id=$id",
+ 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&amp;action=$active_value&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
'U_EDIT' => $this->u_action . "&amp;action=edit&amp;field_id=$id",
'U_TRANSLATE' => $this->u_action . "&amp;action=edit&amp;field_id=$id&amp;step=3",
'U_DELETE' => $this->u_action . "&amp;action=delete&amp;field_id=$id",
- 'U_MOVE_UP' => $this->u_action . "&amp;action=move_up&amp;field_id=$id",
- 'U_MOVE_DOWN' => $this->u_action . "&amp;action=move_down&amp;field_id=$id",
+ 'U_MOVE_UP' => $this->u_action . "&amp;action=move_up&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
+ 'U_MOVE_DOWN' => $this->u_action . "&amp;action=move_down&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
'S_NEED_EDIT' => $s_need_edit)
);
diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php
index 3d7ccf422c..bd40a88138 100644
--- a/phpBB/includes/acp/acp_reasons.php
+++ b/phpBB/includes/acp/acp_reasons.php
@@ -282,6 +282,11 @@ class acp_reasons
case 'move_up':
case 'move_down':
+ if (!check_link_hash($request->variable('hash', ''), 'acp_reasons'))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$sql = 'SELECT reason_order
FROM ' . REPORTS_REASONS_TABLE . "
WHERE reason_id = $reason_id";
@@ -383,8 +388,8 @@ class acp_reasons
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row['reason_id'],
'U_DELETE' => (!$other_reason) ? $this->u_action . '&amp;action=delete&amp;id=' . $row['reason_id'] : '',
- 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row['reason_id'],
- 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row['reason_id'])
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row['reason_id'] . '&amp;hash=' . generate_link_hash('acp_reasons'),
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row['reason_id'] . '&amp;hash=' . generate_link_hash('acp_reasons'))
);
}
$db->sql_freeresult($result);
diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php
index abb8301507..f15a75e9a1 100644
--- a/phpBB/includes/acp/acp_search.php
+++ b/phpBB/includes/acp/acp_search.php
@@ -54,6 +54,13 @@ class acp_search
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$submit = (isset($_POST['submit'])) ? true : false;
+ $form_key = 'acp_search';
+ add_form_key($form_key);
+
+ if ($submit && !check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
$search_types = $this->get_search_types();
@@ -232,7 +239,7 @@ class acp_search
function index($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
+ global $db, $user, $auth, $template, $cache, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$action = request_var('action', '');
@@ -244,6 +251,15 @@ class acp_search
$this->state = array();
$this->save_state();
}
+ $submit = $request->is_set_post('submit', false);
+
+ $form_key = 'acp_search';
+ add_form_key($form_key);
+
+ if (!check_form_key($form_key) && in_array($action, array('delete', 'create')))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
if ($action)
{
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 9c543eaac6..1dc246ec33 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -65,7 +65,7 @@ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = ar
*/
function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false)
{
- global $db, $user, $auth;
+ global $db, $user, $auth, $phpbb_dispatcher;
// This query is identical to the jumpbox one
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id
@@ -73,16 +73,33 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl =
ORDER BY left_id ASC';
$result = $db->sql_query($sql, 600);
+ $rowset = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $rowset[(int) $row['forum_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+
$right = 0;
$padding_store = array('0' => '');
$padding = '';
$forum_list = ($return_array) ? array() : '';
+ /**
+ * Modify the forum list data
+ *
+ * @event core.make_forum_select_modify_forum_list
+ * @var array rowset Array with the forums list data
+ * @since 3.1.10-RC1
+ */
+ $vars = array('rowset');
+ extract($phpbb_dispatcher->trigger_event('core.make_forum_select_modify_forum_list', compact($vars)));
+
// Sometimes it could happen that forums will be displayed here not be displayed within the index page
// This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions.
// If this happens, the padding could be "broken"
- while ($row = $db->sql_fetchrow($result))
+ foreach ($rowset as $row)
{
if ($row['left_id'] < $right)
{
@@ -133,8 +150,7 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl =
$forum_list .= '<option value="' . $row['forum_id'] . '"' . (($disabled) ? ' disabled="disabled" class="disabled-option"' : $selected) . '>' . $padding . $row['forum_name'] . '</option>';
}
}
- $db->sql_freeresult($result);
- unset($padding_store);
+ unset($padding_store, $rowset);
return $forum_list;
}
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index 87dd306e8a..8e60804d6e 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -163,16 +163,33 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list
ORDER BY left_id ASC';
$result = $db->sql_query($sql, 600);
+ $rowset = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $rowset[(int) $row['forum_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+
$right = $padding = 0;
$padding_store = array('0' => 0);
$display_jumpbox = false;
$iteration = 0;
+ /**
+ * Modify the jumpbox forum list data
+ *
+ * @event core.make_jumpbox_modify_forum_list
+ * @var array rowset Array with the forums list data
+ * @since 3.1.10-RC1
+ */
+ $vars = array('rowset');
+ extract($phpbb_dispatcher->trigger_event('core.make_jumpbox_modify_forum_list', compact($vars)));
+
// Sometimes it could happen that forums will be displayed here not be displayed within the index page
// This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions.
// If this happens, the padding could be "broken"
- while ($row = $db->sql_fetchrow($result))
+ foreach ($rowset as $row)
{
if ($row['left_id'] < $right)
{
@@ -254,8 +271,7 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list
}
$iteration++;
}
- $db->sql_freeresult($result);
- unset($padding_store);
+ unset($padding_store, $rowset);
$url_parts = $phpbb_path_helper->get_url_parts($action);
diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php
index 2c6f62227c..c571de579e 100644
--- a/phpBB/includes/functions_download.php
+++ b/phpBB/includes/functions_download.php
@@ -284,7 +284,7 @@ function header_filename($file)
// There be dragons here.
// Not many follows the RFC...
- if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Safari') !== false || strpos($user_agent, 'Konqueror') !== false)
+ if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false)
{
return "filename=" . rawurlencode($file);
}
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 0525cfc29e..9b3ca14101 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -231,6 +231,13 @@ class messenger
$template_lang = basename($config['default_lang']);
}
+ $ext_template_paths = array(
+ array(
+ 'name' => $template_lang . '_email',
+ 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix,
+ ),
+ );
+
if ($template_path)
{
$template_paths = array(
@@ -246,23 +253,38 @@ class messenger
$template_path . $template_dir_prefix,
);
+ $board_language = basename($config['default_lang']);
+
// we can only specify default language fallback when the path is not a custom one for which we
// do not know the default language alternative
- if ($template_lang !== basename($config['default_lang']))
+ if ($template_lang !== $board_language)
{
$fallback_template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
- $fallback_template_path .= basename($config['default_lang']) . '/email';
+ $fallback_template_path .= $board_language . '/email';
$template_paths[] = $fallback_template_path . $template_dir_prefix;
+
+ $ext_template_paths[] = array(
+ 'name' => $board_language . '_email',
+ 'ext_path' => 'language/' . $board_language . '/email' . $template_dir_prefix,
+ );
+ }
+ // If everything fails just fall back to en template
+ if ($template_lang !== 'en' && $board_language !== 'en')
+ {
+ $fallback_template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
+ $fallback_template_path .= 'en/email';
+
+ $template_paths[] = $fallback_template_path . $template_dir_prefix;
+
+ $ext_template_paths[] = array(
+ 'name' => 'en_email',
+ 'ext_path' => 'language/en/email' . $template_dir_prefix,
+ );
}
}
- $this->set_template_paths(array(
- array(
- 'name' => $template_lang . '_email',
- 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix,
- ),
- ), $template_paths);
+ $this->set_template_paths($ext_template_paths, $template_paths);
$this->template->set_filenames(array(
'body' => $template_file . '.txt',
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index bfdd1badc3..b82abe0c5e 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -119,19 +119,29 @@ function user_update_name($old_name, $new_name)
global $config, $db, $cache, $phpbb_dispatcher;
$update_ary = array(
- FORUMS_TABLE => array('forum_last_poster_name'),
- MODERATOR_CACHE_TABLE => array('username'),
- POSTS_TABLE => array('post_username'),
- TOPICS_TABLE => array('topic_first_poster_name', 'topic_last_poster_name'),
+ FORUMS_TABLE => array(
+ 'forum_last_poster_id' => 'forum_last_poster_name',
+ ),
+ MODERATOR_CACHE_TABLE => array(
+ 'user_id' => 'username',
+ ),
+ POSTS_TABLE => array(
+ 'poster_id' => 'post_username',
+ ),
+ TOPICS_TABLE => array(
+ 'topic_poster' => 'topic_first_poster_name',
+ 'topic_last_poster_id' => 'topic_last_poster_name',
+ ),
);
foreach ($update_ary as $table => $field_ary)
{
- foreach ($field_ary as $field)
+ foreach ($field_ary as $id_field => $name_field)
{
$sql = "UPDATE $table
- SET $field = '" . $db->sql_escape($new_name) . "'
- WHERE $field = '" . $db->sql_escape($old_name) . "'";
+ SET $name_field = '" . $db->sql_escape($new_name) . "'
+ WHERE $name_field = '" . $db->sql_escape($old_name) . "'
+ AND $id_field <> " . ANONYMOUS;
$db->sql_query($sql);
}
}
@@ -3076,7 +3086,7 @@ function remove_default_rank($group_id, $user_ids)
*/
function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false)
{
- global $db, $auth, $phpbb_root_path, $phpEx, $config, $phpbb_container;
+ global $db, $auth, $phpbb_root_path, $phpEx, $config, $phpbb_container, $phpbb_dispatcher;
// We need both username and user_id info
$result = user_get_id_name($user_id_ary, $username_ary);
@@ -3207,6 +3217,28 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
break;
}
+ /**
+ * Event to perform additional actions on setting user group attributes
+ *
+ * @event core.user_set_group_attributes
+ * @var int group_id ID of the group
+ * @var string group_name Name of the group
+ * @var array user_id_ary IDs of the users to set group attributes
+ * @var array username_ary Names of the users to set group attributes
+ * @var array group_attributes Group attributes which were changed
+ * @var string action Action to perform over the group members
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'group_id',
+ 'group_name',
+ 'user_id_ary',
+ 'username_ary',
+ 'group_attributes',
+ 'action',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.user_set_group_attributes', compact($vars)));
+
// Clear permissions cache of relevant users
$auth->acl_clear_prefetch($user_id_ary);
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index 6faf0de35b..9573ecbe0d 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -273,7 +273,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
- 'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'POSTS_DELETED') : '',
+ 'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'TOPIC_DELETED') : '',
'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index d0908a0d8b..b2441aed1b 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -877,11 +877,12 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = ''
}
$template->assign_vars(array(
- 'S_SHADOW_TOPICS' => $only_shadow,
- 'S_SOFTDELETED' => $only_softdeleted,
- 'S_TOPIC_MODE' => true,
- 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id),
- 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id),
+ 'S_SHADOW_TOPICS' => $only_shadow,
+ 'S_SOFTDELETED' => $only_softdeleted,
+ 'S_TOPIC_MODE' => true,
+ 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id),
+ 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id),
+ 'DELETE_TOPIC_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_TOPIC_PERMANENTLY', sizeof($topic_ids)),
));
$l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS';
@@ -1116,9 +1117,10 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
}
$template->assign_vars(array(
- 'S_SOFTDELETED' => $only_softdeleted,
- 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id),
- 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id),
+ 'S_SOFTDELETED' => $only_softdeleted,
+ 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id),
+ 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id),
+ 'DELETE_POST_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_POST_PERMANENTLY', sizeof($post_ids)),
));
$l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS';
diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php
index a1624e78ec..8584a9a0fd 100644
--- a/phpBB/includes/ucp/ucp_main.php
+++ b/phpBB/includes/ucp/ucp_main.php
@@ -35,7 +35,7 @@ class ucp_main
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $phpbb_dispatcher;
global $request;
switch ($mode)
@@ -215,6 +215,14 @@ class ucp_main
$unwatch = (isset($_POST['unwatch'])) ? true : false;
+ /**
+ * Read and potentially modify the post data used to remove subscriptions to forums/topics
+ *
+ * @event core.ucp_main_subscribed_post_data
+ * @since 3.1.10-RC1
+ */
+ $phpbb_dispatcher->dispatch('core.ucp_main_subscribed_post_data');
+
if ($unwatch)
{
if (check_form_key('ucp_front_subscribed'))
@@ -300,6 +308,20 @@ class ucp_main
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
}
+ /**
+ * Modify the query used to retrieve a list of subscribed forums
+ *
+ * @event core.ucp_main_subscribed_forums_modify_query
+ * @var array sql_array The subscribed forums query
+ * @var array forbidden_forums The list of forbidden forums
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'sql_array',
+ 'forbidden_forums',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.ucp_main_subscribed_forums_modify_query', compact($vars)));
+
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query($sql);
@@ -341,7 +363,7 @@ class ucp_main
$last_post_time = $last_post_url = '';
}
- $template->assign_block_vars('forumrow', array(
+ $template_vars = array(
'FORUM_ID' => $forum_id,
'FORUM_IMG_STYLE' => $folder_image,
'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt),
@@ -360,8 +382,36 @@ class ucp_main
'S_UNREAD_FORUM' => $unread_forum,
'U_LAST_POST' => $last_post_url,
- 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']))
+ 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])
+ );
+
+ /**
+ * Add template variables to a subscribed forum row.
+ *
+ * @event core.ucp_main_subscribed_forum_modify_template_vars
+ * @var array template_vars Array containing the template variables for the row
+ * @var array row Array containing the subscribed forum row data
+ * @var int forum_id Forum ID
+ * @var string folder_image Folder image
+ * @var string folder_alt Alt text for the folder image
+ * @var bool unread_forum Whether the forum has unread content or not
+ * @var string last_post_time The time of the most recent post, expressed as a formatted date string
+ * @var string last_post_url The URL of the most recent post in the forum
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'template_vars',
+ 'row',
+ 'forum_id',
+ 'folder_image',
+ 'folder_alt',
+ 'unread_forum',
+ 'last_post_time',
+ 'last_post_url',
);
+ extract($phpbb_dispatcher->trigger_event('core.ucp_main_subscribed_forum_modify_template_vars', compact($vars)));
+
+ $template->assign_block_vars('forumrow', $template_vars);
}
$db->sql_freeresult($result);
}
@@ -643,7 +693,7 @@ class ucp_main
*/
function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array())
{
- global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container;
+ global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container, $request, $phpbb_dispatcher;
$table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE;
$start = request_var('start', 0);
@@ -664,6 +714,23 @@ class ucp_main
AND i.user_id = ' . $user->data['user_id'] . '
AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true),
);
+
+ /**
+ * Modify the query used to retrieve the count of subscribed/bookmarked topics
+ *
+ * @event core.ucp_main_topiclist_count_modify_query
+ * @var array sql_array The subscribed/bookmarked topics query
+ * @var array forbidden_forum_ary The list of forbidden forums
+ * @var string mode The type of topic list ('subscribed' or 'bookmarks')
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'sql_array',
+ 'forbidden_forum_ary',
+ 'mode',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_count_modify_query', compact($vars)));
+
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query($sql);
$topics_count = (int) $db->sql_fetchfield('topics_count');
@@ -732,6 +799,22 @@ class ucp_main
$sql_array['SELECT'] .= ', tp.topic_posted';
}
+ /**
+ * Modify the query used to retrieve the list of subscribed/bookmarked topics
+ *
+ * @event core.ucp_main_topiclist_modify_query
+ * @var array sql_array The subscribed/bookmarked topics query
+ * @var array forbidden_forum_ary The list of forbidden forums
+ * @var string mode The type of topic list ('subscribed' or 'bookmarks')
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'sql_array',
+ 'forbidden_forum_ary',
+ 'mode',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_modify_query', compact($vars)));
+
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start);
@@ -796,7 +879,7 @@ class ucp_main
$view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params);
// Send vars to template
- $template->assign_block_vars('topicrow', array(
+ $template_vars = array(
'FORUM_ID' => $forum_id,
'TOPIC_ID' => $topic_id,
'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
@@ -838,7 +921,41 @@ class ucp_main
'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&amp;p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'],
'U_VIEW_TOPIC' => $view_topic_url,
'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
- ));
+ );
+
+ /**
+ * Add template variables to a subscribed/bookmarked topic row.
+ *
+ * @event core.ucp_main_topiclist_topic_modify_template_vars
+ * @var array template_vars Array containing the template variables for the row
+ * @var array row Array containing the subscribed/bookmarked topic row data
+ * @var int forum_id ID of the forum containing the topic
+ * @var int topic_id Topic ID
+ * @var int replies Number of replies in the topic
+ * @var string topic_type Topic type
+ * @var string folder_img Folder image
+ * @var string folder_alt Alt text for the folder image
+ * @var array icons Array containing topic icons
+ * @var bool unread_topic Whether the topic has unread content or not
+ * @var string view_topic_url The URL of the topic
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'template_vars',
+ 'row',
+ 'forum_id',
+ 'topic_id',
+ 'replies',
+ 'topic_type',
+ 'folder_img',
+ 'folder_alt',
+ 'icons',
+ 'unread_topic',
+ 'view_topic_url',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_topic_modify_template_vars', compact($vars)));
+
+ $template->assign_block_vars('topicrow', $template_vars);
$pagination->generate_template_pagination(append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . "&amp;t=$topic_id"), 'topicrow.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
}
diff --git a/phpBB/index.php b/phpBB/index.php
index eb9a657b3f..e4c03949c1 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -184,8 +184,8 @@ if ($config['load_birthdays'] && $config['allow_birthdays'] && $auth->acl_gets('
* Event to modify the birthdays list
*
* @event core.index_modify_birthdays_list
- * @var array birthdays Array with the users birhtdays data
- * @var array rows Array with the birhtdays SQL query result
+ * @var array birthdays Array with the users birthdays data
+ * @var array rows Array with the birthdays SQL query result
* @since 3.1.7-RC1
*/
$vars = array('birthdays', 'rows');
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 0ea6eeffd7..f367ae1fc0 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -211,13 +211,6 @@ while (!$migrator->finished())
phpbb_end_update($cache, $config);
}
- $state = array_merge(array(
- 'migration_schema_done' => false,
- 'migration_data_done' => false,
- ),
- $migrator->last_run_migration['state']
- );
-
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
if ((time() - $update_start_time) >= $safe_time_limit)
{
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
index bb3a74ee5e..8e57ed3edd 100644
--- a/phpBB/install/install_install.php
+++ b/phpBB/install/install_install.php
@@ -151,10 +151,10 @@ class install_install extends module
'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'],
));
- // Test the minimum PHP version
+ // Test the minimum and maximum version of PHP
$php_version = PHP_VERSION;
- if (version_compare($php_version, '5.3.3') < 0)
+ if ((version_compare($php_version, '5.3.3') < 0) || (version_compare($php_version, '7.0.0-dev', '>=')))
{
$result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
}
diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php
index bda965b615..c52b71c121 100644
--- a/phpBB/language/en/acp/search.php
+++ b/phpBB/language/en/acp/search.php
@@ -54,7 +54,7 @@ $lang = array_merge($lang, array(
'DELETING_INDEX_IN_PROGRESS_EXPLAIN' => 'The search backend is currently cleaning its index. This can take a few minutes.',
'FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE' => 'The MySQL fulltext backend can only be used with MySQL4 and above.',
- 'FULLTEXT_MYSQL_NOT_SUPPORTED' => 'MySQL fulltext indexes can only be used with MyISAM or InnoDB tables. MySQL 5.6.4 or later is required for fulltext indexes on InnoDB tables.',
+ 'FULLTEXT_MYSQL_NOT_SUPPORTED' => 'MySQL fulltext indexes can only be used with MyISAM or InnoDB tables. MySQL 5.6.8 or later is required for fulltext indexes on InnoDB tables.',
'FULLTEXT_MYSQL_TOTAL_POSTS' => 'Total number of indexed posts',
'FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
'FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php
index 2542066596..6477a929e9 100644
--- a/phpBB/language/en/install.php
+++ b/phpBB/language/en/install.php
@@ -301,10 +301,10 @@ $lang = array_merge($lang, array(
'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.',
'PHP_SAFE_MODE' => 'Safe mode',
'PHP_SETTINGS' => 'PHP version and settings',
- 'PHP_SETTINGS_EXPLAIN' => '<strong>Required</strong> - You must be running at least version 5.3.3 of PHP in order to install phpBB. If <var>safe mode</var> is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.',
+ 'PHP_SETTINGS_EXPLAIN' => '<strong>Required</strong> - You must be running at least version 5.3.3 of PHP (PHP 7 is not supported) in order to install phpBB. If <var>safe mode</var> is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.',
'PHP_URL_FOPEN_SUPPORT' => 'PHP setting <var>allow_url_fopen</var> is enabled',
'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => '<strong>Optional</strong> - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.',
- 'PHP_VERSION_REQD' => 'PHP version >= 5.3.3',
+ 'PHP_VERSION_REQD' => 'PHP version: >= 5.3.3, < 7.0.0-dev',
'POST_ID' => 'Post ID',
'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using <strong>%s</strong> as table prefix.',
'PREPROCESS_STEP' => 'Executing pre-processing functions/queries',
diff --git a/phpBB/language/en/migrator.php b/phpBB/language/en/migrator.php
index 244a5faadf..b3b5995cc0 100644
--- a/phpBB/language/en/migrator.php
+++ b/phpBB/language/en/migrator.php
@@ -50,6 +50,7 @@ $lang = array_merge($lang, array(
'MIGRATION_NOT_FULFILLABLE' => 'The migration "%1$s" is not fulfillable, missing migration "%2$s".',
'MIGRATION_NOT_VALID' => '%s is not a valid migration.',
'MIGRATION_SCHEMA_DONE' => 'Installed Schema: %1$s; Time: %2$.2f seconds',
+ 'MIGRATION_SCHEMA_IN_PROGRESS' => 'Installing Schema: %1$s; Time: %2$.2f seconds',
'MIGRATION_SCHEMA_RUNNING' => 'Installing Schema: %s.',
'MIGRATION_INVALID_DATA_MISSING_CONDITION' => 'A migration is invalid. An if statement helper is missing a condition.',
@@ -60,9 +61,12 @@ $lang = array_merge($lang, array(
'MIGRATION_INVALID_DATA_UNDEFINED_METHOD' => 'A migration is invalid. An undefined migration tool method was encountered.',
'MODULE_ERROR' => 'An error occurred while creating a module: %s',
+ 'MODULE_EXISTS' => 'A module already exists: %s',
+ 'MODULE_EXIST_MULTIPLE' => 'Several modules with the given parent module langname already exist: %s. Try using before/after keys to clarify the module placement.',
'MODULE_INFO_FILE_NOT_EXIST' => 'A required module info file is missing: %2$s',
'MODULE_NOT_EXIST' => 'A required module does not exist: %s',
+ 'PARENT_MODULE_FIND_ERROR' => 'Unable to determine the parent module identifier: %s',
'PERMISSION_NOT_EXIST' => 'The permission setting "%s" unexpectedly does not exist.',
'ROLE_NOT_EXIST' => 'The permission role "%s" unexpectedly does not exist.',
diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php
index 924395ed44..ef52f59753 100644
--- a/phpBB/language/en/posting.php
+++ b/phpBB/language/en/posting.php
@@ -90,14 +90,20 @@ $lang = array_merge($lang, array(
'DELETE_PERMANENTLY' => 'Delete permanently',
'DELETE_POST_CONFIRM' => 'Are you sure you want to delete this post?',
'DELETE_POST_PERMANENTLY_CONFIRM' => 'Are you sure you want to <strong>permanently</strong> delete this post?',
- 'DELETE_POST_PERMANENTLY' => 'Permanently delete this post so it can not be recovered',
+ 'DELETE_POST_PERMANENTLY' => array(
+ 1 => 'Permanently delete this post so it can not be recovered',
+ 2 => 'Permanently delete %1$d posts so they can not be recovered',
+ ),
'DELETE_POSTS_CONFIRM' => 'Are you sure you want to delete these posts?',
'DELETE_POSTS_PERMANENTLY_CONFIRM' => 'Are you sure you want to <strong>permanently</strong> delete these posts?',
'DELETE_REASON' => 'Reason for deletion',
'DELETE_REASON_EXPLAIN' => 'The specified reason for deletion will be visible to moderators.',
'DELETE_POST_WARN' => 'Delete this post',
'DELETE_TOPIC_CONFIRM' => 'Are you sure you want to delete this topic?',
- 'DELETE_TOPIC_PERMANENTLY' => 'Permanently delete this topic so it can not be recovered',
+ 'DELETE_TOPIC_PERMANENTLY' => array(
+ 1 => 'Permanently delete this topic so it can not be recovered',
+ 2 => 'Permanently delete %1$d topics so they can not be recovered',
+ ),
'DELETE_TOPIC_PERMANENTLY_CONFIRM' => 'Are you sure you want to <strong>permanently</strong> delete this topic?',
'DELETE_TOPICS_CONFIRM' => 'Are you sure you want to delete these topics?',
'DELETE_TOPICS_PERMANENTLY_CONFIRM' => 'Are you sure you want to <strong>permanently</strong> delete these topics?',
diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php
index 147b8ebbff..bf7dc2c703 100644
--- a/phpBB/phpbb/content_visibility.php
+++ b/phpBB/phpbb/content_visibility.php
@@ -428,7 +428,35 @@ class content_visibility
'post_delete_time' => ((int) $time) ?: time(),
'post_delete_reason' => truncate_string($reason, 255, 255, false),
);
-
+ /**
+ * Perform actions right before the query to change post visibility
+ *
+ * @event core.set_post_visibility_before_sql
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool is_starter Are we changing the topic's starter?
+ * @var bool is_latest Are we changing the topic's latest post?
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'post_id',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'is_starter',
+ 'is_latest',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_before_sql', compact($vars)));
$sql = 'UPDATE ' . $this->posts_table . '
SET ' . $this->db->sql_build_array('UPDATE', $data) . '
WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
@@ -585,7 +613,35 @@ class content_visibility
WHERE topic_id = ' . (int) $topic_id;
$this->db->sql_query($sql);
}
-
+ /**
+ * Perform actions after all steps to changing post visibility
+ *
+ * @event core.set_post_visibility_after
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool is_starter Are we changing the topic's starter?
+ * @var bool is_latest Are we changing the topic's latest post?
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'post_id',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'is_starter',
+ 'is_latest',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_after', compact($vars)));
return $data;
}
@@ -645,7 +701,31 @@ class content_visibility
'topic_delete_time' => ((int) $time) ?: time(),
'topic_delete_reason' => truncate_string($reason, 255, 255, false),
);
-
+ /**
+ * Perform actions right before the query to change topic visibility
+ *
+ * @event core.set_topic_visibility_before_sql
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'force_update_all',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars)));
$sql = 'UPDATE ' . $this->topics_table . '
SET ' . $this->db->sql_build_array('UPDATE', $data) . '
WHERE topic_id = ' . (int) $topic_id;
@@ -670,7 +750,31 @@ class content_visibility
{
$this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
}
-
+ /**
+ * Perform actions after all steps to changing topic visibility
+ *
+ * @event core.set_topic_visibility_after
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'force_update_all',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars)));
return $data;
}
diff --git a/phpBB/phpbb/db/migration/helper.php b/phpBB/phpbb/db/migration/helper.php
index e40deeb37b..bce2efff51 100644
--- a/phpBB/phpbb/db/migration/helper.php
+++ b/phpBB/phpbb/db/migration/helper.php
@@ -81,4 +81,36 @@ class helper
return $steps;
}
+
+ /**
+ * Reverse the update steps from an array of data changes
+ *
+ * 'If' statements and custom methods will be skipped, for all
+ * other calls the reverse method of the tool class will be called
+ *
+ * @param array $steps Update changes from migration
+ *
+ * @return array
+ */
+ public function reverse_update_data($steps)
+ {
+ $reversed_array = array();
+
+ foreach ($steps as $step)
+ {
+ $parts = explode('.', $step[0]);
+ $parameters = $step[1];
+
+ $class = $parts[0];
+ $method = isset($parts[1]) ? $parts[1] : false;
+
+ if ($class !== 'if' && $class !== 'custom')
+ {
+ array_unshift($parameters, $method);
+ $reversed_array[] = array($class . '.reverse', $parameters);
+ }
+ }
+
+ return array_reverse($reversed_array);
+ }
}
diff --git a/phpBB/phpbb/db/migration/tool/config.php b/phpBB/phpbb/db/migration/tool/config.php
index f93e7118c4..33aa8ff026 100644
--- a/phpBB/phpbb/db/migration/tool/config.php
+++ b/phpBB/phpbb/db/migration/tool/config.php
@@ -150,6 +150,11 @@ class config implements \phpbb\db\migration\tool\tool_interface
$arguments[0],
);
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migration/tool/config_text.php b/phpBB/phpbb/db/migration/tool/config_text.php
index bf8ac55023..54b45f6f6d 100644
--- a/phpBB/phpbb/db/migration/tool/config_text.php
+++ b/phpBB/phpbb/db/migration/tool/config_text.php
@@ -115,6 +115,11 @@ class config_text implements \phpbb\db\migration\tool\tool_interface
$arguments[] = '';
}
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 035625b095..6d5378e35f 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -36,6 +36,9 @@ class module implements \phpbb\db\migration\tool\tool_interface
/** @var string */
protected $modules_table;
+ /** @var array */
+ protected $module_categories = array();
+
/**
* Constructor
*
@@ -87,30 +90,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
$parent_sql = '';
if ($parent !== false)
{
- // Allows '' to be sent as 0
- $parent = $parent ?: 0;
-
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- if (!$module_id)
- {
- return false;
- }
-
- $parent_sql = 'AND parent_id = ' . (int) $module_id;
- }
- else
- {
- $parent_sql = 'AND parent_id = ' . (int) $parent;
- }
+ $parent = $this->get_parent_module_id($parent, $module);
+ $parent_sql = 'AND parent_id = ' . (int) $parent;
}
$sql = 'SELECT module_id
@@ -171,15 +152,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
*/
public function add($class, $parent = 0, $data = array())
{
- // Allows '' to be sent as 0
- $parent = $parent ?: 0;
-
// allow sending the name as a string in $data to create a category
if (!is_array($data))
{
$data = array('module_langname' => $data);
}
+ $parent = $data['parent_id'] = $this->get_parent_module_id($parent, $data);
+
if (!isset($data['module_langname']))
{
// The "automatic" way
@@ -210,31 +190,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
}
// The "manual" way
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- if (!$module_id)
- {
- throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent);
- }
-
- $parent = $data['parent_id'] = $module_id;
- }
- else if (!$this->exists($class, false, $parent))
+ if (!$this->exists($class, false, $parent))
{
throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent);
}
if ($this->exists($class, $parent, $data['module_langname']))
{
- return;
+ throw new \phpbb\db\migration\exception('MODULE_EXISTS', $module_id);
}
if (!class_exists('acp_modules'))
@@ -373,26 +336,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
$parent_sql = '';
if ($parent !== false)
{
- // Allows '' to be sent as 0
- $parent = ($parent) ?: 0;
-
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- // we know it exists from the module_exists check
- $parent_sql = 'AND parent_id = ' . (int) $module_id;
- }
- else
- {
- $parent_sql = 'AND parent_id = ' . (int) $parent;
- }
+ $parent = $this->get_parent_module_id($parent, $module);
+ $parent_sql = 'AND parent_id = ' . (int) $parent;
}
$module_ids = array();
@@ -454,6 +399,11 @@ class module implements \phpbb\db\migration\tool\tool_interface
case 'remove':
$call = 'add';
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
@@ -487,4 +437,110 @@ class module implements \phpbb\db\migration\tool\tool_interface
return array_pop($module);
}
+
+ /**
+ * Get the list of installed module categories
+ * key - module_id
+ * value - module_langname
+ *
+ * @return null
+ */
+ protected function get_categories_list()
+ {
+ // Select the top level categories
+ // and 2nd level [sub]categories which exist for ACP only
+ $sql = 'SELECT m2.module_id, m2.module_langname
+ FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
+ WHERE m1.parent_id = 0
+ AND (m1.module_id = m2.module_id
+ OR m2.module_class = 'acp' AND m2.parent_id = m1.module_id)
+ ORDER BY m1.module_id, m2.module_id ASC";
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->module_categories[(int) $row['module_id']] = $row['module_langname'];
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Get parent module id
+ *
+ * @param string|int $parent_id The parent module_id|module_langname
+ * @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding
+ * @return int The parent module_id
+ * @throws \phpbb\db\migration\exception
+ */
+ public function get_parent_module_id($parent_id, $data = '')
+ {
+ // Allow '' to be sent as 0
+ $parent_id = $parent_id ?: 0;
+
+ // If automatic adding is in action, convert array back to string to simplify things
+ if (is_array($data) && sizeof($data) == 1)
+ {
+ $data = $data['module_langname'];
+ }
+
+ if (!is_numeric($parent_id))
+ {
+ // Refresh the $module_categories array
+ $this->get_categories_list();
+
+ // Search for the parent module_langname
+ $ids = array_keys($this->module_categories, $parent_id);
+
+ switch (sizeof($ids))
+ {
+ // No parent with the given module_langname exist
+ case 0:
+ throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id);
+ break;
+
+ // Return the module id
+ case 1:
+ $parent_id = (int) $ids[0];
+ break;
+
+ // Several modules with the given module_langname were found
+ // Try to determine the parent_id by the neighbour module parent
+ default:
+ if (is_array($data) && (isset($data['before']) || isset($data['after'])))
+ {
+ $neighbour_module_langname = isset($data['before']) ? $data['before'] : $data['after'];
+ $sql = 'SELECT parent_id
+ FROM ' . $this->modules_table . "
+ WHERE module_langname = '" . $this->db->sql_escape($neighbour_module_langname) . "'
+ AND " . $this->db->sql_in_set('parent_id', $ids);
+ $result = $this->db->sql_query($sql);
+ $parent_id = (int) $this->db->sql_fetchfield('parent_id');
+ if (!$parent_id)
+ {
+ throw new \phpbb\db\migration\exception('PARENT_MODULE_FIND_ERROR', $data['parent_id']);
+ }
+ }
+ else if (!empty($data) && !is_array($data))
+ {
+ // The module_langname is set, checking for the module existance
+ // As more than 1 parents were found already, there's no way for null parent_id here
+ $sql = 'SELECT m2.module_id as module_parent_id
+ FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
+ WHERE " . ((is_numeric($data)) ? 'm1.module_id = ' . (int) $data : "m1.module_langname = '" . $this->db->sql_escape($data)) . "'
+ AND m2.module_id = m1.parent_id
+ AND " . $this->db->sql_in_set('m2.module_id', $ids);
+ $result = $this->db->sql_query($sql);
+ $parent_id = (int) $this->db->sql_fetchfield('module_parent_id');
+ }
+ else
+ {
+ //Unable to get the parent module id, throwing an exception
+ throw new \phpbb\db\migration\exception('MODULE_EXIST_MULTIPLE', $parent_id);
+ }
+ break;
+ }
+ }
+
+ return $parent_id;
+ }
}
diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php
index ceff6d7d5a..9688420025 100644
--- a/phpBB/phpbb/db/migration/tool/permission.php
+++ b/phpBB/phpbb/db/migration/tool/permission.php
@@ -637,6 +637,11 @@ class permission implements \phpbb\db\migration\tool\tool_interface
$arguments[0],
);
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 7fc3e787e2..4c4c0a8672 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -80,14 +80,14 @@ class migrator
*
* @var array
*/
- public $last_run_migration = false;
+ protected $last_run_migration = false;
/**
* The output handler. A null handler is configured by default.
*
* @var migrator_output_handler_interface
*/
- public $output_handler;
+ protected $output_handler;
/**
* Constructor of the database migrator
@@ -152,6 +152,7 @@ class migrator
$this->migration_state[$migration['migration_name']] = $migration;
$this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']);
+ $this->migration_state[$migration['migration_name']]['migration_data_state'] = !empty($migration['migration_data_state']) ? unserialize($migration['migration_data_state']) : '';
}
}
@@ -161,6 +162,19 @@ class migrator
}
/**
+ * Get an array with information about the last migration run.
+ *
+ * The array contains 'name', 'class' and 'state'. 'effectively_installed' is set
+ * and set to true if the last migration was effectively_installed.
+ *
+ * @return array
+ */
+ public function get_last_run_migration()
+ {
+ return $this->last_run_migration;
+ }
+
+ /**
* Sets the list of available migration class names to the given array.
*
* @param array $class_names An array of migration class names
@@ -297,38 +311,70 @@ class migrator
if (!$state['migration_schema_done'])
{
- $this->output_handler->write(array('MIGRATION_SCHEMA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_SCHEMA_RUNNING', $name), $verbosity);
$this->last_run_migration['task'] = 'process_schema_step';
+
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
$elapsed_time = microtime(true);
+
$steps = $this->helper->get_schema_steps($migration->update_schema());
$result = $this->process_data_step($steps, $state['migration_data_state']);
+
$elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_schema_done'] = ($result === true);
- $this->output_handler->write(array('MIGRATION_SCHEMA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ if ($state['migration_schema_done'])
+ {
+ $this->output_handler->write(array('MIGRATION_SCHEMA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ }
+ else
+ {
+ $this->output_handler->write(array('MIGRATION_SCHEMA_IN_PROGRESS', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_VERY_VERBOSE);
+ }
}
else if (!$state['migration_data_done'])
{
try
{
- $this->output_handler->write(array('MIGRATION_DATA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_DATA_RUNNING', $name), $verbosity);
$this->last_run_migration['task'] = 'process_data_step';
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
$elapsed_time = microtime(true);
+
$result = $this->process_data_step($migration->update_data(), $state['migration_data_state']);
+
$elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true);
$state['migration_end_time'] = ($result === true) ? time() : 0;
- if ($state['migration_schema_done'])
+ if ($state['migration_data_done'])
{
- $this->output_handler->write(array('MIGRATION_DATA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ $this->output_handler->write(array('MIGRATION_DATA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
}
else
{
@@ -337,10 +383,12 @@ class migrator
}
catch (\phpbb\db\migration\exception $e)
{
- // Revert the schema changes
+ // Reset data state and revert the schema changes
+ $state['migration_data_state'] = '';
+ $this->set_migration_state($name, $state);
+
$this->revert_do($name);
- // Rethrow exception
throw $e;
}
}
@@ -416,19 +464,11 @@ class migrator
if ($state['migration_data_done'])
{
- if ($state['migration_data_state'] !== 'revert_data')
- {
- $result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true);
-
- $state['migration_data_state'] = ($result === true) ? 'revert_data' : $result;
- }
- else
- {
- $result = $this->process_data_step($migration->revert_data(), '', false);
+ $steps = array_merge($this->helper->reverse_update_data($migration->update_data()), $migration->revert_data());
+ $result = $this->process_data_step($steps, $state['migration_data_state']);
- $state['migration_data_state'] = ($result === true) ? '' : $result;
- $state['migration_data_done'] = ($result === true) ? false : true;
- }
+ $state['migration_data_state'] = ($result === true) ? '' : $result;
+ $state['migration_data_done'] = ($result === true) ? false : true;
$this->set_migration_state($name, $state);
}
@@ -446,8 +486,13 @@ class migrator
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ $this->last_run_migration = false;
unset($this->migration_state[$name]);
}
+ else
+ {
+ $this->set_migration_state($name, $state);
+ }
}
return true;
@@ -464,7 +509,12 @@ class migrator
*/
protected function process_data_step($steps, $state, $revert = false)
{
- $state = ($state) ? unserialize($state) : false;
+ if (sizeof($steps) === 0)
+ {
+ return true;
+ }
+
+ $state = is_array($state) ? $state : false;
// reverse order of steps if reverting
if ($revert === true)
@@ -472,54 +522,45 @@ class migrator
$steps = array_reverse($steps);
}
- foreach ($steps as $step_identifier => $step)
+ $step = $last_result = 0;
+ if ($state)
{
- $last_result = 0;
- if ($state)
- {
- // Continue until we reach the step that matches the last step called
- if ($state['step'] != $step_identifier)
- {
- continue;
- }
-
- // We send the result from last time to the callable function
- $last_result = $state['result'];
+ $step = $state['step'];
- // Set state to false since we reached the point we were at
- $state = false;
- }
+ // We send the result from last time to the callable function
+ $last_result = $state['result'];
+ }
- try
+ try
+ {
+ // Result will be null or true if everything completed correctly
+ // Stop after each update step, to let the updater control the script runtime
+ $result = $this->run_step($steps[$step], $last_result, $revert);
+ if (($result !== null && $result !== true) || $step + 1 < sizeof($steps))
{
- // Result will be null or true if everything completed correctly
- $result = $this->run_step($step, $last_result, $revert);
- if ($result !== null && $result !== true)
- {
- return serialize(array(
- 'result' => $result,
- 'step' => $step_identifier,
- ));
- }
+ return array(
+ 'result' => $result,
+ // Move on if the last call finished
+ 'step' => ($result !== null && $result !== true) ? $step : $step + 1,
+ );
}
- catch (\phpbb\db\migration\exception $e)
+ }
+ catch (\phpbb\db\migration\exception $e)
+ {
+ // We should try rolling back here
+ foreach ($steps as $reverse_step_identifier => $reverse_step)
{
- // We should try rolling back here
- foreach ($steps as $reverse_step_identifier => $reverse_step)
+ // If we've reached the current step we can break because we reversed everything that was run
+ if ($reverse_step_identifier == $step)
{
- // If we've reached the current step we can break because we reversed everything that was run
- if ($reverse_step_identifier == $step_identifier)
- {
- break;
- }
-
- // Reverse the step that was run
- $result = $this->run_step($reverse_step, false, !$revert);
+ break;
}
- // rethrow the exception
- throw $e;
+ // Reverse the step that was run
+ $result = $this->run_step($reverse_step, false, !$revert);
}
+
+ throw $e;
}
return true;
@@ -587,6 +628,13 @@ class migrator
throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step);
}
+ if ($reverse)
+ {
+ // We might get unexpected results when trying
+ // to revert this, so just avoid it
+ return false;
+ }
+
$condition = $parameters[0];
if (!$condition)
@@ -664,6 +712,7 @@ class migrator
{
$migration_row = $state;
$migration_row['migration_depends_on'] = serialize($state['migration_depends_on']);
+ $migration_row['migration_data_state'] = !empty($state['migration_data_state']) ? serialize($state['migration_data_state']) : '';
if (isset($this->migration_state[$name]))
{
diff --git a/phpBB/phpbb/db/migrator_output_handler_interface.php b/phpBB/phpbb/db/migrator_output_handler_interface.php
index a923af99f6..9947b51dcc 100644
--- a/phpBB/phpbb/db/migrator_output_handler_interface.php
+++ b/phpBB/phpbb/db/migrator_output_handler_interface.php
@@ -15,11 +15,11 @@ namespace phpbb\db;
interface migrator_output_handler_interface
{
- const VERBOSITY_QUIET = 0;
- const VERBOSITY_NORMAL = 1;
- const VERBOSITY_VERBOSE = 2;
- const VERBOSITY_VERY_VERBOSE = 3;
- const VERBOSITY_DEBUG = 4;
+ const VERBOSITY_QUIET = 16;
+ const VERBOSITY_NORMAL = 32;
+ const VERBOSITY_VERBOSE = 64;
+ const VERBOSITY_VERY_VERBOSE = 128;
+ const VERBOSITY_DEBUG = 256;
/**
* Write output using the configured closure.
diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php
index 3c6d617c66..0bfbfd6b02 100644
--- a/phpBB/phpbb/notification/method/messenger_base.php
+++ b/phpBB/phpbb/notification/method/messenger_base.php
@@ -81,7 +81,7 @@ abstract class messenger_base extends \phpbb\notification\method\base
$messenger->assign_vars(array_merge(array(
'USERNAME' => $user['username'],
- 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&amp;mode=notification_options',
+ 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&mode=notification_options',
), $notification->get_email_template_variables()));
$messenger->send($notify_method);
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index 3ddbd85b36..9faf5ca08b 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -177,8 +177,10 @@ class fulltext_mysql extends \phpbb\search\base
$engine === 'MyISAM' ||
// FULLTEXT is supported on InnoDB since MySQL 5.6.4 according to
// http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html
+ // We also require https://bugs.mysql.com/bug.php?id=67004 to be
+ // fixed for proper overall operation. Hence we require 5.6.8.
$engine === 'InnoDB' &&
- phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
+ phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>=');
if (!$fulltext_supported)
{
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index e2c02ffdab..63b0b24edf 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -1262,7 +1262,7 @@ class fulltext_native extends \phpbb\search\base
if (!$total_results && $is_mysql)
{
// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
- $sql_calc = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql);
+ $sql_calc = str_replace('SELECT ' . $select, 'SELECT SQL_CALC_FOUND_ROWS ' . $select, $sql);
$result = $this->db->sql_query($sql_calc);
$this->db->sql_freeresult($result);
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index 83e87b7704..eb5543b50b 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -219,7 +219,7 @@ class session
function session_begin($update_session_page = true)
{
global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path;
- global $request, $phpbb_container;
+ global $request, $phpbb_container, $phpbb_dispatcher;
// Give us some basic information
$this->time_now = time();
@@ -281,11 +281,21 @@ class session
// Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
// it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
- $this->ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));
- $this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip));
+ $ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));
+ $ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $ip));
+
+ /**
+ * Event to alter user IP address
+ *
+ * @event core.session_ip_after
+ * @var string ip REMOTE_ADDR
+ * @since 3.1.10-RC1
+ */
+ $vars = array('ip');
+ extract($phpbb_dispatcher->trigger_event('core.session_ip_after', compact($vars)));
// split the list of IPs
- $ips = explode(' ', trim($this->ip));
+ $ips = explode(' ', trim($ip));
// Default IP if REMOTE_ADDR is invalid
$this->ip = '127.0.0.1';
@@ -1585,7 +1595,7 @@ class session
$this->data = array_merge($this->data, $sql_ary);
- if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts'])
+ if ($this->data['user_id'] != ANONYMOUS && isset($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts'])
{
$this->leave_newly_registered();
}
diff --git a/phpBB/posting.php b/phpBB/posting.php
index 653740ae1c..db580d926b 100644
--- a/phpBB/posting.php
+++ b/phpBB/posting.php
@@ -371,7 +371,9 @@ switch ($mode)
* NOTE: Should be actual language strings, NOT
* language keys.
* @var bool is_authed Does the user have the required permissions?
+* @var array post_data All post data from database
* @since 3.1.3-RC1
+* @changed 3.1.10-RC1 Added post_data
*/
$vars = array(
'post_id',
@@ -387,6 +389,7 @@ $vars = array(
'mode',
'error',
'is_authed',
+ 'post_data',
);
extract($phpbb_dispatcher->trigger_event('core.modify_posting_auth', compact($vars)));
@@ -1741,6 +1744,7 @@ $page_data = array(
'L_POST_A' => $page_title,
'L_ICON' => ($mode == 'reply' || $mode == 'quote' || ($mode == 'edit' && $post_id != $post_data['topic_first_post_id'])) ? $user->lang['POST_ICON'] : $user->lang['TOPIC_ICON'],
'L_MESSAGE_BODY_EXPLAIN' => $user->lang('MESSAGE_BODY_EXPLAIN', (int) $config['max_post_chars']),
+ 'L_DELETE_POST_PERMANENTLY' => $user->lang('DELETE_POST_PERMANENTLY', 1),
'FORUM_NAME' => $post_data['forum_name'],
'FORUM_DESC' => ($post_data['forum_desc']) ? generate_text_for_display($post_data['forum_desc'], $post_data['forum_desc_uid'], $post_data['forum_desc_bitfield'], $post_data['forum_desc_options']) : '',
diff --git a/phpBB/search.php b/phpBB/search.php
index a0380590c1..03575f7e0b 100644
--- a/phpBB/search.php
+++ b/phpBB/search.php
@@ -126,6 +126,26 @@ gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
$pagination = $phpbb_container->get('pagination');
+/**
+* This event allows you to alter the above parameters, such as keywords and submit
+*
+* @event core.search_modify_submit_parameters
+* @var string keywords The search keywords
+* @var string author Specifies the author match, when ANONYMOUS is also a search-match
+* @var int author_id ID of the author to search by
+* @var string search_id Predefined search type name
+* @var bool submit Whether or not the form has been submitted
+* @since 3.1.10-RC1
+*/
+$vars = array(
+ 'keywords',
+ 'author',
+ 'author_id',
+ 'search_id',
+ 'submit',
+);
+extract($phpbb_dispatcher->trigger_event('core.search_modify_submit_parameters', compact($vars)));
+
if ($keywords || $author || $author_id || $search_id || $submit)
{
// clear arrays
@@ -575,6 +595,48 @@ if ($keywords || $author || $author_id || $search_id || $submit)
$total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page);
}
+ /**
+ * Event to search otherwise than by keywords or author
+ *
+ * @event core.search_backend_search_after
+ * @var string show_results 'posts' or 'topics' type of ids
+ * @var string search_fields The data fields to search in
+ * @var string search_terms Is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
+ * @var array sort_by_sql Array of SQL sorting instructions
+ * @var string sort_key The sort key
+ * @var string sort_dir The sort direction
+ * @var int sort_days Limit the age of results
+ * @var array ex_fid_ary Array of excluded forum ids
+ * @var string m_approve_posts_fid_sql Specifies which types of posts the user can view in which forums
+ * @var int topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
+ * @var array author_id_ary Array of exclusive author ids
+ * @var string sql_author_match Specifies the author match, when ANONYMOUS is also a search-match
+ * @var array id_ary Array of post or topic ids for search result
+ * @var int start The starting id of the results
+ * @var int per_page Number of ids each page is supposed to contain
+ * @var int total_match_count The total number of search matches
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'show_results',
+ 'search_fields',
+ 'search_terms',
+ 'sort_by_sql',
+ 'sort_key',
+ 'sort_dir',
+ 'sort_days',
+ 'ex_fid_ary',
+ 'm_approve_posts_fid_sql',
+ 'topic_id',
+ 'author_id_ary',
+ 'sql_author_match',
+ 'id_ary',
+ 'start',
+ 'per_page',
+ 'total_match_count',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.search_backend_search_after', compact($vars)));
+
$sql_where = '';
if (sizeof($id_ary))
@@ -625,11 +687,18 @@ if ($keywords || $author || $author_id || $search_id || $submit)
* @event core.search_modify_url_parameters
* @var string u_search Search URL parameters string
* @var string search_id Predefined search type name
+ * @var string show_results String indicating the show results mode
+ * @var string sql_where The SQL WHERE string used by search to get topic data
+ * @var int total_match_count The total number of search matches
* @since 3.1.7-RC1
+ * @changed 3.1.10-RC1 Added show_results, sql_where, total_match_count
*/
$vars = array(
'u_search',
'search_id',
+ 'show_results',
+ 'sql_where',
+ 'total_match_count',
);
extract($phpbb_dispatcher->trigger_event('core.search_modify_url_parameters', compact($vars)));
diff --git a/phpBB/styles/prosilver/template/confirm_delete_body.html b/phpBB/styles/prosilver/template/confirm_delete_body.html
index f0a7ab2bdb..fbd881a940 100644
--- a/phpBB/styles/prosilver/template/confirm_delete_body.html
+++ b/phpBB/styles/prosilver/template/confirm_delete_body.html
@@ -7,7 +7,7 @@
<label>
<strong>{L_DELETE_PERMANENTLY}{L_COLON}</strong>
<input id="delete_permanent" name="delete_permanent" type="checkbox" value="1" {S_CHECKED_PERMANENT} />
- <!-- IF S_TOPIC_MODE -->{L_DELETE_TOPIC_PERMANENTLY}<!-- ELSE -->{L_DELETE_POST_PERMANENTLY}<!-- ENDIF -->
+ <!-- IF S_TOPIC_MODE -->{DELETE_TOPIC_PERMANENTLY_EXPLAIN}<!-- ELSE -->{DELETE_POST_PERMANENTLY_EXPLAIN}<!-- ENDIF -->
</label>
<!-- ENDIF -->
@@ -43,7 +43,7 @@
<dd>
<label for="delete_permanent">
<input id="delete_permanent" name="delete_permanent" type="checkbox" value="1" {S_CHECKED_PERMANENT} />
- <!-- IF S_TOPIC_MODE -->{L_DELETE_TOPIC_PERMANENTLY}<!-- ELSE -->{L_DELETE_POST_PERMANENTLY}<!-- ENDIF -->
+ <!-- IF S_TOPIC_MODE -->{DELETE_TOPIC_PERMANENTLY_EXPLAIN}<!-- ELSE -->{DELETE_POST_PERMANENTLY_EXPLAIN}<!-- ENDIF -->
</label>
</dd>
</dl>
diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html
index e6978191de..22d837b3d1 100644
--- a/phpBB/styles/prosilver/template/mcp_topic.html
+++ b/phpBB/styles/prosilver/template/mcp_topic.html
@@ -73,7 +73,7 @@
<dl>
<dt><label for="to_topic_id">{L_MERGE_TOPIC_ID}{L_COLON}</label></dt>
<dd>
- <input class="inputbox autowidth" type="number" min="0" max="999999" name="to_topic_id" id="to_topic_id" value="{TO_TOPIC_ID}" />
+ <input class="inputbox autowidth" type="number" min="0" max="9999999999" name="to_topic_id" id="to_topic_id" value="{TO_TOPIC_ID}" />
<a href="{U_SELECT_TOPIC}" >{L_SELECT_TOPIC}</a>
</dd>
<!-- IF TO_TOPIC_INFO --><dd>{TO_TOPIC_INFO}</dd><!-- ENDIF -->
@@ -112,7 +112,10 @@
</ul>
<h3><a href="{postrow.U_POST_DETAILS}">{postrow.POST_SUBJECT}</a></h3>
+
+ <!-- EVENT mcp_topic_postrow_post_details_before -->
<p class="author"><a href="#pr{postrow.POST_ID}">{postrow.MINI_POST_IMG}</a> {L_POSTED} {postrow.POST_DATE} {L_POST_BY_AUTHOR} <strong>{postrow.POST_AUTHOR_FULL}</strong><!-- IF postrow.U_MCP_DETAILS --> [ <a href="{postrow.U_MCP_DETAILS}">{L_POST_DETAILS}</a> ]<!-- ENDIF --></p>
+ <!-- EVENT mcp_topic_postrow_post_details_after -->
<!-- IF postrow.S_POST_UNAPPROVED -->
<p class="post-notice unapproved">
diff --git a/phpBB/styles/prosilver/template/memberlist_email.html b/phpBB/styles/prosilver/template/memberlist_email.html
index 4a9f764d07..eea699da08 100644
--- a/phpBB/styles/prosilver/template/memberlist_email.html
+++ b/phpBB/styles/prosilver/template/memberlist_email.html
@@ -1,5 +1,7 @@
<!-- INCLUDE overall_header.html -->
+<!-- EVENT memberlist_email_before -->
+
<!-- IF S_CONTACT_ADMIN-->
<h2 class="titlespace">{L_CONTACT_ADMIN}</h2>
<!-- ELSEIF S_SEND_USER -->
diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html
index f897bf7a3b..5258ea09a2 100644
--- a/phpBB/styles/prosilver/template/posting_editor.html
+++ b/phpBB/styles/prosilver/template/posting_editor.html
@@ -23,7 +23,11 @@
<!-- IF S_POST_ACTION or S_PRIVMSGS or S_EDIT_DRAFT -->
<dl style="clear: left;">
<dt><label for="subject">{L_SUBJECT}{L_COLON}</label></dt>
- <dd><input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /></dd>
+ <dd>
+ <!-- EVENT posting_editor_subject_prepend -->
+ <input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" />
+ <!-- EVENT posting_editor_subject_append -->
+ </dd>
</dl>
<!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE -->
<!-- DEFINE $CAPTCHA_TAB_INDEX = 3 -->
diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html
index 6909877196..c51d8032dc 100644
--- a/phpBB/styles/prosilver/template/posting_topic_review.html
+++ b/phpBB/styles/prosilver/template/posting_topic_review.html
@@ -43,7 +43,10 @@
</ul>
<!-- ENDIF -->
+ <!-- EVENT posting_topic_review_row_post_details_before -->
<p class="author"><!-- IF S_IS_BOT -->{topic_review_row.MINI_POST_IMG}<!-- ELSE --><a href="{topic_review_row.U_MINI_POST}">{topic_review_row.MINI_POST_IMG}</a><!-- ENDIF --> {L_POST_BY_AUTHOR} <strong>{topic_review_row.POST_AUTHOR_FULL}</strong> &raquo; {topic_review_row.POST_DATE} </p>
+ <!-- EVENT posting_topic_review_row_post_details_after -->
+
<div class="content">{topic_review_row.MESSAGE}</div>
<!-- IF topic_review_row.S_HAS_ATTACHMENTS -->
diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html
index bb18a5dd2c..643b78823f 100644
--- a/phpBB/styles/prosilver/template/viewforum_body.html
+++ b/phpBB/styles/prosilver/template/viewforum_body.html
@@ -121,6 +121,8 @@
<!-- ENDIF -->
+<!-- EVENT viewforum_body_topic_row_before -->
+
<!-- BEGIN topicrow -->
<!-- IF not topicrow.S_TOPIC_TYPE_SWITCH and not topicrow.S_FIRST_ROW -->
@@ -145,7 +147,7 @@
<ul class="topiclist topics">
<!-- ENDIF -->
- <!-- EVENT viewforum_body_topic_row_before -->
+ <!-- EVENT viewforum_body_topicrow_row_before -->
<li class="row<!-- IF topicrow.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF topicrow.S_POST_GLOBAL --> global-announce<!-- ENDIF --><!-- IF topicrow.S_POST_ANNOUNCE --> announce<!-- ENDIF --><!-- IF topicrow.S_POST_STICKY --> sticky<!-- ENDIF --><!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ENDIF -->">
<!-- EVENT viewforum_body_topic_row_prepend -->
<dl class="icon {topicrow.TOPIC_IMG_STYLE}">
diff --git a/phpBB/styles/subsilver2/template/mcp_topic.html b/phpBB/styles/subsilver2/template/mcp_topic.html
index c6a8236b20..eee7fa95ea 100644
--- a/phpBB/styles/subsilver2/template/mcp_topic.html
+++ b/phpBB/styles/subsilver2/template/mcp_topic.html
@@ -44,7 +44,7 @@
</tr>
<tr>
<td class="row1" nowrap="nowrap"><span class="gen">{L_MERGE_TOPIC_ID}</span></td>
- <td class="row2" colspan="2"><input class="post" type="number" min="0" max="999999" name="to_topic_id" value="{TO_TOPIC_ID}" /> <a href="{U_SELECT_TOPIC}">{L_SELECT_TOPIC}</a></td>
+ <td class="row2" colspan="2"><input class="post" type="number" min="0" max="9999999999" name="to_topic_id" value="{TO_TOPIC_ID}" /> <a href="{U_SELECT_TOPIC}">{L_SELECT_TOPIC}</a></td>
</tr>
<!-- IF TO_TOPIC_INFO -->
<tr>
@@ -74,12 +74,14 @@
<td align="center"><b class="postauthor">{postrow.POST_AUTHOR_FULL}</b></td>
<td width="100%">
+ <!-- EVENT mcp_topic_postrow_post_details_before -->
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr style="vertical-align: top;">
<td class="gensmall" nowrap="nowrap">&nbsp;<b>{L_POST_SUBJECT}{L_COLON}</b>&nbsp;</td>
<td class="gensmall" width="100%">{postrow.POST_SUBJECT}</td>
</tr>
</table>
+ <!-- EVENT mcp_topic_postrow_post_details_after -->
</td>
<td width="5%" align="center"><a href="{postrow.U_POST_DETAILS}" class="imageset">{INFO_IMG}</a></td>
</tr>
diff --git a/phpBB/styles/subsilver2/template/memberlist_email.html b/phpBB/styles/subsilver2/template/memberlist_email.html
index 78ab3e4b8d..04f36b2244 100644
--- a/phpBB/styles/subsilver2/template/memberlist_email.html
+++ b/phpBB/styles/subsilver2/template/memberlist_email.html
@@ -1,5 +1,7 @@
<!-- INCLUDE overall_header.html -->
+<!-- EVENT memberlist_email_before -->
+
<div id="pagecontent">
<form action="{S_POST_ACTION}" method="post" name="postform">
diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html
index b984c9f96f..95f817e838 100644
--- a/phpBB/styles/subsilver2/template/posting_body.html
+++ b/phpBB/styles/subsilver2/template/posting_body.html
@@ -166,7 +166,11 @@
<!-- EVENT posting_editor_subject_before -->
<tr>
<td class="row1" width="22%"><b class="genmed">{L_SUBJECT}{L_COLON}</b></td>
- <td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}" /></td>
+ <td class="row2" width="78%">
+ <!-- EVENT posting_editor_subject_prepend -->
+ <input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}" />
+ <!-- EVENT posting_editor_subject_append -->
+ </td>
</tr>
<!-- EVENT posting_editor_subject_after -->
<tr>
diff --git a/phpBB/styles/subsilver2/template/posting_topic_review.html b/phpBB/styles/subsilver2/template/posting_topic_review.html
index 20976861fc..46329e19fa 100644
--- a/phpBB/styles/subsilver2/template/posting_topic_review.html
+++ b/phpBB/styles/subsilver2/template/posting_topic_review.html
@@ -18,6 +18,7 @@
</tr>
<!-- BEGIN topic_review_row -->
+ <!-- EVENT posting_topic_review_row_post_details_before -->
<!-- IF topic_review_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<!-- IF topic_review_row.S_IGNORE_POST -->
@@ -41,6 +42,7 @@
</table>
</td>
</tr>
+ <!-- EVENT posting_topic_review_row_post_details_after -->
<!-- IF topic_review_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/viewforum_body.html b/phpBB/styles/subsilver2/template/viewforum_body.html
index 2b8268d2c3..c76c081ba7 100644
--- a/phpBB/styles/subsilver2/template/viewforum_body.html
+++ b/phpBB/styles/subsilver2/template/viewforum_body.html
@@ -32,9 +32,11 @@
<th>&nbsp;{L_LAST_POST}&nbsp;</th>
</tr>
+ <!-- EVENT viewforum_body_topic_row_before -->
+
<!-- BEGIN topicrow -->
- <!-- EVENT viewforum_body_topic_row_before -->
+ <!-- EVENT viewforum_body_topicrow_row_before -->
<tr>
<!-- EVENT viewforum_body_topic_row_prepend -->
<td class="row1" width="25" align="center">{topicrow.TOPIC_FOLDER_IMG}</td>
diff --git a/tests/dbal/fixtures/migrator_module.xml b/tests/dbal/fixtures/migrator_module.xml
index 32afe7e6f3..e172d7a145 100644
--- a/tests/dbal/fixtures/migrator_module.xml
+++ b/tests/dbal/fixtures/migrator_module.xml
@@ -20,7 +20,7 @@
<value>acp</value>
<value>0</value>
<value>1</value>
- <value>4</value>
+ <value>6</value>
<value>ACP_CAT</value>
<value></value>
<value></value>
@@ -38,5 +38,57 @@
<value>test</value>
<value></value>
</row>
+ <row>
+ <value>3</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>acp</value>
+ <value>1</value>
+ <value>4</value>
+ <value>5</value>
+ <value>ACP_FORUM_BASED_PERMISSIONS</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>acp</value>
+ <value>0</value>
+ <value>7</value>
+ <value>12</value>
+ <value>ACP_CAT_FORUMS</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>acp</value>
+ <value>4</value>
+ <value>8</value>
+ <value>11</value>
+ <value>ACP_FORUM_BASED_PERMISSIONS</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>acp</value>
+ <value>5</value>
+ <value>9</value>
+ <value>10</value>
+ <value>ACP_FORUM_BASED_PERMISSIONS_CHILD_1</value>
+ <value></value>
+ <value></value>
+ </row>
</table>
</dataset>
diff --git a/tests/dbal/migration/if.php b/tests/dbal/migration/if.php
index 98a66526ed..481250ea77 100644
--- a/tests/dbal/migration/if.php
+++ b/tests/dbal/migration/if.php
@@ -36,13 +36,13 @@ class phpbb_dbal_migration_if extends \phpbb\db\migration\migration
{
global $migrator_test_if_true_failed;
- $migrator_test_if_true_failed = false;
+ $migrator_test_if_true_failed = !$migrator_test_if_true_failed;
}
function test_false()
{
global $migrator_test_if_false_failed;
- $migrator_test_if_false_failed = true;
+ $migrator_test_if_false_failed = !$migrator_test_if_false_failed;
}
}
diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php
index 4c4306888c..798200eef1 100644
--- a/tests/dbal/migrator_test.php
+++ b/tests/dbal/migrator_test.php
@@ -156,6 +156,14 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
$this->assertFalse($migrator_test_if_true_failed, 'True test failed');
$this->assertFalse($migrator_test_if_false_failed, 'False test failed');
+
+ while ($this->migrator->migration_state('phpbb_dbal_migration_if') !== false)
+ {
+ $this->migrator->revert('phpbb_dbal_migration_if');
+ }
+
+ $this->assertFalse($migrator_test_if_true_failed, 'True test after revert failed');
+ $this->assertFalse($migrator_test_if_false_failed, 'False test after revert failed');
}
public function test_recall()
diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php
index 08c3e979b8..49dff8b929 100644
--- a/tests/dbal/migrator_tool_module_test.php
+++ b/tests/dbal/migrator_tool_module_test.php
@@ -118,6 +118,44 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case
$this->fail($e);
}
$this->assertEquals(true, $this->tool->exists('acp', 'ACP_NEW_CAT', 'ACP_NEW_MODULE'));
+
+ // Test adding module when plural parent module_langname exists
+ // PHPBB3-14703
+ // Adding fail
+ try
+ {
+ $this->tool->add('acp', 'ACP_FORUM_BASED_PERMISSIONS', array(
+ 'module_basename' => 'acp_new_permissions_module',
+ 'module_langname' => 'ACP_NEW_PERMISSIONS_MODULE',
+ 'module_mode' => 'test',
+ 'module_auth' => '',
+ ));
+ $this->fail('Exception not thrown');
+ }
+ catch (Exception $e)
+ {
+ $this->assertEquals('phpbb\db\migration\exception', get_class($e));
+ $this->assertEquals('MODULE_EXIST_MULTIPLE', $e->getMessage());
+ }
+
+ // Test adding module when plural parent module_langname exists
+ // PHPBB3-14703
+ // Adding success
+ try
+ {
+ $this->tool->add('acp', 'ACP_FORUM_BASED_PERMISSIONS', array(
+ 'module_basename' => 'acp_new_permissions_module',
+ 'module_langname' => 'ACP_NEW_PERMISSIONS_MODULE',
+ 'module_mode' => 'test',
+ 'module_auth' => '',
+ 'after' => 'ACP_FORUM_BASED_PERMISSIONS_CHILD_1',
+ ));
+ }
+ catch (Exception $e)
+ {
+ $this->fail($e);
+ }
+ $this->assertEquals(true, $this->tool->exists('acp', 'ACP_FORUM_BASED_PERMISSIONS', 'ACP_NEW_PERMISSIONS_MODULE'));
}
public function test_remove()
diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php
index 1d37d748df..d41e3ec925 100644
--- a/tests/functional/search/base.php
+++ b/tests/functional/search/base.php
@@ -75,6 +75,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
protected function create_search_index()
{
$this->add_lang('acp/search');
+ $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
+ $form_values = $crawler->selectButton('Delete index')->form()->getValues();
$crawler = self::request(
'POST',
'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid,
@@ -82,6 +84,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
'search_type' => $this->search_backend,
'action' => 'create',
'submit' => true,
+ 'form_token' => $form_values['form_token'],
+ 'creation_time' => $form_values['creation_time'],
)
);
$this->assertContainsLang('SEARCH_INDEX_CREATED', $crawler->text());
@@ -90,6 +94,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
protected function delete_search_index()
{
$this->add_lang('acp/search');
+ $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
+ $form_values = $crawler->selectButton('Delete index')->form()->getValues();
$crawler = self::request(
'POST',
'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid,
@@ -97,6 +103,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
'search_type' => $this->search_backend,
'action' => 'delete',
'submit' => true,
+ 'form_token' => $form_values['form_token'],
+ 'creation_time' => $form_values['creation_time'],
)
);
$this->assertContainsLang('SEARCH_INDEX_REMOVED', $crawler->text());
diff --git a/tests/migrator/reverse_update_data_test.php b/tests/migrator/reverse_update_data_test.php
new file mode 100644
index 0000000000..b85e48c64c
--- /dev/null
+++ b/tests/migrator/reverse_update_data_test.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+class reverse_update_data_test extends phpbb_test_case
+{
+ /** @var \phpbb\db\migration\helper */
+ protected $helper;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->helper = new \phpbb\db\migration\helper();
+ }
+
+ public function update_data_provider()
+ {
+ return array(
+ array(
+ array(
+ array('config.add', array('foobar', 1)),
+ array('if', array(
+ (false === true),
+ array('permission.add', array('some_data')),
+ )),
+ array('config.remove', array('foobar')),
+ array('custom', array(array($this, 'foo_bar'))),
+ array('tool.method', array('test_data')),
+ ),
+ array(
+ array('tool.reverse', array('method', 'test_data')),
+ array('config.reverse', array('remove', 'foobar')),
+ array('config.reverse', array('add', 'foobar', 1)),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider update_data_provider
+ */
+ public function test_get_schema_steps($data_changes, $expected)
+ {
+ $this->assertEquals($expected, $this->helper->reverse_update_data($data_changes));
+ }
+}