aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb')
-rw-r--r--phpBB/phpbb/auth/provider/ldap.php2
-rw-r--r--phpBB/phpbb/cache/driver/eaccelerator.php4
-rw-r--r--phpBB/phpbb/cache/driver/file.php4
-rw-r--r--phpBB/phpbb/cache/driver/memory.php5
-rw-r--r--phpBB/phpbb/cache/driver/null.php4
-rw-r--r--phpBB/phpbb/captcha/plugins/captcha_abstract.php14
-rw-r--r--phpBB/phpbb/captcha/plugins/gd.php16
-rw-r--r--phpBB/phpbb/captcha/plugins/qa.php54
-rw-r--r--phpBB/phpbb/captcha/plugins/recaptcha.php18
-rw-r--r--phpBB/phpbb/composer.json2
-rw-r--r--phpBB/phpbb/config/db_text.php2
-rw-r--r--phpBB/phpbb/content_visibility.php10
-rw-r--r--phpBB/phpbb/controller/helper.php25
-rw-r--r--phpBB/phpbb/cron/task/core/prune_forum.php2
-rw-r--r--phpBB/phpbb/cron/task/core/prune_shadow_topics.php2
-rw-r--r--phpBB/phpbb/cron/task/core/tidy_plupload.php8
-rw-r--r--phpBB/phpbb/db/driver/mysqli.php3
-rw-r--r--phpBB/phpbb/db/migration/container_aware_migration.php36
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_13.php37
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_13_pl1.php37
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php37
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php11
-rw-r--r--phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php20
-rw-r--r--phpBB/phpbb/db/migration/data/v310/style_update_p1.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php70
-rw-r--r--phpBB/phpbb/db/migration/data/v31x/v313.php31
-rw-r--r--phpBB/phpbb/db/migration/data/v31x/v313rc1.php35
-rw-r--r--phpBB/phpbb/db/migration/data/v31x/v313rc2.php32
-rw-r--r--phpBB/phpbb/db/migration/profilefield_base_migration.php6
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php4
-rw-r--r--phpBB/phpbb/db/migration/tool/permission.php3
-rw-r--r--phpBB/phpbb/db/migrator.php52
-rw-r--r--phpBB/phpbb/db/tools/factory.php43
-rw-r--r--phpBB/phpbb/db/tools/mssql.php793
-rw-r--r--phpBB/phpbb/db/tools/postgres.php613
-rw-r--r--phpBB/phpbb/db/tools/tools.php864
-rw-r--r--phpBB/phpbb/event/dispatcher.php35
-rw-r--r--phpBB/phpbb/event/dispatcher_interface.php10
-rw-r--r--phpBB/phpbb/event/kernel_exception_subscriber.php59
-rw-r--r--phpBB/phpbb/event/kernel_terminate_subscriber.php2
-rw-r--r--phpBB/phpbb/exception/exception_interface.php29
-rw-r--r--phpBB/phpbb/exception/http_exception.php70
-rw-r--r--phpBB/phpbb/exception/runtime_exception.php52
-rw-r--r--phpBB/phpbb/feed/base.php11
-rw-r--r--phpBB/phpbb/file_downloader.php8
-rw-r--r--phpBB/phpbb/log/log.php8
-rw-r--r--phpBB/phpbb/log/log_interface.php16
-rw-r--r--phpBB/phpbb/notification/manager.php6
-rw-r--r--phpBB/phpbb/notification/type/post.php1
-rw-r--r--phpBB/phpbb/notification/type/topic.php1
-rw-r--r--phpBB/phpbb/path_helper.php34
-rw-r--r--phpBB/phpbb/profilefields/type/type_bool.php40
-rw-r--r--phpBB/phpbb/profilefields/type/type_date.php2
-rw-r--r--phpBB/phpbb/request/deactivated_super_global.php2
-rw-r--r--phpBB/phpbb/routing/router.php45
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php6
-rw-r--r--phpBB/phpbb/search/fulltext_native.php10
-rw-r--r--phpBB/phpbb/search/fulltext_postgres.php2
-rw-r--r--phpBB/phpbb/search/fulltext_sphinx.php13
-rw-r--r--phpBB/phpbb/session.php31
-rw-r--r--phpBB/phpbb/template/asset.php7
-rw-r--r--phpBB/phpbb/template/twig/extension.php3
-rw-r--r--phpBB/phpbb/template/twig/lexer.php6
-rw-r--r--phpBB/phpbb/template/twig/twig.php8
-rw-r--r--phpBB/phpbb/version_helper.php5
65 files changed, 2385 insertions, 1040 deletions
diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php
index d32e7504eb..c71950c698 100644
--- a/phpBB/phpbb/auth/provider/ldap.php
+++ b/phpBB/phpbb/auth/provider/ldap.php
@@ -306,7 +306,7 @@ class ldap extends \phpbb\auth\provider\base
return array(
'TEMPLATE_FILE' => 'auth_provider_ldap.html',
'TEMPLATE_VARS' => array(
- 'AUTH_LDAP_DN' => $new_config['ldap_base_dn'],
+ 'AUTH_LDAP_BASE_DN' => $new_config['ldap_base_dn'],
'AUTH_LDAP_EMAIL' => $new_config['ldap_email'],
'AUTH_LDAP_PASSORD' => $new_config['ldap_password'],
'AUTH_LDAP_PORT' => $new_config['ldap_port'],
diff --git a/phpBB/phpbb/cache/driver/eaccelerator.php b/phpBB/phpbb/cache/driver/eaccelerator.php
index 1697758acc..740855144f 100644
--- a/phpBB/phpbb/cache/driver/eaccelerator.php
+++ b/phpBB/phpbb/cache/driver/eaccelerator.php
@@ -44,9 +44,11 @@ class eaccelerator extends \phpbb\cache\driver\memory
*/
function tidy()
{
+ global $config;
+
eaccelerator_gc();
- set_config('cache_last_gc', time(), true);
+ $config->set('cache_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php
index 114959c06c..9c63d0010c 100644
--- a/phpBB/phpbb/cache/driver/file.php
+++ b/phpBB/phpbb/cache/driver/file.php
@@ -95,7 +95,7 @@ class file extends \phpbb\cache\driver\base
*/
function tidy()
{
- global $phpEx;
+ global $config, $phpEx;
$dir = @opendir($this->cache_dir);
@@ -149,7 +149,7 @@ class file extends \phpbb\cache\driver\base
}
}
- set_config('cache_last_gc', time(), true);
+ $config->set('cache_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php
index 0cef9c3483..baae22d809 100644
--- a/phpBB/phpbb/cache/driver/memory.php
+++ b/phpBB/phpbb/cache/driver/memory.php
@@ -81,9 +81,10 @@ abstract class memory extends \phpbb\cache\driver\base
*/
function tidy()
{
- // cache has auto GC, no need to have any code here :)
+ global $config;
- set_config('cache_last_gc', time(), true);
+ // cache has auto GC, no need to have any code here :)
+ $config->set('cache_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/cache/driver/null.php b/phpBB/phpbb/cache/driver/null.php
index a45cf97862..298731ea54 100644
--- a/phpBB/phpbb/cache/driver/null.php
+++ b/phpBB/phpbb/cache/driver/null.php
@@ -52,8 +52,10 @@ class null extends \phpbb\cache\driver\base
*/
function tidy()
{
+ global $config;
+
// This cache always has a tidy room.
- set_config('cache_last_gc', time(), true);
+ $config->set('cache_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php
index 24ed7f939d..2c0b95411e 100644
--- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php
+++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php
@@ -34,12 +34,12 @@ abstract class captcha_abstract
function init($type)
{
- global $config, $db, $user;
+ global $config, $db, $user, $request;
// read input
- $this->confirm_id = request_var('confirm_id', '');
- $this->confirm_code = request_var('confirm_code', '');
- $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
+ $this->confirm_id = $request->variable('confirm_id', '');
+ $this->confirm_code = $request->variable('confirm_code', '');
+ $refresh = $request->variable('refresh_vc', false) && $config['confirm_refresh'];
$this->type = (int) $type;
@@ -125,7 +125,7 @@ abstract class captcha_abstract
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $variables .= '&' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
+ $variables .= '&' . rawurlencode($captcha_var) . '=' . $request->variable($captcha_var, (int) $config[$captcha_var]);
}
}
@@ -350,7 +350,9 @@ abstract class captcha_abstract
function is_solved()
{
- if (request_var('confirm_code', false) && $this->solved === 0)
+ global $request;
+
+ if ($request->variable('confirm_code', false) && $this->solved === 0)
{
$this->validate();
}
diff --git a/phpBB/phpbb/captcha/plugins/gd.php b/phpBB/phpbb/captcha/plugins/gd.php
index f6200b5b2f..1727dcc1bb 100644
--- a/phpBB/phpbb/captcha/plugins/gd.php
+++ b/phpBB/phpbb/captcha/plugins/gd.php
@@ -53,7 +53,7 @@ class gd extends captcha_abstract
function acp_page($id, &$module)
{
- global $db, $user, $auth, $template;
+ global $db, $user, $auth, $template, $phpbb_log, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
@@ -70,21 +70,21 @@ class gd extends captcha_abstract
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', '');
+ $submit = $request->variable('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($this->captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
- $value = request_var($captcha_var, 0);
+ $value = $request->variable($captcha_var, 0);
if ($value >= 0)
{
- set_config($captcha_var, $value);
+ $config->set($captcha_var, $value);
}
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
@@ -95,7 +95,7 @@ class gd extends captcha_abstract
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
+ $var = (isset($_REQUEST[$captcha_var])) ? $request->variable($captcha_var, 0) : $config[$captcha_var];
$template->assign_var($template_var, $var);
}
@@ -109,7 +109,7 @@ class gd extends captcha_abstract
function execute_demo()
{
- global $config;
+ global $config, $request;
$config_old = $config;
@@ -121,7 +121,7 @@ class gd extends captcha_abstract
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $config->set($captcha_var, request_var($captcha_var, (int) $config[$captcha_var]));
+ $config->set($captcha_var, $request->variable($captcha_var, (int) $config[$captcha_var]));
}
parent::execute_demo();
$config = $config_old;
diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php
index ca242a96dc..cf03f92e96 100644
--- a/phpBB/phpbb/captcha/plugins/qa.php
+++ b/phpBB/phpbb/captcha/plugins/qa.php
@@ -58,14 +58,14 @@ class qa
*/
function init($type)
{
- global $config, $db, $user;
+ global $config, $db, $user, $request;
// load our language file
$user->add_lang('captcha_qa');
// read input
- $this->confirm_id = request_var('qa_confirm_id', '');
- $this->answer = utf8_normalize_nfc(request_var('qa_answer', '', true));
+ $this->confirm_id = $request->variable('qa_confirm_id', '');
+ $this->answer = $request->variable('qa_answer', '', true);
$this->type = (int) $type;
$this->question_lang = $user->lang_name;
@@ -113,9 +113,9 @@ class qa
*/
public function is_installed()
{
- global $db;
+ global $phpbb_container;
- $db_tool = new \phpbb\db\tools\tools($db);
+ $db_tool = $phpbb_container->get('dbal.tools');
return $db_tool->sql_table_exists($this->table_captcha_questions);
}
@@ -306,11 +306,9 @@ class qa
*/
function install()
{
- global $db;
-
- $db_tool = new \phpbb\db\tools\tools($db);
+ global $phpbb_container;
- $tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm);
+ $db_tool = $phpbb_container->get('dbal.tools');
$schemas = array(
$this->table_captcha_questions => array (
@@ -352,7 +350,7 @@ class qa
),
);
- foreach($schemas as $table => $schema)
+ foreach ($schemas as $table => $schema)
{
if (!$db_tool->sql_table_exists($table))
{
@@ -544,9 +542,9 @@ class qa
*/
function check_answer()
{
- global $db;
+ global $db, $request;
- $answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true)));
+ $answer = ($this->question_strict) ? $request->variable('qa_answer', '', true) : utf8_clean_string($request->variable('qa_answer', '', true));
$sql = 'SELECT answer_text
FROM ' . $this->table_captcha_answers . '
@@ -598,7 +596,9 @@ class qa
*/
function is_solved()
{
- if (request_var('qa_answer', false) && $this->solved === 0)
+ global $request;
+
+ if ($request->variable('qa_answer', false) && $this->solved === 0)
{
$this->validate();
}
@@ -611,7 +611,7 @@ class qa
*/
function acp_page($id, &$module)
{
- global $db, $user, $auth, $template;
+ global $db, $user, $auth, $template, $phpbb_log, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
@@ -627,9 +627,9 @@ class qa
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', false);
- $question_id = request_var('question_id', 0);
- $action = request_var('action', '');
+ $submit = $request->variable('submit', false);
+ $question_id = $request->variable('question_id', 0);
+ $action = $request->variable('action', '');
// we have two pages, so users might want to navigate from one to the other
$list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_service_name();
@@ -675,10 +675,10 @@ class qa
{
// okay, show the editor
$error = false;
- $input_question = request_var('question_text', '', true);
- $input_answers = request_var('answers', '', true);
- $input_lang = request_var('lang_iso', '', true);
- $input_strict = request_var('strict', false);
+ $input_question = $request->variable('question_text', '', true);
+ $input_answers = $request->variable('answers', '', true);
+ $input_lang = $request->variable('lang_iso', '', true);
+ $input_strict = $request->variable('strict', false);
$langs = $this->get_languages();
foreach ($langs as $lang => $entry)
@@ -742,7 +742,7 @@ class qa
$this->acp_add_question($data);
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
}
}
@@ -826,11 +826,13 @@ class qa
*/
function acp_get_question_input()
{
- $answers = utf8_normalize_nfc(request_var('answers', '', true));
+ global $request;
+
+ $answers = $request->variable('answers', '', true);
$question = array(
- 'question_text' => request_var('question_text', '', true),
- 'strict' => request_var('strict', false),
- 'lang_iso' => request_var('lang_iso', ''),
+ 'question_text' => $request->variable('question_text', '', true),
+ 'strict' => $request->variable('strict', false),
+ 'lang_iso' => $request->variable('lang_iso', ''),
'answers' => (strlen($answers)) ? explode("\n", $answers) : '',
);
diff --git a/phpBB/phpbb/captcha/plugins/recaptcha.php b/phpBB/phpbb/captcha/plugins/recaptcha.php
index 584f3afec1..98132ab47d 100644
--- a/phpBB/phpbb/captcha/plugins/recaptcha.php
+++ b/phpBB/phpbb/captcha/plugins/recaptcha.php
@@ -37,12 +37,12 @@ class recaptcha extends captcha_abstract
function init($type)
{
- global $config, $db, $user;
+ global $config, $db, $user, $request;
$user->add_lang('captcha_recaptcha');
parent::init($type);
- $this->challenge = request_var('recaptcha_challenge_field', '');
- $this->response = request_var('recaptcha_response_field', '');
+ $this->challenge = $request->variable('recaptcha_challenge_field', '');
+ $this->response = $request->variable('recaptcha_response_field', '');
}
public function is_available()
@@ -75,7 +75,7 @@ class recaptcha extends captcha_abstract
function acp_page($id, &$module)
{
- global $config, $db, $template, $user;
+ global $config, $db, $template, $user, $phpbb_log, $request;
$captcha_vars = array(
'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
@@ -87,21 +87,21 @@ class recaptcha extends captcha_abstract
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', '');
+ $submit = $request->variable('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
- $value = request_var($captcha_var, '');
+ $value = $request->variable($captcha_var, '');
if ($value)
{
- set_config($captcha_var, $value);
+ $config->set($captcha_var, $value);
}
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
@@ -112,7 +112,7 @@ class recaptcha extends captcha_abstract
{
foreach ($captcha_vars as $captcha_var => $template_var)
{
- $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
+ $var = (isset($_REQUEST[$captcha_var])) ? $request->variable($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
$template->assign_var($template_var, $var);
}
diff --git a/phpBB/phpbb/composer.json b/phpBB/phpbb/composer.json
index 513d7e4559..175be4b0ab 100644
--- a/phpBB/phpbb/composer.json
+++ b/phpBB/phpbb/composer.json
@@ -22,6 +22,6 @@
"classmap": [""]
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
}
}
diff --git a/phpBB/phpbb/config/db_text.php b/phpBB/phpbb/config/db_text.php
index b1e3ef5da4..ddc7c9aef0 100644
--- a/phpBB/phpbb/config/db_text.php
+++ b/phpBB/phpbb/config/db_text.php
@@ -154,6 +154,6 @@ class db_text
$sql = 'DELETE
FROM ' . $this->table . '
WHERE ' . $this->db->sql_in_set('config_name', $keys, false, true);
- $result = $this->db->sql_query($sql);
+ $this->db->sql_query($sql);
}
}
diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php
index c8516d6c85..02338a5c2f 100644
--- a/phpBB/phpbb/content_visibility.php
+++ b/phpBB/phpbb/content_visibility.php
@@ -45,7 +45,7 @@ class content_visibility
/**
* Event dispatcher object
- * @var \phpbb\event\dispatcher
+ * @var \phpbb\event\dispatcher_interface
*/
protected $phpbb_dispatcher;
@@ -66,7 +66,7 @@ class content_visibility
*
* @param \phpbb\auth\auth $auth Auth object
* @param \phpbb\config\config $config Config object
- * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher object
+ * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
* @param \phpbb\db\driver\driver_interface $db Database object
* @param \phpbb\user $user User object
* @param string $phpbb_root_path Root path
@@ -76,7 +76,7 @@ class content_visibility
* @param string $topics_table Topics table name
* @param string $users_table Users table name
*/
- public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
+ public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
{
$this->auth = $auth;
$this->config = $config;
@@ -252,7 +252,7 @@ class content_visibility
* @event core.phpbb_content_visibility_get_global_visibility_before
* @var array where_sqls The action the user tried to execute
* @var string mode Either "topic" or "post" depending on the query this is being used in
- * @var array forum_ids Array of forum ids which the posts/topics are limited to
+ * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to
* @var string table_alias Table alias to prefix in SQL queries
* @var array approve_forums Array of forums where the user has m_approve permissions
* @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR")
@@ -261,7 +261,7 @@ class content_visibility
$vars = array(
'where_sqls',
'mode',
- 'forum_ids',
+ 'exclude_forum_ids',
'table_alias',
'approve_forums',
'visibility_sql_overwrite',
diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php
index 2bc8e6b9d0..2790ea4277 100644
--- a/phpBB/phpbb/controller/helper.php
+++ b/phpBB/phpbb/controller/helper.php
@@ -187,15 +187,34 @@ class helper
* @param string $message The error message
* @param int $code The error code (e.g. 404, 500, 503, etc.)
* @return Response A Response instance
+ *
+ * @deprecated 3.1.3 (To be removed: 3.3.0) Use exceptions instead.
*/
public function error($message, $code = 500)
{
+ return $this->message($message, array(), 'INFORMATION', $code);
+ }
+
+ /**
+ * Output a message
+ *
+ * In case of an error, please throw an exception instead
+ *
+ * @param string $message The message to display (must be a language variable)
+ * @param array $parameters The parameters to use with the language var
+ * @param string $title Title for the message (must be a language variable)
+ * @param int $code The HTTP status code (e.g. 404, 500, 503, etc.)
+ * @return Response A Response instance
+ */
+ public function message($message, array $parameters = array(), $title = 'INFORMATION', $code = 200)
+ {
+ array_unshift($parameters, $message);
$this->template->assign_vars(array(
- 'MESSAGE_TEXT' => $message,
- 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
+ 'MESSAGE_TEXT' => call_user_func_array(array($this->user, 'lang'), $parameters),
+ 'MESSAGE_TITLE' => $this->user->lang($title),
));
- return $this->render('message_body.html', $this->user->lang('INFORMATION'), $code);
+ return $this->render('message_body.html', $this->user->lang($title), $code);
}
/**
diff --git a/phpBB/phpbb/cron/task/core/prune_forum.php b/phpBB/phpbb/cron/task/core/prune_forum.php
index ba68565197..abf91aee19 100644
--- a/phpBB/phpbb/cron/task/core/prune_forum.php
+++ b/phpBB/phpbb/cron/task/core/prune_forum.php
@@ -31,7 +31,7 @@ class prune_forum extends \phpbb\cron\task\base implements \phpbb\cron\task\para
* If $forum_data is given, it is assumed to contain necessary information
* about a single forum that is to be pruned.
*
- * If $forum_data is not given, forum id will be retrieved via request_var
+ * If $forum_data is not given, forum id will be retrieved via $request->variable()
* and a database query will be performed to load the necessary information
* about the forum.
*/
diff --git a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
index 97a4b0ea86..0ab59f9ed5 100644
--- a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
+++ b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
@@ -33,7 +33,7 @@ class prune_shadow_topics extends \phpbb\cron\task\base implements \phpbb\cron\t
* If $forum_data is given, it is assumed to contain necessary information
* about a single forum that is to be pruned.
*
- * If $forum_data is not given, forum id will be retrieved via request_var
+ * If $forum_data is not given, forum id will be retrieved via $request->variable()
* and a database query will be performed to load the necessary information
* about the forum.
*/
diff --git a/phpBB/phpbb/cron/task/core/tidy_plupload.php b/phpBB/phpbb/cron/task/core/tidy_plupload.php
index b6aeecf4b4..d7364374af 100644
--- a/phpBB/phpbb/cron/task/core/tidy_plupload.php
+++ b/phpBB/phpbb/cron/task/core/tidy_plupload.php
@@ -67,6 +67,8 @@ class tidy_plupload extends \phpbb\cron\task\base
*/
public function run()
{
+ global $user, $phpbb_log;
+
// Remove old temporary file (perhaps failed uploads?)
$last_valid_timestamp = time() - $this->max_file_age;
try
@@ -88,13 +90,11 @@ class tidy_plupload extends \phpbb\cron\task\base
}
catch (\UnexpectedValueException $e)
{
- add_log(
- 'critical',
- 'LOG_PLUPLOAD_TIDY_FAILED',
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_PLUPLOAD_TIDY_FAILED', false, array(
$this->plupload_upload_path,
$e->getMessage(),
$e->getTraceAsString()
- );
+ ));
}
$this->config->set('plupload_last_gc', time(), true);
diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php
index debc3cc523..d43e201526 100644
--- a/phpBB/phpbb/db/driver/mysqli.php
+++ b/phpBB/phpbb/db/driver/mysqli.php
@@ -34,8 +34,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
return $this->sql_error('');
}
- // Mysqli extension supports persistent connection since PHP 5.3.0
- $this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false;
+ $this->persistency = $persistency;
$this->user = $sqluser;
// If persistent connection, set dbhost to localhost when empty and prepend it with 'p:' prefix
diff --git a/phpBB/phpbb/db/migration/container_aware_migration.php b/phpBB/phpbb/db/migration/container_aware_migration.php
new file mode 100644
index 0000000000..3b4b49b04b
--- /dev/null
+++ b/phpBB/phpbb/db/migration/container_aware_migration.php
@@ -0,0 +1,36 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration;
+
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+* Abstract base class for container aware database migrations.
+*/
+abstract class container_aware_migration extends migration implements ContainerAwareInterface
+{
+ /**
+ * @var ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setContainer(ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_13.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13.php
new file mode 100644
index 0000000000..310fcc70fc
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v30x;
+
+class release_3_0_13 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return phpbb_version_compare($this->config['version'], '3.0.13', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v30x\release_3_0_13_rc1');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('if', array(
+ phpbb_version_compare($this->config['version'], '3.0.13', '<'),
+ array('config.update', array('version', '3.0.13')),
+ )),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_pl1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_pl1.php
new file mode 100644
index 0000000000..b12a96a7fb
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_pl1.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v30x;
+
+class release_3_0_13_pl1 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return phpbb_version_compare($this->config['version'], '3.0.13-PL1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v30x\release_3_0_13');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('if', array(
+ phpbb_version_compare($this->config['version'], '3.0.13-PL1', '<'),
+ array('config.update', array('version', '3.0.13-PL1')),
+ )),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php
new file mode 100644
index 0000000000..9ea68fa862
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v30x;
+
+class release_3_0_13_rc1 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return phpbb_version_compare($this->config['version'], '3.0.13-RC1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v30x\release_3_0_12');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('if', array(
+ phpbb_version_compare($this->config['version'], '3.0.13-RC1', '<'),
+ array('config.update', array('version', '3.0.13-RC1')),
+ )),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
index 20543463ab..9f6e3efb91 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
@@ -13,7 +13,9 @@
namespace phpbb\db\migration\data\v30x;
-class release_3_0_5_rc1 extends \phpbb\db\migration\migration
+use phpbb\db\migration\container_aware_migration;
+
+class release_3_0_5_rc1 extends container_aware_migration
{
public function effectively_installed()
{
@@ -55,10 +57,9 @@ class release_3_0_5_rc1 extends \phpbb\db\migration\migration
public function hash_old_passwords()
{
- global $phpbb_container;
-
/* @var $passwords_manager \phpbb\passwords\manager */
- $passwords_manager = $phpbb_container->get('passwords.manager');
+ $passwords_manager = $this->container->get('passwords.manager');
+
$sql = 'SELECT user_id, user_password
FROM ' . $this->table_prefix . 'users
WHERE user_pass_convert = 1';
@@ -111,7 +112,7 @@ class release_3_0_5_rc1 extends \phpbb\db\migration\migration
// Select auth_option_ids... the largest id will be preserved
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
- WHERE auth_option = '" . $db->sql_escape($option) . "'
+ WHERE auth_option = '" . $this->db->sql_escape($option) . "'
ORDER BY auth_option_id DESC";
// sql_query_limit not possible here, due to bug in postgresql layer
$result = $this->db->sql_query($sql);
diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php
index 58845b88ec..85b90da5fa 100644
--- a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php
+++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php
@@ -13,12 +13,14 @@
namespace phpbb\db\migration\data\v310;
+use phpbb\db\migration\container_aware_migration;
+
/**
* Migration to convert the Soft Delete MOD for 3.0
*
* https://www.phpbb.com/customise/db/mod/soft_delete/
*/
-class soft_delete_mod_convert extends \phpbb\db\migration\migration
+class soft_delete_mod_convert extends container_aware_migration
{
static public function depends_on()
{
@@ -115,19 +117,11 @@ class soft_delete_mod_convert extends \phpbb\db\migration\migration
}
}
+ /**
+ * @return \phpbb\content_visibility
+ */
protected function get_content_visibility()
{
- return new \phpbb\content_visibility(
- new \phpbb\auth\auth(),
- $this->config,
- $this->db,
- new \phpbb\user('\phpbb\datetime'),
- $this->phpbb_root_path,
- $this->php_ext,
- $this->table_prefix . 'forums',
- $this->table_prefix . 'posts',
- $this->table_prefix . 'topics',
- $this->table_prefix . 'users'
- );
+ return $this->container->get('content.visibility');
}
}
diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
index e8d3a3af64..918a565e06 100644
--- a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
+++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
@@ -62,6 +62,8 @@ class style_update_p1 extends \phpbb\db\migration\migration
public function styles_update()
{
+ global $config;
+
// Get list of valid 3.1 styles
$available_styles = array('prosilver');
@@ -163,7 +165,7 @@ class style_update_p1 extends \phpbb\db\migration\migration
$default_style = $this->db->sql_fetchfield($result);
$this->db->sql_freeresult($result);
- set_config('default_style', $default_style);
+ $config->set('default_style', $default_style);
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = 0';
$this->sql_query($sql);
diff --git a/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php
new file mode 100644
index 0000000000..854ed1f568
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php
@@ -0,0 +1,70 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v31x;
+
+class update_custom_bbcodes_with_idn extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v312',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'update_bbcodes_table'))),
+ );
+ }
+
+ public function update_bbcodes_table()
+ {
+ if (!class_exists('acp_bbcodes'))
+ {
+ include($this->phpbb_root_path . 'includes/acp/acp_bbcodes.' . $this->php_ext);
+ }
+
+ $bbcodes = new \acp_bbcodes();
+
+ $sql = 'SELECT bbcode_id, bbcode_match, bbcode_tpl
+ FROM ' . BBCODES_TABLE;
+ $result = $this->sql_query($sql);
+
+ $sql_ary = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $data = array();
+ if (preg_match('/(URL|LOCAL_URL|RELATIVE_URL)/', $row['bbcode_match']))
+ {
+ $data = $bbcodes->build_regexp($row['bbcode_match'], $row['bbcode_tpl']);
+ $sql_ary[$row['bbcode_id']] = array(
+ 'first_pass_match' => $data['first_pass_match'],
+ 'first_pass_replace' => $data['first_pass_replace'],
+ 'second_pass_match' => $data['second_pass_match'],
+ 'second_pass_replace' => $data['second_pass_replace']
+ );
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ foreach ($sql_ary as $bbcode_id => $bbcode_data)
+ {
+ $sql = 'UPDATE ' . BBCODES_TABLE . '
+ SET ' . $this->db->sql_build_array('UPDATE', $bbcode_data) . '
+ WHERE bbcode_id = ' . (int) $bbcode_id;
+ $this->sql_query($sql);
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v31x/v313.php b/phpBB/phpbb/db/migration/data/v31x/v313.php
new file mode 100644
index 0000000000..5a4e21a9b7
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v31x/v313.php
@@ -0,0 +1,31 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v31x;
+
+class v313 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v313rc2',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.3')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v31x/v313rc1.php b/phpBB/phpbb/db/migration/data/v31x/v313rc1.php
new file mode 100644
index 0000000000..e50754f805
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v31x/v313rc1.php
@@ -0,0 +1,35 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v31x;
+
+class v313rc1 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v30x\release_3_0_13_rc1',
+ '\phpbb\db\migration\data\v31x\plupload_last_gc_dynamic',
+ '\phpbb\db\migration\data\v31x\profilefield_remove_underscore_from_alpha',
+ '\phpbb\db\migration\data\v31x\profilefield_yahoo_update_url',
+ '\phpbb\db\migration\data\v31x\update_custom_bbcodes_with_idn',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.3-RC1')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v31x/v313rc2.php b/phpBB/phpbb/db/migration/data/v31x/v313rc2.php
new file mode 100644
index 0000000000..d832d6f502
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v31x/v313rc2.php
@@ -0,0 +1,32 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v31x;
+
+class v313rc2 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v30x\release_3_0_13_pl1',
+ '\phpbb\db\migration\data\v31x\v313rc1',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.3-RC2')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php
index bc3d2e9ee5..3f26a4998c 100644
--- a/phpBB/phpbb/db/migration/profilefield_base_migration.php
+++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php
@@ -13,7 +13,7 @@
namespace phpbb\db\migration;
-abstract class profilefield_base_migration extends \phpbb\db\migration\migration
+abstract class profilefield_base_migration extends container_aware_migration
{
protected $profilefield_name;
@@ -237,10 +237,8 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration
if ($profile_row === null)
{
- global $phpbb_container;
-
/* @var $manager \phpbb\profilefields\manager */
- $manager = $phpbb_container->get('profilefields.manager');
+ $manager = $this->container->get('profilefields.manager');
$profile_row = $manager->build_insert_sql_array(array());
}
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 035625b095..b6f0372181 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -171,6 +171,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
*/
public function add($class, $parent = 0, $data = array())
{
+ global $user, $phpbb_log;
+
// Allows '' to be sent as 0
$parent = $parent ?: 0;
@@ -266,7 +268,7 @@ class module implements \phpbb\db\migration\tool\tool_interface
{
// Success
$module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
- add_log('admin', 'LOG_MODULE_ADD', $module_log_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name));
// Move the module if requested above/below an existing one
if (isset($data['before']) && $data['before'])
diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php
index 5cfbc5ca00..1a91127d2d 100644
--- a/phpBB/phpbb/db/migration/tool/permission.php
+++ b/phpBB/phpbb/db/migration/tool/permission.php
@@ -537,7 +537,8 @@ class permission implements \phpbb\db\migration\tool\tool_interface
}
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
- WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove);
+ WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove) . '
+ AND role_id = ' . (int) $role_id;
$this->db->sql_query($sql);
break;
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index bb79c0dd68..6902913c64 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -13,11 +13,19 @@
namespace phpbb\db;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
/**
* The migrator is responsible for applying new migrations in the correct order.
*/
class migrator
{
+ /**
+ * @var ContainerInterface
+ */
+ protected $container;
+
/** @var \phpbb\config\config */
protected $config;
@@ -77,15 +85,16 @@ class migrator
/**
* The output handler. A null handler is configured by default.
*
- * @var migrator_output_handler
+ * @var migrator_output_handler_interface
*/
public $output_handler;
/**
* Constructor of the database migrator
*/
- public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
+ public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
{
+ $this->container = $container;
$this->config = $config;
$this->db = $db;
$this->db_tools = $db_tools;
@@ -172,6 +181,18 @@ class migrator
*/
public function update()
{
+ $this->container->get('dispatcher')->disable();
+ $this->update_do();
+ $this->container->get('dispatcher')->enable();
+ }
+
+ /**
+ * Effectively runs a single update step from the next migration to be applied.
+ *
+ * @return null
+ */
+ protected function update_do()
+ {
foreach ($this->migrations as $name)
{
if (!isset($this->migration_state[$name]) ||
@@ -317,7 +338,7 @@ class migrator
catch (\phpbb\db\migration\exception $e)
{
// Revert the schema changes
- $this->revert($name);
+ $this->revert_do($name);
// Rethrow exception
throw $e;
@@ -337,10 +358,22 @@ class migrator
* check if revert() needs to be called again use the migration_state() method.
*
* @param string $migration String migration name to revert (including any that depend on this migration)
- * @return null
*/
public function revert($migration)
{
+ $this->container->get('dispatcher')->disable();
+ $this->revert_do($migration);
+ $this->container->get('dispatcher')->enable();
+ }
+
+ /**
+ * Effectively runs a single revert step from the last migration installed
+ *
+ * @param string $migration String migration name to revert (including any that depend on this migration)
+ * @return null
+ */
+ protected function revert_do($migration)
+ {
if (!isset($this->migration_state[$migration]))
{
// Not installed
@@ -351,7 +384,7 @@ class migrator
{
if (!empty($state['migration_depends_on']) && in_array($migration, $state['migration_depends_on']))
{
- $this->revert($name);
+ $this->revert_do($name);
}
}
@@ -742,7 +775,14 @@ class migrator
*/
protected function get_migration($name)
{
- return new $name($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix);
+ $migration = new $name($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix);
+
+ if ($migration instanceof ContainerAwareInterface)
+ {
+ $migration->setContainer($this->container);
+ }
+
+ return $migration;
}
/**
diff --git a/phpBB/phpbb/db/tools/factory.php b/phpBB/phpbb/db/tools/factory.php
new file mode 100644
index 0000000000..d204451a63
--- /dev/null
+++ b/phpBB/phpbb/db/tools/factory.php
@@ -0,0 +1,43 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\tools;
+
+/**
+ * A factory which serves the suitable tools instance for the given dbal
+ */
+class factory
+{
+ /**
+ * @param mixed $db_driver
+ * @param bool $return_statements
+ * @return \phpbb\db\tools\tools_interface
+ */
+ public function get($db_driver, $return_statements = false)
+ {
+ if ($db_driver instanceof \phpbb\db\driver\mssql || $db_driver instanceof \phpbb\db\driver\mssql_base)
+ {
+ return new \phpbb\db\tools\mssql($db_driver, $return_statements);
+ }
+ else if ($db_driver instanceof \phpbb\db\driver\postgres)
+ {
+ return new \phpbb\db\tools\postgres($db_driver, $return_statements);
+ }
+ else if ($db_driver instanceof \phpbb\db\driver\driver_interface)
+ {
+ return new \phpbb\db\tools\tools($db_driver, $return_statements);
+ }
+
+ throw new \InvalidArgumentException('Invalid database driver given');
+ }
+}
diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php
new file mode 100644
index 0000000000..6e58171040
--- /dev/null
+++ b/phpBB/phpbb/db/tools/mssql.php
@@ -0,0 +1,793 @@
+<?php
+/**
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\db\tools;
+
+/**
+ * Database Tools for handling cross-db actions such as altering columns, etc.
+ * Currently not supported is returning SQL for creating tables.
+ */
+class mssql extends tools
+{
+ /**
+ * Is the used MS SQL Server a SQL Server 2000?
+ * @var bool
+ */
+ protected $is_sql_server_2000;
+
+ /**
+ * Get the column types for mssql based databases
+ *
+ * @return array
+ */
+ public static function get_dbms_type_map()
+ {
+ return array(
+ 'mssql' => array(
+ 'INT:' => '[int]',
+ 'BINT' => '[float]',
+ 'UINT' => '[int]',
+ 'UINT:' => '[int]',
+ 'TINT:' => '[int]',
+ 'USINT' => '[int]',
+ 'BOOL' => '[int]',
+ 'VCHAR' => '[varchar] (255)',
+ 'VCHAR:' => '[varchar] (%d)',
+ 'CHAR:' => '[char] (%d)',
+ 'XSTEXT' => '[varchar] (1000)',
+ 'STEXT' => '[varchar] (3000)',
+ 'TEXT' => '[varchar] (8000)',
+ 'MTEXT' => '[text]',
+ 'XSTEXT_UNI'=> '[varchar] (100)',
+ 'STEXT_UNI' => '[varchar] (255)',
+ 'TEXT_UNI' => '[varchar] (4000)',
+ 'MTEXT_UNI' => '[text]',
+ 'TIMESTAMP' => '[int]',
+ 'DECIMAL' => '[float]',
+ 'DECIMAL:' => '[float]',
+ 'PDECIMAL' => '[float]',
+ 'PDECIMAL:' => '[float]',
+ 'VCHAR_UNI' => '[varchar] (255)',
+ 'VCHAR_UNI:'=> '[varchar] (%d)',
+ 'VCHAR_CI' => '[varchar] (255)',
+ 'VARBINARY' => '[varchar] (255)',
+ ),
+
+ 'mssqlnative' => array(
+ 'INT:' => '[int]',
+ 'BINT' => '[float]',
+ 'UINT' => '[int]',
+ 'UINT:' => '[int]',
+ 'TINT:' => '[int]',
+ 'USINT' => '[int]',
+ 'BOOL' => '[int]',
+ 'VCHAR' => '[varchar] (255)',
+ 'VCHAR:' => '[varchar] (%d)',
+ 'CHAR:' => '[char] (%d)',
+ 'XSTEXT' => '[varchar] (1000)',
+ 'STEXT' => '[varchar] (3000)',
+ 'TEXT' => '[varchar] (8000)',
+ 'MTEXT' => '[text]',
+ 'XSTEXT_UNI'=> '[varchar] (100)',
+ 'STEXT_UNI' => '[varchar] (255)',
+ 'TEXT_UNI' => '[varchar] (4000)',
+ 'MTEXT_UNI' => '[text]',
+ 'TIMESTAMP' => '[int]',
+ 'DECIMAL' => '[float]',
+ 'DECIMAL:' => '[float]',
+ 'PDECIMAL' => '[float]',
+ 'PDECIMAL:' => '[float]',
+ 'VCHAR_UNI' => '[varchar] (255)',
+ 'VCHAR_UNI:'=> '[varchar] (%d)',
+ 'VCHAR_CI' => '[varchar] (255)',
+ 'VARBINARY' => '[varchar] (255)',
+ ),
+ );
+ }
+
+ /**
+ * Constructor. Set DB Object and set {@link $return_statements return_statements}.
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param bool $return_statements True if only statements should be returned and no SQL being executed
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
+ {
+ parent::__construct($db, $return_statements);
+
+ // Determine mapping database type
+ switch ($this->db->get_sql_layer())
+ {
+ case 'mssql':
+ case 'mssql_odbc':
+ $this->sql_layer = 'mssql';
+ break;
+
+ case 'mssqlnative':
+ $this->sql_layer = 'mssqlnative';
+ break;
+ }
+
+ $this->dbms_type_map = self::get_dbms_type_map();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_tables()
+ {
+ $sql = "SELECT name
+ FROM sysobjects
+ WHERE type='U'";
+ $result = $this->db->sql_query($sql);
+
+ $tables = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $name = current($row);
+ $tables[$name] = $name;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $tables;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_table($table_name, $table_data)
+ {
+ // holds the DDL for a column
+ $columns = $statements = array();
+
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // Begin transaction
+ $statements[] = 'begin';
+
+ // Determine if we have created a PRIMARY KEY in the earliest
+ $primary_key_gen = false;
+
+ // Determine if the table requires a sequence
+ $create_sequence = false;
+
+ // Begin table sql statement
+ $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n";
+
+ if (!isset($table_data['PRIMARY_KEY']))
+ {
+ $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
+ $table_data['PRIMARY_KEY'] = 'mssqlindex';
+ }
+
+ // Iterate through the columns to create a table
+ foreach ($table_data['COLUMNS'] as $column_name => $column_data)
+ {
+ // here lies an array, filled with information compiled on the column's data
+ $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
+ {
+ trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
+ }
+
+ // here we add the definition of the new column to the list of columns
+ $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
+
+ // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
+ if (!$primary_key_gen)
+ {
+ $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
+ }
+
+ // create sequence DDL based off of the existance of auto incrementing columns
+ if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
+ {
+ $create_sequence = $column_name;
+ }
+ }
+
+ // this makes up all the columns in the create table statement
+ $table_sql .= implode(",\n", $columns);
+
+ // Close the table for two DBMS and add to the statements
+ $table_sql .= "\n);";
+ $statements[] = $table_sql;
+
+ // we have yet to create a primary key for this table,
+ // this means that we can add the one we really wanted instead
+ if (!$primary_key_gen)
+ {
+ // Write primary key
+ if (isset($table_data['PRIMARY_KEY']))
+ {
+ if (!is_array($table_data['PRIMARY_KEY']))
+ {
+ $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
+ }
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
+ foreach ($primary_key_stmts as $pk_stmt)
+ {
+ $statements[] = $pk_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Write Keys
+ if (isset($table_data['KEYS']))
+ {
+ foreach ($table_data['KEYS'] as $key_name => $key_data)
+ {
+ if (!is_array($key_data[1]))
+ {
+ $key_data[1] = array($key_data[1]);
+ }
+
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
+
+ foreach ($key_stmts as $key_stmt)
+ {
+ $statements[] = $key_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Commit Transaction
+ $statements[] = 'commit';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_columns($table_name)
+ {
+ $columns = array();
+
+ $sql = "SELECT c.name
+ FROM syscolumns c
+ LEFT JOIN sysobjects o ON c.id = o.id
+ WHERE o.name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $column = strtolower(current($row));
+ $columns[$column] = $column;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_exists($table_name, $index_name)
+ {
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['TYPE'] == 3)
+ {
+ if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_unique_index_exists($table_name, $index_name)
+ {
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Usually NON_UNIQUE is the column we want to check, but we allow for both
+ if ($row['TYPE'] == 3)
+ {
+ if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_prepare_column_data($table_name, $column_name, $column_data)
+ {
+ if (strlen($column_name) > 30)
+ {
+ trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
+ }
+
+ // Get type
+ list($column_type, ) = $this->get_column_type($column_data[0]);
+
+ // Adjust default value if db-dependent specified
+ if (is_array($column_data[1]))
+ {
+ $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
+ }
+
+ $sql = '';
+
+ $return_array = array();
+
+ $sql .= " {$column_type} ";
+ $sql_default = " {$column_type} ";
+
+ // For adding columns we need the default definition
+ if (!is_null($column_data[1]))
+ {
+ // For hexadecimal values do not use single quotes
+ if (strpos($column_data[1], '0x') === 0)
+ {
+ $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
+ $sql_default .= $return_array['default'];
+ }
+ else
+ {
+ $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
+ $sql_default .= $return_array['default'];
+ }
+ }
+
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ // $sql .= 'IDENTITY (1, 1) ';
+ $sql_default .= 'IDENTITY (1, 1) ';
+ }
+
+ $return_array['textimage'] = $column_type === '[text]';
+
+ if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
+ {
+ $sql .= 'NOT NULL';
+ $sql_default .= 'NOT NULL';
+ }
+ else
+ {
+ $sql .= 'NULL';
+ $sql_default .= 'NULL';
+ }
+
+ $return_array['column_type_sql_default'] = $sql_default;
+
+ $return_array['column_type_sql'] = $sql;
+
+ return $return_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // Does not support AFTER, only through temporary table
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_remove($table_name, $column_name, $inline = false)
+ {
+ $statements = array();
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->get_existing_indexes($table_name, $column_name);
+ $indexes = array_merge($indexes, $this->get_existing_indexes($table_name, $column_name, true));
+
+ // Drop any indexes
+ $recreate_indexes = array();
+ if (!empty($indexes))
+ {
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_index_drop($table_name, $index_name);
+ $statements = array_merge($statements, $result);
+ if (sizeof($index_data) > 1)
+ {
+ // Remove this column from the index and recreate it
+ $recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
+ }
+ }
+ }
+
+ // Drop default value constraint
+ $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Remove the column
+ $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
+
+ if (!empty($recreate_indexes))
+ {
+ // Recreate indexes after we removed the column
+ foreach ($recreate_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_drop($table_name, $index_name)
+ {
+ $statements = array();
+
+ $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_drop($table_name)
+ {
+ $statements = array();
+
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // the most basic operation, get rid of the table
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_primary_key($table_name, $column, $inline = false)
+ {
+ $statements = array();
+
+ $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
+ $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
+ $sql .= '[' . implode("],\n\t\t[", $column) . ']';
+ $sql .= ')';
+
+ $statements[] = $sql;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_unique_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ // remove index length
+ $column = preg_replace('#:.*$#', '', $column);
+
+ $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_index($table_name)
+ {
+ $index_array = array();
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['TYPE'] == 3)
+ {
+ $index_array[] = strtolower($row['INDEX_NAME']);
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return $index_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->get_existing_indexes($table_name, $column_name);
+ $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
+
+ // Drop any indexes
+ if (!empty($indexes) || !empty($unique_indexes))
+ {
+ $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
+ foreach ($drop_indexes as $index_name)
+ {
+ $result = $this->sql_index_drop($table_name, $index_name);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ // Drop default value constraint
+ $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Change the column
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
+
+ if (!empty($column_data['default']))
+ {
+ // Add new default value constraint
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $this->db->sql_escape($column_data['default']) . ' FOR [' . $column_name . ']';
+ }
+
+ if (!empty($indexes))
+ {
+ // Recreate indexes after we changed the column
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ if (!empty($unique_indexes))
+ {
+ // Recreate unique indexes after we changed the column
+ foreach ($unique_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_unique_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Get queries to drop the default constraints of a column
+ *
+ * We need to drop the default constraints of a column,
+ * before being able to change their type or deleting them.
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @return array Array with SQL statements
+ */
+ protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
+ {
+ $statements = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT so.name AS def_name
+ FROM sysobjects so
+ JOIN sysconstraints sc ON so.id = sc.constid
+ WHERE object_name(so.parent_obj) = '{$table_name}'
+ AND so.xtype = 'D'
+ AND sc.colid = (SELECT colid FROM syscolumns
+ WHERE id = object_id('{$table_name}')
+ AND name = '{$column_name}')";
+ }
+ else
+ {
+ $sql = "SELECT dobj.name AS def_name
+ FROM sys.columns col
+ LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
+ WHERE col.object_id = object_id('{$table_name}')
+ AND col.name = '{$column_name}'
+ AND dobj.name IS NOT NULL";
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
+ }
+ $this->db->sql_freeresult($result);
+
+ return $statements;
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @param bool $unique Should we get unique indexes or normal ones
+ * @return array Array with Index name => columns
+ */
+ public function get_existing_indexes($table_name, $column_name, $unique = false)
+ {
+ $existing_indexes = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'
+ AND INDEXPROPERTY(ix.id, ix.name, 'IsUnique') = " . ($unique ? '1' : '0');
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'
+ AND ix.is_unique = " . ($unique ? '1' : '0');
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!isset($row['is_unique']) || ($unique && $row['is_unique'] == 'UNIQUE') || (!$unique && $row['is_unique'] == 'NONUNIQUE'))
+ {
+ $existing_indexes[$row['phpbb_index_name']] = array();
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($existing_indexes))
+ {
+ return array();
+ }
+
+ if ($this->mssql_is_sql_server_2000())
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $existing_indexes;
+ }
+
+ /**
+ * Is the used MS SQL Server a SQL Server 2000?
+ *
+ * @return bool
+ */
+ protected function mssql_is_sql_server_2000()
+ {
+ if ($this->is_sql_server_2000 === null)
+ {
+ $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
+ $result = $this->db->sql_query($sql);
+ $properties = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
+ }
+
+ return $this->is_sql_server_2000;
+ }
+
+}
diff --git a/phpBB/phpbb/db/tools/postgres.php b/phpBB/phpbb/db/tools/postgres.php
new file mode 100644
index 0000000000..8b61625c3c
--- /dev/null
+++ b/phpBB/phpbb/db/tools/postgres.php
@@ -0,0 +1,613 @@
+<?php
+/**
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\db\tools;
+
+/**
+ * Database Tools for handling cross-db actions such as altering columns, etc.
+ * Currently not supported is returning SQL for creating tables.
+ */
+class postgres extends tools
+{
+ /**
+ * Get the column types for postgres only
+ *
+ * @return array
+ */
+ public static function get_dbms_type_map()
+ {
+ return array(
+ 'postgres' => array(
+ 'INT:' => 'INT4',
+ 'BINT' => 'INT8',
+ 'UINT' => 'INT4', // unsigned
+ 'UINT:' => 'INT4', // unsigned
+ 'USINT' => 'INT2', // unsigned
+ 'BOOL' => 'INT2', // unsigned
+ 'TINT:' => 'INT2',
+ 'VCHAR' => 'varchar(255)',
+ 'VCHAR:' => 'varchar(%d)',
+ 'CHAR:' => 'char(%d)',
+ 'XSTEXT' => 'varchar(1000)',
+ 'STEXT' => 'varchar(3000)',
+ 'TEXT' => 'varchar(8000)',
+ 'MTEXT' => 'TEXT',
+ 'XSTEXT_UNI'=> 'varchar(100)',
+ 'STEXT_UNI' => 'varchar(255)',
+ 'TEXT_UNI' => 'varchar(4000)',
+ 'MTEXT_UNI' => 'TEXT',
+ 'TIMESTAMP' => 'INT4', // unsigned
+ 'DECIMAL' => 'decimal(5,2)',
+ 'DECIMAL:' => 'decimal(%d,2)',
+ 'PDECIMAL' => 'decimal(6,3)',
+ 'PDECIMAL:' => 'decimal(%d,3)',
+ 'VCHAR_UNI' => 'varchar(255)',
+ 'VCHAR_UNI:'=> 'varchar(%d)',
+ 'VCHAR_CI' => 'varchar_ci',
+ 'VARBINARY' => 'bytea',
+ ),
+ );
+ }
+
+ /**
+ * Constructor. Set DB Object and set {@link $return_statements return_statements}.
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param bool $return_statements True if only statements should be returned and no SQL being executed
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
+ {
+ parent::__construct($db, $return_statements);
+
+ // Determine mapping database type
+ $this->sql_layer = 'postgres';
+
+ $this->dbms_type_map = self::get_dbms_type_map();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_tables()
+ {
+ $sql = 'SELECT relname
+ FROM pg_stat_user_tables';
+ $result = $this->db->sql_query($sql);
+
+ $tables = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $name = current($row);
+ $tables[$name] = $name;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $tables;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_table($table_name, $table_data)
+ {
+ // holds the DDL for a column
+ $columns = $statements = array();
+
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // Begin transaction
+ $statements[] = 'begin';
+
+ // Determine if we have created a PRIMARY KEY in the earliest
+ $primary_key_gen = false;
+
+ // Determine if the table requires a sequence
+ $create_sequence = false;
+
+ // Begin table sql statement
+ $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
+
+ // Iterate through the columns to create a table
+ foreach ($table_data['COLUMNS'] as $column_name => $column_data)
+ {
+ // here lies an array, filled with information compiled on the column's data
+ $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
+ {
+ trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
+ }
+
+ // here we add the definition of the new column to the list of columns
+ $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
+
+ // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
+ if (!$primary_key_gen)
+ {
+ $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
+ }
+
+ // create sequence DDL based off of the existance of auto incrementing columns
+ if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
+ {
+ $create_sequence = $column_name;
+ }
+ }
+
+ // this makes up all the columns in the create table statement
+ $table_sql .= implode(",\n", $columns);
+
+ // we have yet to create a primary key for this table,
+ // this means that we can add the one we really wanted instead
+ if (!$primary_key_gen)
+ {
+ // Write primary key
+ if (isset($table_data['PRIMARY_KEY']))
+ {
+ if (!is_array($table_data['PRIMARY_KEY']))
+ {
+ $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
+ }
+
+ $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
+ }
+ }
+
+ // do we need to add a sequence for auto incrementing columns?
+ if ($create_sequence)
+ {
+ $statements[] = "CREATE SEQUENCE {$table_name}_seq;";
+ }
+
+ // close the table
+ $table_sql .= "\n);";
+ $statements[] = $table_sql;
+
+ // Write Keys
+ if (isset($table_data['KEYS']))
+ {
+ foreach ($table_data['KEYS'] as $key_name => $key_data)
+ {
+ if (!is_array($key_data[1]))
+ {
+ $key_data[1] = array($key_data[1]);
+ }
+
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
+
+ foreach ($key_stmts as $key_stmt)
+ {
+ $statements[] = $key_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Commit Transaction
+ $statements[] = 'commit';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_columns($table_name)
+ {
+ $columns = array();
+
+ $sql = "SELECT a.attname
+ FROM pg_class c, pg_attribute a
+ WHERE c.relname = '{$table_name}'
+ AND a.attnum > 0
+ AND a.attrelid = c.oid";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $column = strtolower(current($row));
+ $columns[$column] = $column;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_exists($table_name, $index_name)
+ {
+ $sql = "SELECT ic.relname as index_name
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisunique != 't')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // This DBMS prefixes index names with the table name
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ if (strtolower($row['index_name']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_unique_index_exists($table_name, $index_name)
+ {
+ $sql = "SELECT ic.relname as index_name, i.indisunique
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['indisunique'] != 't')
+ {
+ continue;
+ }
+
+ // This DBMS prefixes index names with the table name
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ if (strtolower($row['index_name']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * Function to prepare some column information for better usage
+ * @access private
+ */
+ function sql_prepare_column_data($table_name, $column_name, $column_data)
+ {
+ if (strlen($column_name) > 30)
+ {
+ trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
+ }
+
+ // Get type
+ list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]);
+
+ // Adjust default value if db-dependent specified
+ if (is_array($column_data[1]))
+ {
+ $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
+ }
+
+ $sql = " {$column_type} ";
+
+ $return_array = array(
+ 'column_type' => $column_type,
+ 'auto_increment' => false,
+ );
+
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ $default_val = "nextval('{$table_name}_seq')";
+ $return_array['auto_increment'] = true;
+ }
+ else if (!is_null($column_data[1]))
+ {
+ $default_val = "'" . $column_data[1] . "'";
+ $return_array['null'] = 'NOT NULL';
+ $sql .= 'NOT NULL ';
+ }
+ else
+ {
+ // Integers need to have 0 instead of empty string as default
+ if (strpos($column_type, 'INT') === 0)
+ {
+ $default_val = '0';
+ }
+ else
+ {
+ $default_val = "'" . $column_data[1] . "'";
+ }
+ $return_array['null'] = 'NULL';
+ $sql .= 'NULL ';
+ }
+
+ $return_array['default'] = $default_val;
+
+ $sql .= "DEFAULT {$default_val}";
+
+ // Unsigned? Then add a CHECK contraint
+ if (in_array($orig_column_type, $this->unsigned_types))
+ {
+ $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
+ $sql .= " CHECK ({$column_name} >= 0)";
+ }
+
+ $return_array['column_type_sql'] = $sql;
+
+ return $return_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // Does not support AFTER, only through temporary table
+ if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
+ }
+ else
+ {
+ // old versions cannot add columns with default and null information
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
+
+ if (isset($column_data['null']))
+ {
+ if ($column_data['null'] == 'NOT NULL')
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
+ }
+ }
+
+ if (isset($column_data['default']))
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
+ }
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_remove($table_name, $column_name, $inline = false)
+ {
+ $statements = array();
+
+ $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_drop($table_name, $index_name)
+ {
+ $statements = array();
+
+ $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_drop($table_name)
+ {
+ $statements = array();
+
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // the most basic operation, get rid of the table
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ // PGSQL does not "tightly" bind sequences and tables, we must guess...
+ $sql = "SELECT relname
+ FROM pg_class
+ WHERE relkind = 'S'
+ AND relname = '{$table_name}_seq'";
+ $result = $this->db->sql_query($sql);
+
+ // We don't even care about storing the results. We already know the answer if we get rows back.
+ if ($this->db->sql_fetchrow($result))
+ {
+ $statements[] = "DROP SEQUENCE {$table_name}_seq;\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_primary_key($table_name, $column, $inline = false)
+ {
+ $statements = array();
+
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_unique_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ // remove index length
+ $column = preg_replace('#:.*$#', '', $column);
+
+ $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_index($table_name)
+ {
+ $index_array = array();
+
+ $sql = "SELECT ic.relname as index_name
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisunique != 't')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ $index_array[] = $row['index_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return array_map('strtolower', $index_array);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ $sql = 'ALTER TABLE ' . $table_name . ' ';
+
+ $sql_array = array();
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
+
+ if (isset($column_data['null']))
+ {
+ if ($column_data['null'] == 'NOT NULL')
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
+ }
+ else if ($column_data['null'] == 'NULL')
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
+ }
+ }
+
+ if (isset($column_data['default']))
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
+ }
+
+ // we don't want to double up on constraints if we change different number data types
+ if (isset($column_data['constraint']))
+ {
+ $constraint_sql = "SELECT consrc as constraint_data
+ FROM pg_constraint, pg_class bc
+ WHERE conrelid = bc.oid
+ AND bc.relname = '{$table_name}'
+ AND NOT EXISTS (
+ SELECT *
+ FROM pg_constraint as c, pg_inherits as i
+ WHERE i.inhrelid = pg_constraint.conrelid
+ AND c.conname = pg_constraint.conname
+ AND c.consrc = pg_constraint.consrc
+ AND c.conrelid = i.inhparent
+ )";
+
+ $constraint_exists = false;
+
+ $result = $this->db->sql_query($constraint_sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (trim($row['constraint_data']) == trim($column_data['constraint']))
+ {
+ $constraint_exists = true;
+ break;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!$constraint_exists)
+ {
+ $sql_array[] = 'ADD ' . $column_data['constraint'];
+ }
+ }
+
+ $sql .= implode(', ', $sql_array);
+
+ $statements[] = $sql;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @param bool $unique Should we get unique indexes or normal ones
+ * @return array Array with Index name => columns
+ */
+ public function get_existing_indexes($table_name, $column_name, $unique = false)
+ {
+ // Not supported
+ throw new \Exception('DBMS is not supported');
+ }
+}
diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php
index e1389a24bf..0d1eb63c47 100644
--- a/phpBB/phpbb/db/tools/tools.php
+++ b/phpBB/phpbb/db/tools/tools.php
@@ -36,12 +36,6 @@ class tools implements tools_interface
var $dbms_type_map = array();
/**
- * Is the used MS SQL Server a SQL Server 2000?
- * @var bool
- */
- protected $is_sql_server_2000;
-
- /**
* Get the column types for every database we support
*
* @return array
@@ -109,66 +103,6 @@ class tools implements tools_interface
'VARBINARY' => 'varbinary(255)',
),
- 'mssql' => array(
- 'INT:' => '[int]',
- 'BINT' => '[float]',
- 'UINT' => '[int]',
- 'UINT:' => '[int]',
- 'TINT:' => '[int]',
- 'USINT' => '[int]',
- 'BOOL' => '[int]',
- 'VCHAR' => '[varchar] (255)',
- 'VCHAR:' => '[varchar] (%d)',
- 'CHAR:' => '[char] (%d)',
- 'XSTEXT' => '[varchar] (1000)',
- 'STEXT' => '[varchar] (3000)',
- 'TEXT' => '[varchar] (8000)',
- 'MTEXT' => '[text]',
- 'XSTEXT_UNI'=> '[varchar] (100)',
- 'STEXT_UNI' => '[varchar] (255)',
- 'TEXT_UNI' => '[varchar] (4000)',
- 'MTEXT_UNI' => '[text]',
- 'TIMESTAMP' => '[int]',
- 'DECIMAL' => '[float]',
- 'DECIMAL:' => '[float]',
- 'PDECIMAL' => '[float]',
- 'PDECIMAL:' => '[float]',
- 'VCHAR_UNI' => '[varchar] (255)',
- 'VCHAR_UNI:'=> '[varchar] (%d)',
- 'VCHAR_CI' => '[varchar] (255)',
- 'VARBINARY' => '[varchar] (255)',
- ),
-
- 'mssqlnative' => array(
- 'INT:' => '[int]',
- 'BINT' => '[float]',
- 'UINT' => '[int]',
- 'UINT:' => '[int]',
- 'TINT:' => '[int]',
- 'USINT' => '[int]',
- 'BOOL' => '[int]',
- 'VCHAR' => '[varchar] (255)',
- 'VCHAR:' => '[varchar] (%d)',
- 'CHAR:' => '[char] (%d)',
- 'XSTEXT' => '[varchar] (1000)',
- 'STEXT' => '[varchar] (3000)',
- 'TEXT' => '[varchar] (8000)',
- 'MTEXT' => '[text]',
- 'XSTEXT_UNI'=> '[varchar] (100)',
- 'STEXT_UNI' => '[varchar] (255)',
- 'TEXT_UNI' => '[varchar] (4000)',
- 'MTEXT_UNI' => '[text]',
- 'TIMESTAMP' => '[int]',
- 'DECIMAL' => '[float]',
- 'DECIMAL:' => '[float]',
- 'PDECIMAL' => '[float]',
- 'PDECIMAL:' => '[float]',
- 'VCHAR_UNI' => '[varchar] (255)',
- 'VCHAR_UNI:'=> '[varchar] (%d)',
- 'VCHAR_CI' => '[varchar] (255)',
- 'VARBINARY' => '[varchar] (255)',
- ),
-
'oracle' => array(
'INT:' => 'number(%d)',
'BINT' => 'number(20)',
@@ -258,36 +192,6 @@ class tools implements tools_interface
'VCHAR_CI' => 'VARCHAR(255)',
'VARBINARY' => 'BLOB',
),
-
- 'postgres' => array(
- 'INT:' => 'INT4',
- 'BINT' => 'INT8',
- 'UINT' => 'INT4', // unsigned
- 'UINT:' => 'INT4', // unsigned
- 'USINT' => 'INT2', // unsigned
- 'BOOL' => 'INT2', // unsigned
- 'TINT:' => 'INT2',
- 'VCHAR' => 'varchar(255)',
- 'VCHAR:' => 'varchar(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'varchar(1000)',
- 'STEXT' => 'varchar(3000)',
- 'TEXT' => 'varchar(8000)',
- 'MTEXT' => 'TEXT',
- 'XSTEXT_UNI'=> 'varchar(100)',
- 'STEXT_UNI' => 'varchar(255)',
- 'TEXT_UNI' => 'varchar(4000)',
- 'MTEXT_UNI' => 'TEXT',
- 'TIMESTAMP' => 'INT4', // unsigned
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'varchar(255)',
- 'VCHAR_UNI:'=> 'varchar(%d)',
- 'VCHAR_CI' => 'varchar_ci',
- 'VARBINARY' => 'bytea',
- ),
);
}
@@ -298,12 +202,6 @@ class tools implements tools_interface
var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
/**
- * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules.
- * @var array
- */
- var $supported_dbms = array('mssql', 'mssqlnative', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite', 'sqlite3');
-
- /**
* This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array).
* This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command.
*/
@@ -344,15 +242,6 @@ class tools implements tools_interface
$this->sql_layer = 'mysql_41';
break;
- case 'mssql':
- case 'mssql_odbc':
- $this->sql_layer = 'mssql';
- break;
-
- case 'mssqlnative':
- $this->sql_layer = 'mssqlnative';
- break;
-
default:
$this->sql_layer = $this->db->get_sql_layer();
break;
@@ -396,19 +285,6 @@ class tools implements tools_interface
AND name <> "sqlite_sequence"';
break;
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $sql = "SELECT name
- FROM sysobjects
- WHERE type='U'";
- break;
-
- case 'postgres':
- $sql = 'SELECT relname
- FROM pg_stat_user_tables';
- break;
-
case 'oracle':
$sql = 'SELECT table_name
FROM USER_TABLES';
@@ -469,26 +345,7 @@ class tools implements tools_interface
$create_sequence = false;
// Begin table sql statement
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n";
- break;
-
- default:
- $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
- break;
- }
-
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- if (!isset($table_data['PRIMARY_KEY']))
- {
- $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
- $table_data['PRIMARY_KEY'] = 'mssqlindex';
- }
- }
+ $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
// Iterate through the columns to create a table
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
@@ -502,17 +359,7 @@ class tools implements tools_interface
}
// here we add the definition of the new column to the list of columns
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
- break;
-
- default:
- $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
- break;
- }
+ $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
// see if we have found a primary key set due to a column definition if we have found it, we can stop looking
if (!$primary_key_gen)
@@ -530,16 +377,6 @@ class tools implements tools_interface
// this makes up all the columns in the create table statement
$table_sql .= implode(",\n", $columns);
- // Close the table for two DBMS and add to the statements
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
- }
-
// we have yet to create a primary key for this table,
// this means that we can add the one we really wanted instead
if (!$primary_key_gen)
@@ -556,27 +393,11 @@ class tools implements tools_interface
{
case 'mysql_40':
case 'mysql_41':
- case 'postgres':
case 'sqlite':
case 'sqlite3':
$table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
break;
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
- foreach ($primary_key_stmts as $pk_stmt)
- {
- $statements[] = $pk_stmt;
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
case 'oracle':
$table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
break;
@@ -600,17 +421,6 @@ class tools implements tools_interface
$statements[] = $table_sql;
break;
- case 'postgres':
- // do we need to add a sequence for auto incrementing columns?
- if ($create_sequence)
- {
- $statements[] = "CREATE SEQUENCE {$table_name}_seq;";
- }
-
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
-
case 'oracle':
$table_sql .= "\n)";
$statements[] = $table_sql;
@@ -1063,26 +873,6 @@ class tools implements tools_interface
$sql = "SHOW COLUMNS FROM $table_name";
break;
- // PostgreSQL has a way of doing this in a much simpler way but would
- // not allow us to support all versions of PostgreSQL
- case 'postgres':
- $sql = "SELECT a.attname
- FROM pg_class c, pg_attribute a
- WHERE c.relname = '{$table_name}'
- AND a.attnum > 0
- AND a.attrelid = c.oid";
- break;
-
- // same deal with PostgreSQL, we must perform more complex operations than
- // we technically could
- case 'mssql':
- case 'mssqlnative':
- $sql = "SELECT c.name
- FROM syscolumns c
- LEFT JOIN sysobjects o ON c.id = o.id
- WHERE o.name = '{$table_name}'";
- break;
-
case 'oracle':
$sql = "SELECT column_name
FROM user_tab_columns
@@ -1154,40 +944,8 @@ class tools implements tools_interface
*/
function sql_index_exists($table_name, $index_name)
{
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
-
- return false;
- }
-
switch ($this->sql_layer)
{
- case 'postgres':
- $sql = "SELECT ic.relname as index_name
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisunique != 't')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
- break;
-
case 'mysql_40':
case 'mysql_41':
$sql = 'SHOW KEYS
@@ -1223,7 +981,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
case 'oracle':
- case 'postgres':
case 'sqlite':
case 'sqlite3':
$row[$col] = substr($row[$col], strlen($table_name) + 1);
@@ -1246,39 +1003,8 @@ class tools implements tools_interface
*/
function sql_unique_index_exists($table_name, $index_name)
{
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- // Usually NON_UNIQUE is the column we want to check, but we allow for both
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
- return false;
- }
-
switch ($this->sql_layer)
{
- case 'postgres':
- $sql = "SELECT ic.relname as index_name, i.indisunique
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
- break;
-
case 'mysql_40':
case 'mysql_41':
$sql = 'SHOW KEYS
@@ -1315,11 +1041,6 @@ class tools implements tools_interface
continue;
}
- if ($this->sql_layer == 'postgres' && $row['indisunique'] != 't')
- {
- continue;
- }
-
// These DBMS prefix index name with the table name
switch ($this->sql_layer)
{
@@ -1335,7 +1056,6 @@ class tools implements tools_interface
}
break;
- case 'postgres':
case 'sqlite':
case 'sqlite3':
$row[$col] = substr($row[$col], strlen($table_name) + 1);
@@ -1410,50 +1130,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- $sql .= " {$column_type} ";
- $sql_default = " {$column_type} ";
-
- // For adding columns we need the default definition
- if (!is_null($column_data[1]))
- {
- // For hexadecimal values do not use single quotes
- if (strpos($column_data[1], '0x') === 0)
- {
- $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
- $sql_default .= $return_array['default'];
- }
- else
- {
- $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
- $sql_default .= $return_array['default'];
- }
- }
-
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
-// $sql .= 'IDENTITY (1, 1) ';
- $sql_default .= 'IDENTITY (1, 1) ';
- }
-
- $return_array['textimage'] = $column_type === '[text]';
-
- if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
- {
- $sql .= 'NOT NULL';
- $sql_default .= 'NOT NULL';
- }
- else
- {
- $sql .= 'NULL';
- $sql_default .= 'NULL';
- }
-
- $return_array['column_type_sql_default'] = $sql_default;
-
- break;
-
case 'mysql_40':
case 'mysql_41':
$sql .= " {$column_type} ";
@@ -1507,43 +1183,6 @@ class tools implements tools_interface
break;
- case 'postgres':
- $return_array['column_type'] = $column_type;
-
- $sql .= " {$column_type} ";
-
- $return_array['auto_increment'] = false;
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
- $default_val = "nextval('{$table_name}_seq')";
- $return_array['auto_increment'] = true;
- }
- else if (!is_null($column_data[1]))
- {
- $default_val = "'" . $column_data[1] . "'";
- $return_array['null'] = 'NOT NULL';
- $sql .= 'NOT NULL ';
- }
- else
- {
- $default_val = "'" . $column_data[1] . "'";
- $return_array['null'] = 'NULL';
- $sql .= 'NULL ';
- }
-
- $return_array['default'] = $default_val;
-
- $sql .= "DEFAULT {$default_val}";
-
- // Unsigned? Then add a CHECK contraint
- if (in_array($orig_column_type, $this->unsigned_types))
- {
- $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
- $sql .= " CHECK ({$column_name} >= 0)";
- }
-
- break;
-
case 'sqlite':
case 'sqlite3':
$return_array['primary_key_set'] = false;
@@ -1585,6 +1224,7 @@ class tools implements tools_interface
*/
function get_column_type($column_map_type)
{
+ $column_type = '';
if (strpos($column_map_type, ':') !== false)
{
list($orig_column_type, $column_length) = explode(':', $column_map_type);
@@ -1645,12 +1285,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- // Does not support AFTER, only through temporary table
- $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
- break;
-
case 'mysql_40':
case 'mysql_41':
$after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : '';
@@ -1662,33 +1296,6 @@ class tools implements tools_interface
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
break;
- case 'postgres':
- // Does not support AFTER, only through temporary table
- if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
- }
- else
- {
- // old versions cannot add columns with default and null information
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
-
- if (isset($column_data['null']))
- {
- if ($column_data['null'] == 'NOT NULL')
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
- }
- }
-
- if (isset($column_data['default']))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
- }
- }
-
- break;
-
case 'sqlite':
if ($inline && $this->return_statements)
{
@@ -1762,51 +1369,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $indexes = $this->get_existing_indexes($table_name, $column_name);
- $indexes = array_merge($indexes, $this->get_existing_indexes($table_name, $column_name, true));
-
- // Drop any indexes
- $recreate_indexes = array();
- if (!empty($indexes))
- {
- foreach ($indexes as $index_name => $index_data)
- {
- $result = $this->sql_index_drop($table_name, $index_name);
- $statements = array_merge($statements, $result);
- if (sizeof($index_data) > 1)
- {
- // Remove this column from the index and recreate it
- $recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
- }
- }
- }
-
- // Drop default value constraint
- $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
- $statements = array_merge($statements, $result);
-
- // Remove the column
- $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
-
- if (!empty($recreate_indexes))
- {
- // Recreate indexes after we removed the column
- foreach ($recreate_indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
case 'mysql_40':
case 'mysql_41':
$statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
@@ -1816,10 +1378,6 @@ class tools implements tools_interface
$statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
break;
- case 'postgres':
- $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
- break;
-
case 'sqlite':
case 'sqlite3':
@@ -1891,18 +1449,12 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name;
- break;
-
case 'mysql_40':
case 'mysql_41':
$statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
break;
case 'oracle':
- case 'postgres':
case 'sqlite':
case 'sqlite3':
$statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
@@ -1944,22 +1496,6 @@ class tools implements tools_interface
}
$this->db->sql_freeresult($result);
break;
-
- case 'postgres':
- // PGSQL does not "tightly" bind sequences and tables, we must guess...
- $sql = "SELECT relname
- FROM pg_class
- WHERE relkind = 'S'
- AND relname = '{$table_name}_seq'";
- $result = $this->db->sql_query($sql);
-
- // We don't even care about storing the results. We already know the answer if we get rows back.
- if ($this->db->sql_fetchrow($result))
- {
- $statements[] = "DROP SEQUENCE {$table_name}_seq;\n";
- }
- $this->db->sql_freeresult($result);
- break;
}
return $this->_sql_run_sql($statements);
@@ -1974,22 +1510,11 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'postgres':
case 'mysql_40':
case 'mysql_41':
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
break;
- case 'mssql':
- case 'mssqlnative':
- $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
- $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
- $sql .= '[' . implode("],\n\t\t[", $column) . ']';
- $sql .= ')';
-
- $statements[] = $sql;
- break;
-
case 'oracle':
$statements[] = 'ALTER TABLE ' . $table_name . ' add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
break;
@@ -2056,16 +1581,10 @@ class tools implements tools_interface
{
$statements = array();
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . '_' . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = strlen($table_prefix) + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
+ $this->check_index_name_length($table_name, $index_name);
switch ($this->sql_layer)
{
- case 'postgres':
case 'oracle':
case 'sqlite':
case 'sqlite3':
@@ -2076,11 +1595,6 @@ class tools implements tools_interface
case 'mysql_41':
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')';
break;
-
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
- break;
}
return $this->_sql_run_sql($statements);
@@ -2093,12 +1607,7 @@ class tools implements tools_interface
{
$statements = array();
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = strlen($table_prefix) + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
+ $this->check_index_name_length($table_name, $index_name);
// remove index length unless MySQL4
if ('mysql_40' != $this->sql_layer)
@@ -2108,7 +1617,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'postgres':
case 'oracle':
case 'sqlite':
case 'sqlite3':
@@ -2129,96 +1637,79 @@ class tools implements tools_interface
case 'mysql_41':
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')';
break;
-
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
- break;
}
return $this->_sql_run_sql($statements);
}
/**
+ * Check whether the index name is too long
+ *
+ * @param string $table_name
+ * @param string $index_name
+ */
+ protected function check_index_name_length($table_name, $index_name)
+ {
+ $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
+ if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
+ {
+ $max_length = strlen($table_prefix) + 24;
+ trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
function sql_list_index($table_name)
{
$index_array = array();
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- $index_array[] = $row['INDEX_NAME'];
- }
- }
- $this->db->sql_freeresult($result);
- }
- else
+ switch ($this->sql_layer)
{
- switch ($this->sql_layer)
- {
- case 'postgres':
- $sql = "SELECT ic.relname as index_name
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisunique != 't')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql = 'SHOW KEYS
+ FROM ' . $table_name;
+ $col = 'Key_name';
break;
- case 'mysql_40':
- case 'mysql_41':
- $sql = 'SHOW KEYS
- FROM ' . $table_name;
- $col = 'Key_name';
+ case 'oracle':
+ $sql = "SELECT index_name
+ FROM user_indexes
+ WHERE table_name = '" . strtoupper($table_name) . "'
+ AND generated = 'N'
+ AND uniqueness = 'NONUNIQUE'";
+ $col = 'index_name';
break;
- case 'oracle':
- $sql = "SELECT index_name
- FROM user_indexes
- WHERE table_name = '" . strtoupper($table_name) . "'
- AND generated = 'N'
- AND uniqueness = 'NONUNIQUE'";
- $col = 'index_name';
+ case 'sqlite':
+ case 'sqlite3':
+ $sql = "PRAGMA index_info('" . $table_name . "');";
+ $col = 'name';
break;
+ }
- case 'sqlite':
- case 'sqlite3':
- $sql = "PRAGMA index_info('" . $table_name . "');";
- $col = 'name';
- break;
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
+ {
+ continue;
}
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
+ switch ($this->sql_layer)
{
- if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
- {
- continue;
- }
-
- switch ($this->sql_layer)
- {
- case 'oracle':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
+ case 'oracle':
+ case 'sqlite':
+ case 'sqlite3':
+ $row[$col] = substr($row[$col], strlen($table_name) + 1);
break;
- }
-
- $index_array[] = $row[$col];
}
- $this->db->sql_freeresult($result);
+
+ $index_array[] = $row[$col];
}
+ $this->db->sql_freeresult($result);
return array_map('strtolower', $index_array);
}
@@ -2246,62 +1737,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $indexes = $this->get_existing_indexes($table_name, $column_name);
- $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
-
- // Drop any indexes
- if (!empty($indexes) || !empty($unique_indexes))
- {
- $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
- foreach ($drop_indexes as $index_name)
- {
- $result = $this->sql_index_drop($table_name, $index_name);
- $statements = array_merge($statements, $result);
- }
- }
-
- // Drop default value constraint
- $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
- $statements = array_merge($statements, $result);
-
- // Change the column
- $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
-
- if (!empty($column_data['default']))
- {
- // Add new default value constraint
- $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $this->db->sql_escape($column_data['default']) . ' FOR [' . $column_name . ']';
- }
-
- if (!empty($indexes))
- {
- // Recreate indexes after we changed the column
- foreach ($indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- if (!empty($unique_indexes))
- {
- // Recreate unique indexes after we changed the column
- foreach ($unique_indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_unique_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
case 'mysql_40':
case 'mysql_41':
$statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
@@ -2373,69 +1808,6 @@ class tools implements tools_interface
$this->return_statements = $old_return_statements;
break;
- case 'postgres':
- $sql = 'ALTER TABLE ' . $table_name . ' ';
-
- $sql_array = array();
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
-
- if (isset($column_data['null']))
- {
- if ($column_data['null'] == 'NOT NULL')
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
- }
- else if ($column_data['null'] == 'NULL')
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
- }
- }
-
- if (isset($column_data['default']))
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
- }
-
- // we don't want to double up on constraints if we change different number data types
- if (isset($column_data['constraint']))
- {
- $constraint_sql = "SELECT consrc as constraint_data
- FROM pg_constraint, pg_class bc
- WHERE conrelid = bc.oid
- AND bc.relname = '{$table_name}'
- AND NOT EXISTS (
- SELECT *
- FROM pg_constraint as c, pg_inherits as i
- WHERE i.inhrelid = pg_constraint.conrelid
- AND c.conname = pg_constraint.conname
- AND c.consrc = pg_constraint.consrc
- AND c.conrelid = i.inhparent
- )";
-
- $constraint_exists = false;
-
- $result = $this->db->sql_query($constraint_sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (trim($row['constraint_data']) == trim($column_data['constraint']))
- {
- $constraint_exists = true;
- break;
- }
- }
- $this->db->sql_freeresult($result);
-
- if (!$constraint_exists)
- {
- $sql_array[] = 'ADD ' . $column_data['constraint'];
- }
- }
-
- $sql .= implode(', ', $sql_array);
-
- $statements[] = $sql;
- break;
-
case 'sqlite':
case 'sqlite3':
@@ -2504,52 +1876,6 @@ class tools implements tools_interface
}
/**
- * Get queries to drop the default constraints of a column
- *
- * We need to drop the default constraints of a column,
- * before being able to change their type or deleting them.
- *
- * @param string $table_name
- * @param string $column_name
- * @return array Array with SQL statements
- */
- protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
- {
- $statements = array();
- if ($this->mssql_is_sql_server_2000())
- {
- // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
- // Deprecated in SQL Server 2005
- $sql = "SELECT so.name AS def_name
- FROM sysobjects so
- JOIN sysconstraints sc ON so.id = sc.constid
- WHERE object_name(so.parent_obj) = '{$table_name}'
- AND so.xtype = 'D'
- AND sc.colid = (SELECT colid FROM syscolumns
- WHERE id = object_id('{$table_name}')
- AND name = '{$column_name}')";
- }
- else
- {
- $sql = "SELECT dobj.name AS def_name
- FROM sys.columns col
- LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
- WHERE col.object_id = object_id('{$table_name}')
- AND col.name = '{$column_name}'
- AND dobj.name IS NOT NULL";
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
- }
- $this->db->sql_freeresult($result);
-
- return $statements;
- }
-
- /**
* Get a list with existing indexes for the column
*
* @param string $table_name
@@ -2563,7 +1889,6 @@ class tools implements tools_interface
{
case 'mysql_40':
case 'mysql_41':
- case 'postgres':
case 'sqlite':
case 'sqlite3':
// Not supported
@@ -2576,40 +1901,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- if ($this->mssql_is_sql_server_2000())
- {
- // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
- // Deprecated in SQL Server 2005
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
- FROM sysindexes ix
- INNER JOIN sysindexkeys ixc
- ON ixc.id = ix.id
- AND ixc.indid = ix.indid
- INNER JOIN syscolumns cols
- ON cols.colid = ixc.colid
- AND cols.id = ix.id
- WHERE ix.id = object_id('{$table_name}')
- AND cols.name = '{$column_name}'
- AND INDEXPROPERTY(ix.id, ix.name, 'IsUnique') = " . ($unique ? '1' : '0');
- }
- else
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
- FROM sys.indexes ix
- INNER JOIN sys.index_columns ixc
- ON ixc.object_id = ix.object_id
- AND ixc.index_id = ix.index_id
- INNER JOIN sys.columns cols
- ON cols.column_id = ixc.column_id
- AND cols.object_id = ix.object_id
- WHERE ix.object_id = object_id('{$table_name}')
- AND cols.name = '{$column_name}'
- AND ix.is_unique = " . ($unique ? '1' : '0');
- }
- break;
-
case 'oracle':
$sql = "SELECT ix.index_name AS phpbb_index_name, ix.uniqueness AS is_unique
FROM all_ind_columns ixc, all_indexes ix
@@ -2636,36 +1927,6 @@ class tools implements tools_interface
switch ($this->sql_layer)
{
- case 'mssql':
- case 'mssqlnative':
- if ($this->mssql_is_sql_server_2000())
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
- FROM sysindexes ix
- INNER JOIN sysindexkeys ixc
- ON ixc.id = ix.id
- AND ixc.indid = ix.indid
- INNER JOIN syscolumns cols
- ON cols.colid = ixc.colid
- AND cols.id = ix.id
- WHERE ix.id = object_id('{$table_name}')
- AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
- }
- else
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
- FROM sys.indexes ix
- INNER JOIN sys.index_columns ixc
- ON ixc.object_id = ix.object_id
- AND ixc.index_id = ix.index_id
- INNER JOIN sys.columns cols
- ON cols.column_id = ixc.column_id
- AND cols.object_id = ix.object_id
- WHERE ix.object_id = object_id('{$table_name}')
- AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
- }
- break;
-
case 'oracle':
$sql = "SELECT index_name AS phpbb_index_name, column_name AS phpbb_column_name
FROM all_ind_columns
@@ -2685,25 +1946,6 @@ class tools implements tools_interface
}
/**
- * Is the used MS SQL Server a SQL Server 2000?
- *
- * @return bool
- */
- protected function mssql_is_sql_server_2000()
- {
- if ($this->is_sql_server_2000 === null)
- {
- $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
- $result = $this->db->sql_query($sql);
- $properties = $this->db->sql_fetchrow($result);
- $this->db->sql_freeresult($result);
- $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
- }
-
- return $this->is_sql_server_2000;
- }
-
- /**
* Returns the Queries which are required to recreate a table including indexes
*
* @param string $table_name
diff --git a/phpBB/phpbb/event/dispatcher.php b/phpBB/phpbb/event/dispatcher.php
index 9a786022c2..1c4abeb108 100644
--- a/phpBB/phpbb/event/dispatcher.php
+++ b/phpBB/phpbb/event/dispatcher.php
@@ -14,6 +14,7 @@
namespace phpbb\event;
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
+use Symfony\Component\EventDispatcher\Event;
/**
* Extension of the Symfony2 EventDispatcher
@@ -32,6 +33,11 @@ use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_interface
{
/**
+ * @var bool
+ */
+ protected $disabled = false;
+
+ /**
* {@inheritdoc}
*/
public function trigger_event($eventName, $data = array())
@@ -40,4 +46,33 @@ class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_int
$this->dispatch($eventName, $event);
return $event->get_data_filtered(array_keys($data));
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dispatch($eventName, Event $event = null)
+ {
+ if ($this->disabled)
+ {
+ return $event;
+ }
+
+ return parent::dispatch($eventName, $event);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable()
+ {
+ $this->disabled = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable()
+ {
+ $this->disabled = false;
+ }
}
diff --git a/phpBB/phpbb/event/dispatcher_interface.php b/phpBB/phpbb/event/dispatcher_interface.php
index 50a3ef9101..c66aa98260 100644
--- a/phpBB/phpbb/event/dispatcher_interface.php
+++ b/phpBB/phpbb/event/dispatcher_interface.php
@@ -37,4 +37,14 @@ interface dispatcher_interface extends \Symfony\Component\EventDispatcher\EventD
* @return mixed
*/
public function trigger_event($eventName, $data = array());
+
+ /**
+ * Disable the event dispatcher.
+ */
+ public function disable();
+
+ /**
+ * Enable the event dispatcher.
+ */
+ public function enable();
}
diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php
index 44e87507f9..eb7831ad34 100644
--- a/phpBB/phpbb/event/kernel_exception_subscriber.php
+++ b/phpBB/phpbb/event/kernel_exception_subscriber.php
@@ -14,9 +14,10 @@
namespace phpbb\event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
-use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpFoundation\Response;
class kernel_exception_subscriber implements EventSubscriberInterface
@@ -53,23 +54,55 @@ class kernel_exception_subscriber implements EventSubscriberInterface
*/
public function on_kernel_exception(GetResponseForExceptionEvent $event)
{
- page_header($this->user->lang('INFORMATION'));
-
$exception = $event->getException();
- $this->template->assign_vars(array(
- 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
- 'MESSAGE_TEXT' => $exception->getMessage(),
- ));
+ $message = $exception->getMessage();
+
+ if ($exception instanceof \phpbb\exception\exception_interface)
+ {
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($message), $exception->get_parameters()));
+ }
+
+ if (!$event->getRequest()->isXmlHttpRequest())
+ {
+ page_header($this->user->lang('INFORMATION'));
+
+ $this->template->assign_vars(array(
+ 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
+ 'MESSAGE_TEXT' => $message,
+ ));
+
+ $this->template->set_filenames(array(
+ 'body' => 'message_body.html',
+ ));
+
+ page_footer(true, false, false);
+
+ $response = new Response($this->template->assign_display('body'), 500);
+ }
+ else
+ {
+ $data = array();
+
+ if (!empty($message))
+ {
+ $data['message'] = $message;
+ }
+
+ if (defined('DEBUG'))
+ {
+ $data['trace'] = $exception->getTrace();
+ }
- $this->template->set_filenames(array(
- 'body' => 'message_body.html',
- ));
+ $response = new JsonResponse($data, 500);
+ }
- page_footer(true, false, false);
+ if ($exception instanceof HttpExceptionInterface)
+ {
+ $response->setStatusCode($exception->getStatusCode());
+ $response->headers->add($exception->getHeaders());
+ }
- $status_code = $exception instanceof HttpException ? $exception->getStatusCode() : 500;
- $response = new Response($this->template->assign_display('body'), $status_code);
$event->setResponse($response);
}
diff --git a/phpBB/phpbb/event/kernel_terminate_subscriber.php b/phpBB/phpbb/event/kernel_terminate_subscriber.php
index 57e4840380..3a709f73fd 100644
--- a/phpBB/phpbb/event/kernel_terminate_subscriber.php
+++ b/phpBB/phpbb/event/kernel_terminate_subscriber.php
@@ -35,7 +35,7 @@ class kernel_terminate_subscriber implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
- KernelEvents::TERMINATE => 'on_kernel_terminate',
+ KernelEvents::TERMINATE => array('on_kernel_terminate', ~PHP_INT_MAX),
);
}
}
diff --git a/phpBB/phpbb/exception/exception_interface.php b/phpBB/phpbb/exception/exception_interface.php
new file mode 100644
index 0000000000..e8526a35f5
--- /dev/null
+++ b/phpBB/phpbb/exception/exception_interface.php
@@ -0,0 +1,29 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\exception;
+
+/**
+ * Interface exception_interface
+ *
+ * Define an exception which support a language var as message.
+ */
+interface exception_interface
+{
+ /**
+ * Return the arguments associated with the message if it's a language var.
+ *
+ * @return array
+ */
+ public function get_parameters();
+}
diff --git a/phpBB/phpbb/exception/http_exception.php b/phpBB/phpbb/exception/http_exception.php
new file mode 100644
index 0000000000..0e6ffe4f59
--- /dev/null
+++ b/phpBB/phpbb/exception/http_exception.php
@@ -0,0 +1,70 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\exception;
+
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+
+/**
+ * Class http_exception
+ */
+class http_exception extends runtime_exception implements HttpExceptionInterface
+{
+ /**
+ * Http status code.
+ *
+ * @var integer
+ */
+ private $status_code;
+
+ /**
+ * Additional headers to set in the response.
+ *
+ * @var array
+ */
+ private $headers;
+
+ /**
+ * Constructor
+ *
+ * @param integer $status_code The http status code.
+ * @param string $message The Exception message to throw (must be a language variable).
+ * @param array $parameters The parameters to use with the language var.
+ * @param \Exception $previous The previous exception used for the exception chaining.
+ * @param array $headers Additional headers to set in the response.
+ * @param integer $code The Exception code.
+ */
+ public function __construct($status_code, $message = "", array $parameters = array(), \Exception $previous = null, array $headers = array(), $code = 0)
+ {
+ $this->status_code = $status_code;
+ $this->headers = $headers;
+
+ parent::__construct($message, $parameters, $previous, $code);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getStatusCode()
+ {
+ return $this->status_code;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+}
diff --git a/phpBB/phpbb/exception/runtime_exception.php b/phpBB/phpbb/exception/runtime_exception.php
new file mode 100644
index 0000000000..6568bbf86f
--- /dev/null
+++ b/phpBB/phpbb/exception/runtime_exception.php
@@ -0,0 +1,52 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\exception;
+
+/**
+ * Class runtime_exception
+ *
+ * Define an exception which support a language var as message.
+ */
+class runtime_exception extends \RuntimeException implements exception_interface
+{
+ /**
+ * Parameters to use with the language var.
+ *
+ * @var array
+ */
+ private $parameters;
+
+ /**
+ * Constructor
+ *
+ * @param string $message The Exception message to throw (must be a language variable).
+ * @param array $parameters The parameters to use with the language var.
+ * @param \Exception $previous The previous runtime_exception used for the runtime_exception chaining.
+ * @param integer $code The Exception code.
+ */
+ public function __construct($message = "", array $parameters = array(), \Exception $previous = null, $code = 0)
+ {
+ $this->parameters = $parameters;
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_parameters()
+ {
+ return $this->parameters;
+ }
+}
diff --git a/phpBB/phpbb/feed/base.php b/phpBB/phpbb/feed/base.php
index e31854160a..322e2ee9f1 100644
--- a/phpBB/phpbb/feed/base.php
+++ b/phpBB/phpbb/feed/base.php
@@ -67,6 +67,9 @@ abstract class base
*/
var $separator_stats = "\xE2\x80\x94"; // &mdash;
+ /** @var mixed Query result handle */
+ protected $result;
+
/**
* Constructor
*
@@ -229,9 +232,7 @@ abstract class base
function get_item()
{
- static $result;
-
- if (!isset($result))
+ if (!isset($this->result))
{
if (!$this->get_sql())
{
@@ -240,10 +241,10 @@ abstract class base
// Query database
$sql = $this->db->sql_build_query('SELECT', $this->sql);
- $result = $this->db->sql_query_limit($sql, $this->num_items);
+ $this->result = $this->db->sql_query_limit($sql, $this->num_items);
}
- return $this->db->sql_fetchrow($result);
+ return $this->db->sql_fetchrow($this->result);
}
function user_viewprofile($row)
diff --git a/phpBB/phpbb/file_downloader.php b/phpBB/phpbb/file_downloader.php
index d717b394d5..462b87ca51 100644
--- a/phpBB/phpbb/file_downloader.php
+++ b/phpBB/phpbb/file_downloader.php
@@ -33,7 +33,7 @@ class file_downloader
* @return mixed File data as string if file can be read and there is no
* timeout, false if there were errors or the connection timed out
*
- * @throws \RuntimeException If data can't be retrieved and no error
+ * @throws \phpbb\exception\runtime_exception If data can't be retrieved and no error
* message is returned
*/
public function get($host, $directory, $filename, $port = 80, $timeout = 6)
@@ -69,7 +69,7 @@ class file_downloader
}
else if (stripos($line, '404 not found') !== false)
{
- throw new \RuntimeException(array('FILE_NOT_FOUND', $filename));
+ throw new \phpbb\exception\runtime_exception('FILE_NOT_FOUND', array($filename));
}
}
@@ -77,7 +77,7 @@ class file_downloader
if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
{
- throw new \RuntimeException('FSOCK_TIMEOUT');
+ throw new \phpbb\exception\runtime_exception('FSOCK_TIMEOUT');
}
}
@fclose($socket);
@@ -91,7 +91,7 @@ class file_downloader
}
else
{
- throw new \RuntimeException('FSOCK_DISABLED');
+ throw new \phpbb\exception\runtime_exception('FSOCK_DISABLED');
}
}
diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php
index 0c5205530b..4bb2e7a75a 100644
--- a/phpBB/phpbb/log/log.php
+++ b/phpBB/phpbb/log/log.php
@@ -27,7 +27,7 @@ class log implements \phpbb\log\log_interface
/**
* An array with the disabled log types. Logs of such types will not be
- * added when add_log() is called.
+ * added when add() is called.
* @var array
*/
protected $disabled_types;
@@ -223,14 +223,14 @@ class log implements \phpbb\log\log_interface
return false;
}
- if ($log_time == false)
+ if ($log_time === false)
{
$log_time = time();
}
$sql_ary = array(
- 'user_id' => $user_id,
- 'log_ip' => $log_ip,
+ 'user_id' => $user_id ? (int) $user_id : ANONYMOUS,
+ 'log_ip' => empty($log_ip) ? '' : $log_ip,
'log_time' => $log_time,
'log_operation' => $log_operation,
);
diff --git a/phpBB/phpbb/log/log_interface.php b/phpBB/phpbb/log/log_interface.php
index 5932f722aa..86286e6f88 100644
--- a/phpBB/phpbb/log/log_interface.php
+++ b/phpBB/phpbb/log/log_interface.php
@@ -32,8 +32,8 @@ interface log_interface
* Disable log
*
* This function allows disabling the log system or parts of it, for this
- * page call. When add_log is called and the type is disabled,
- * the log will not be added to the database.
+ * page call. When add() is called and the type is disabled, the log will
+ * not be added to the database.
*
* @param mixed $type The log type we want to disable. Empty to
* disable all logs. Can also be an array of types.
@@ -57,12 +57,12 @@ interface log_interface
/**
* Adds a log entry to the database
*
- * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
- * @param int $user_id User ID of the user
- * @param string $log_ip IP address of the user
- * @param string $log_operation Name of the operation
- * @param int $log_time Timestamp when the log entry was added, if empty time() will be used
- * @param array $additional_data More arguments can be added, depending on the log_type
+ * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
+ * @param int $user_id User ID of the user
+ * @param string $log_ip IP address of the user
+ * @param string $log_operation Name of the operation
+ * @param int|bool $log_time Timestamp when the log entry was added. If false, time() will be used
+ * @param array $additional_data More arguments can be added, depending on the log_type
*
* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
*/
diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php
index aa52eb61d0..db92170dd8 100644
--- a/phpBB/phpbb/notification/manager.php
+++ b/phpBB/phpbb/notification/manager.php
@@ -38,7 +38,7 @@ class manager
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\event\dispatcher */
+ /** @var \phpbb\event\dispatcher_interface */
protected $phpbb_dispatcher;
/** @var \phpbb\db\driver\driver_interface */
@@ -73,7 +73,7 @@ class manager
* @param ContainerInterface $phpbb_container
* @param \phpbb\user_loader $user_loader
* @param \phpbb\config\config $config
- * @param \phpbb\event\dispatcher $phpbb_dispatcher
+ * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\service $cache
* @param \phpbb\user $user
@@ -85,7 +85,7 @@ class manager
*
* @return \phpbb\notification\manager
*/
- public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php
index d9e74f2e95..421eff6372 100644
--- a/phpBB/phpbb/notification/type/post.php
+++ b/phpBB/phpbb/notification/type/post.php
@@ -357,6 +357,7 @@ class post extends \phpbb\notification\type\base
{
$tracking_data[$row['user_id']] = $row['mark_time'];
}
+ $this->db->sql_freeresult($result);
return $tracking_data;
}
diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php
index cf0ec77099..5f57087b73 100644
--- a/phpBB/phpbb/notification/type/topic.php
+++ b/phpBB/phpbb/notification/type/topic.php
@@ -257,6 +257,7 @@ class topic extends \phpbb\notification\type\base
{
$tracking_data[$row['user_id']] = $row['mark_time'];
}
+ $this->db->sql_freeresult($result);
return $tracking_data;
}
diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php
index b49d8d13c2..5400c1c5a6 100644
--- a/phpBB/phpbb/path_helper.php
+++ b/phpBB/phpbb/path_helper.php
@@ -455,4 +455,38 @@ class path_helper
return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : '');
}
+
+ /**
+ * Get a valid page
+ *
+ * @param string $page The page to verify
+ * @param bool $mod_rewrite Whether mod_rewrite is enabled, default: false
+ *
+ * @return string A valid page based on given page and mod_rewrite
+ */
+ public function get_valid_page($page, $mod_rewrite = false)
+ {
+ // We need to be cautious here.
+ // On some situations, the redirect path is an absolute URL, sometimes a relative path
+ // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
+ // else we use the URL directly.
+ $url_parts = parse_url($page);
+
+ // URL
+ if ($url_parts === false || empty($url_parts['scheme']) || empty($url_parts['host']))
+ {
+ // Remove 'app.php/' from the page, when rewrite is enabled.
+ // Treat app.php as a reserved file name and remove on mod rewrite
+ // even if it might not be in the phpBB root.
+ if ($mod_rewrite && ($app_position = strpos($page, 'app.' . $this->php_ext . '/')) !== false)
+ {
+ $page = substr($page, 0, $app_position) . substr($page, $app_position + strlen('app.' . $this->php_ext . '/'));
+ }
+
+ // Remove preceding slashes from page name and prepend root path
+ $page = $this->get_phpbb_root_path() . ltrim($page, '/\\');
+ }
+
+ return $page;
+ }
}
diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php
index 75934e3be7..f6f3f17a6c 100644
--- a/phpBB/phpbb/profilefields/type/type_bool.php
+++ b/phpBB/phpbb/profilefields/type/type_bool.php
@@ -173,7 +173,7 @@ class type_bool extends type_base
}
else
{
- return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1);
+ return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1) ? $this->lang_helper->get($field_id, $lang_id, $field_value + 1) : null;
}
}
@@ -367,29 +367,29 @@ class type_bool extends type_base
*/
public function prepare_hidden_fields($step, $key, $action, &$field_data)
{
- if ($key == 'l_lang_options' && $this->request->is_set('l_lang_options'))
+ if ($key == 'field_default_value')
{
- return $this->request->variable($key, array(array('')), true);
- }
- else if ($key == 'field_default_value')
- {
- return $this->request->variable($key, $field_data[$key]);
- }
- else
- {
- if (!$this->request->is_set($key))
- {
- return false;
- }
- else if ($key == 'field_ident' && isset($field_data[$key]))
- {
- return $field_data[$key];
- }
- else
+ $field_length = $this->request->variable('field_length', 0);
+
+ // Do a simple is set check if using checkbox.
+ if ($field_length == 2)
{
- return ($key == 'lang_options') ? $this->request->variable($key, array(''), true) : $this->request->variable($key, '', true);
+ return $this->request->is_set($key);
}
+ return $this->request->variable($key, $field_data[$key], true);
+ }
+
+ $default_lang_options = array(
+ 'l_lang_options' => array(0 => array('')),
+ 'lang_options' => array(0 => ''),
+ );
+
+ if (isset($default_lang_options[$key]) && $this->request->is_set($key))
+ {
+ return $this->request->variable($key, $default_lang_options[$key], true);
}
+
+ return parent::prepare_hidden_fields($step, $key, $action, $field_data);
}
/**
diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php
index 90ac9a6703..414484920b 100644
--- a/phpBB/phpbb/profilefields/type/type_date.php
+++ b/phpBB/phpbb/profilefields/type/type_date.php
@@ -72,7 +72,7 @@ class type_date extends type_base
'lang_options' => $field_data['lang_options'],
);
- $always_now = request_var('always_now', -1);
+ $always_now = $request->variable('always_now', -1);
if ($always_now == -1)
{
$s_checked = ($field_data['field_default_value'] == 'now') ? true : false;
diff --git a/phpBB/phpbb/request/deactivated_super_global.php b/phpBB/phpbb/request/deactivated_super_global.php
index b6cad59be4..ab56240b14 100644
--- a/phpBB/phpbb/request/deactivated_super_global.php
+++ b/phpBB/phpbb/request/deactivated_super_global.php
@@ -56,7 +56,7 @@ class deactivated_super_global implements \ArrayAccess, \Countable, \IteratorAgg
$file = '';
$line = 0;
- $message = 'Illegal use of $' . $this->name . '. You must use the request class or request_var() to access input data. Found in %s on line %d. This error message was generated by deactivated_super_global.';
+ $message = 'Illegal use of $' . $this->name . '. You must use the request class to access input data. Found in %s on line %d. This error message was generated by deactivated_super_global.';
$backtrace = debug_backtrace();
if (isset($backtrace[1]))
diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php
index 601d774129..4ccd3cf5e3 100644
--- a/phpBB/phpbb/routing/router.php
+++ b/phpBB/phpbb/routing/router.php
@@ -13,6 +13,7 @@
namespace phpbb\routing;
+use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper;
use Symfony\Component\Routing\Matcher\UrlMatcher;
@@ -232,14 +233,7 @@ class router implements RouterInterface
return $this->matcher;
}
- if (defined('DEBUG'))
- {
- $this->create_new_url_matcher();
- }
- else
- {
- $this->create_dumped_url_matcher();
- }
+ $this->create_dumped_url_matcher();
return $this->matcher;
}
@@ -248,21 +242,22 @@ class router implements RouterInterface
*/
protected function create_dumped_url_matcher()
{
- if (!file_exists($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext))
+ $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_matcher.{$this->php_ext}", defined('DEBUG'));
+ if (!$cache->isFresh())
{
$dumper = new PhpMatcherDumper($this->get_routes());
$options = array(
- 'class' => 'phpbb_url_matcher',
+ 'class' => 'phpbb_url_matcher',
+ 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
);
- $dump = $dumper->dump($options);
- file_put_contents($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext, $dump);
+ $cache->write($dumper->dump($options), $this->get_routes()->getResources());
}
- require_once($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext);
+ require_once($cache);
- $this->matcher = new phpbb_url_matcher($this->context);
+ $this->matcher = new \phpbb_url_matcher($this->context);
}
/**
@@ -285,14 +280,7 @@ class router implements RouterInterface
return $this->generator;
}
- if (defined('DEBUG'))
- {
- $this->create_new_url_generator();
- }
- else
- {
- $this->create_dumped_url_generator();
- }
+ $this->create_dumped_url_generator();
return $this->generator;
}
@@ -302,21 +290,22 @@ class router implements RouterInterface
*/
protected function create_dumped_url_generator()
{
- if (!file_exists($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext))
+ $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_generator.{$this->php_ext}", defined('DEBUG'));
+ if (!$cache->isFresh())
{
$dumper = new PhpGeneratorDumper($this->get_routes());
$options = array(
- 'class' => 'phpbb_url_generator',
+ 'class' => 'phpbb_url_generator',
+ 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
);
- $dump = $dumper->dump($options);
- file_put_contents($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext, $dump);
+ $cache->write($dumper->dump($options), $this->get_routes()->getResources());
}
- require_once($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext);
+ require_once($cache);
- $this->generator = new phpbb_url_generator($this->context);
+ $this->generator = new \phpbb_url_generator($this->context);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index 1a0aba096f..da9de56009 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -188,8 +188,8 @@ class fulltext_mysql extends \phpbb\search\base
}
$this->db->sql_freeresult($result);
- set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
- set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
+ $this->config->set('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
+ $this->config->set('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
return false;
}
@@ -745,7 +745,7 @@ class fulltext_mysql extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index ea239c0b36..b18015ba1a 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -303,7 +303,7 @@ class fulltext_native extends \phpbb\search\base
$this->search_query = $keywords;
$exact_words = array();
- preg_match_all('#([^\\s+\\-|*()]+)(?:$|[\\s+\\-|()])#u', $keywords, $exact_words);
+ preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $exact_words);
$exact_words = $exact_words[1];
$common_ids = $words = array();
@@ -437,7 +437,7 @@ class fulltext_native extends \phpbb\search\base
// throw an error if we shall not ignore unexistant words
else if (!$ignore_no_id && sizeof($non_common_words))
{
- trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], implode($user->lang['COMMA_SEPARATOR'], $non_common_words)));
+ trigger_error(sprintf($this->user->lang['WORDS_IN_NO_POST'], implode($this->user->lang['COMMA_SEPARATOR'], $non_common_words)));
}
unset($non_common_words);
}
@@ -1425,7 +1425,7 @@ class fulltext_native extends \phpbb\search\base
// carry on ... it's okay ... I know when I'm not wanted boo hoo
if (!$this->config['fulltext_native_load_upd'])
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
return;
}
@@ -1460,7 +1460,7 @@ class fulltext_native extends \phpbb\search\base
// by setting search_last_gc to the new time here we make sure that if a user reloads because the
// following query takes too long, he won't run into it again
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
// Delete the matches
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
@@ -1476,7 +1476,7 @@ class fulltext_native extends \phpbb\search\base
$this->destroy_cache(array_unique($destroy_cache_words));
}
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php
index b6af371d13..5a68f0cbfb 100644
--- a/phpBB/phpbb/search/fulltext_postgres.php
+++ b/phpBB/phpbb/search/fulltext_postgres.php
@@ -746,7 +746,7 @@ class fulltext_postgres extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php
index 2765d05b94..a5ad96b114 100644
--- a/phpBB/phpbb/search/fulltext_sphinx.php
+++ b/phpBB/phpbb/search/fulltext_sphinx.php
@@ -136,11 +136,12 @@ class fulltext_sphinx
$this->auth = $auth;
// Initialize \phpbb\db\tools\tools object
- $this->db_tools = new \phpbb\db\tools\tools($this->db);
+ global $phpbb_container; // TODO inject into object
+ $this->db_tools = $phpbb_container->get('dbal.tools');
if(!$this->config['fulltext_sphinx_id'])
{
- set_config('fulltext_sphinx_id', unique_id());
+ $this->config->set('fulltext_sphinx_id', unique_id());
}
$this->id = $this->config['fulltext_sphinx_id'];
$this->indexes = 'index_phpbb_' . $this->id . '_delta;index_phpbb_' . $this->id . '_main';
@@ -211,7 +212,7 @@ class fulltext_sphinx
}
// Move delta to main index each hour
- set_config('search_gc', 3600);
+ $this->config->set('search_gc', 3600);
return false;
}
@@ -454,6 +455,8 @@ class fulltext_sphinx
*/
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
+ global $user, $phpbb_log;
+
// No keywords? No posts.
if (!strlen($this->search_query) && !sizeof($author_ary))
{
@@ -601,7 +604,7 @@ class fulltext_sphinx
if ($this->sphinx->GetLastError())
{
- add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError());
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_SPHINX_ERROR', false, array($this->sphinx->GetLastError()));
if ($this->auth->acl_get('a_'))
{
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError()));
@@ -755,7 +758,7 @@ class fulltext_sphinx
*/
public function tidy($create = false)
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index 5b9fb6d835..6aeb8a91de 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -139,7 +139,7 @@ class session
'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)),
'page' => $page,
- 'forum' => request_var('f', 0),
+ 'forum' => $request->variable('f', 0),
);
return $page_array;
@@ -215,7 +215,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, $user, $phpbb_log;
// Give us some basic information
$this->time_now = time();
@@ -253,23 +253,23 @@ class session
if ($request->is_set($config['cookie_name'] . '_sid', \phpbb\request\request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u', \phpbb\request\request_interface::COOKIE))
{
- $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
- $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
- $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true);
+ $this->cookie_data['u'] = $request->variable($config['cookie_name'] . '_u', 0, false, \phpbb\request\request_interface::COOKIE);
+ $this->cookie_data['k'] = $request->variable($config['cookie_name'] . '_k', '', false, \phpbb\request\request_interface::COOKIE);
+ $this->session_id = $request->variable($config['cookie_name'] . '_sid', '', false, \phpbb\request\request_interface::COOKIE);
$SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
$_SID = (defined('NEED_SID')) ? $this->session_id : '';
if (empty($this->session_id))
{
- $this->session_id = $_SID = request_var('sid', '');
+ $this->session_id = $_SID = $request->variable('sid', '');
$SID = '?sid=' . $this->session_id;
$this->cookie_data = array('u' => 0, 'k' => '');
}
}
else
{
- $this->session_id = $_SID = request_var('sid', '');
+ $this->session_id = $_SID = $request->variable('sid', '');
$SID = '?sid=' . $this->session_id;
}
@@ -345,8 +345,8 @@ class session
}
else
{
- set_config('limit_load', '0');
- set_config('limit_search_load', '0');
+ $config->set('limit_load', '0');
+ $config->set('limit_search_load', '0');
}
}
@@ -490,11 +490,18 @@ class session
{
if ($referer_valid)
{
- add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for));
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IP_BROWSER_FORWARDED_CHECK', false, array(
+ $u_ip,
+ $s_ip,
+ $u_browser,
+ $s_browser,
+ htmlspecialchars($u_forwarded_for),
+ htmlspecialchars($s_forwarded_for)
+ ));
}
else
{
- add_log('critical', 'LOG_REFERER_INVALID', $this->referer);
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_REFERER_INVALID', false, array($this->referer));
}
}
}
@@ -1029,7 +1036,7 @@ class session
{
// Less than 10 users, update gc timer ... else we want gc
// called again to delete other sessions
- set_config('session_last_gc', $this->time_now, true);
+ $config->set('session_last_gc', $this->time_now, false);
if ($config['max_autologin_time'])
{
diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php
index 67dbd7b357..4729685459 100644
--- a/phpBB/phpbb/template/asset.php
+++ b/phpBB/phpbb/template/asset.php
@@ -152,6 +152,12 @@ class asset
*/
public function set_path($path, $urlencode = false)
{
+ // Since 1.7.0 Twig returns the real path of the file. We need it to be relative to the working directory.
+ $real_root_path = realpath('.') . DIRECTORY_SEPARATOR;
+ if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) {
+ $path = str_replace('\\', '/', substr($path, strlen($real_root_path)));
+ }
+
if ($urlencode)
{
$paths = explode('/', $path);
@@ -161,6 +167,7 @@ class asset
}
$path = implode('/', $paths);
}
+
$this->components['path'] = $path;
}
diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php
index 3a983491b9..14d1258c09 100644
--- a/phpBB/phpbb/template/twig/extension.php
+++ b/phpBB/phpbb/template/twig/extension.php
@@ -71,6 +71,7 @@ class extension extends \Twig_Extension
{
return array(
new \Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)),
+ // @deprecated 3.2.0 Uses twig's JS escape method instead of addslashes
new \Twig_SimpleFilter('addslashes', 'addslashes'),
);
}
@@ -177,7 +178,7 @@ class extension extends \Twig_Extension
return $context_vars['L_' . $key];
}
- // LA_ is transformed into lang(\'$1\')|addslashes, so we should not
+ // LA_ is transformed into lang(\'$1\')|escape('js'), so we should not
// need to check for it
return call_user_func_array(array($this->user, 'lang'), $args);
diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php
index a7848738bb..f1542109a4 100644
--- a/phpBB/phpbb/template/twig/lexer.php
+++ b/phpBB/phpbb/template/twig/lexer.php
@@ -117,9 +117,9 @@ class lexer extends \Twig_Lexer
// Appends any filters after lang()
$code = preg_replace('#{L_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2 }}', $code);
- // Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|addslashes }}
- // Appends any filters after lang(), but before addslashes
- $code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|addslashes }}', $code);
+ // Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|escape('js') }}
+ // Appends any filters after lang(), but before escape('js')
+ $code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|escape(\'js\') }}', $code);
// Replace all of our variables, {VARNAME}, with Twig style, {{ VARNAME }}
// Appends any filters
diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php
index 4962d14aef..605d37e954 100644
--- a/phpBB/phpbb/template/twig/twig.php
+++ b/phpBB/phpbb/template/twig/twig.php
@@ -261,19 +261,19 @@ class twig extends \phpbb\template\base
$ext_style_theme_path = $ext_style_path . 'theme/';
}
- $ok = false;
+ $is_valid_dir = false;
if (is_dir($ext_style_template_path))
{
- $ok = true;
+ $is_valid_dir = true;
$paths[] = $ext_style_template_path;
}
if (is_dir($ext_style_theme_path))
{
- $ok = true;
+ $is_valid_dir = true;
$paths[] = $ext_style_theme_path;
}
- if ($ok)
+ if ($is_valid_dir)
{
// Add the base style directory as a safe directory
$this->twig->getLoader()->addSafeDirectory($ext_style_path);
diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php
index dc62f06fb2..e4f68f5aab 100644
--- a/phpBB/phpbb/version_helper.php
+++ b/phpBB/phpbb/version_helper.php
@@ -257,9 +257,10 @@ class version_helper
try {
$info = $this->file_downloader->get($this->host, $this->path, $this->file);
}
- catch (\RuntimeException $exception)
+ catch (\phpbb\exception\runtime_exception $exception)
{
- throw new \RuntimeException($this->user->lang($exception->getMessage()));
+ $prepare_parameters = array_merge(array($exception->getMessage()), $exception->get_parameters());
+ throw new \RuntimeException(call_user_func_array(array($this->user, 'lang'), $prepare_parameters));
}
$error_string = $this->file_downloader->get_error_string();