diff options
Diffstat (limited to 'phpBB/phpbb/db')
26 files changed, 717 insertions, 123 deletions
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 3e9110d8bc..9fc04d47a1 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -372,6 +372,17 @@ abstract class driver implements driver_interface /** * {@inheritDoc} */ + function sql_not_like_expression($expression) + { + $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + + return $this->_sql_not_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\''); + } + + /** + * {@inheritDoc} + */ public function sql_case($condition, $action_true, $action_false = false) { $sql_case = 'CASE WHEN ' . $condition; diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 6722d059a5..8b487c5d42 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -419,6 +419,16 @@ interface driver_interface public function sql_like_expression($expression); /** + * Correctly adjust NOT LIKE expression for special characters + * Some DBMS are handling them in a different way + * + * @param string $expression The expression to use. Every wildcard is + * escaped, except $this->any_char and $this->one_char + * @return string A SQL statement like: "NOT LIKE 'bertie_%'" + */ + public function sql_not_like_expression($expression); + + /** * Explain queries * * @param string $mode Available modes: display, start, stop, diff --git a/phpBB/phpbb/db/driver/factory.php b/phpBB/phpbb/db/driver/factory.php index f0fa18051b..fb3a826254 100644 --- a/phpBB/phpbb/db/driver/factory.php +++ b/phpBB/phpbb/db/driver/factory.php @@ -420,6 +420,14 @@ class factory implements driver_interface /** * {@inheritdoc} */ + public function sql_not_like_expression($expression) + { + return $this->get_driver()->sql_not_like_expression($expression); + } + + /** + * {@inheritdoc} + */ public function sql_report($mode, $query = '') { return $this->get_driver()->sql_report($mode, $query); diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 268463a151..f9ea884ce2 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -351,6 +351,15 @@ class mssql extends \phpbb\db\driver\driver } /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** * return sql error array * @access private */ diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index e7101903b8..514df9eaca 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -52,6 +52,15 @@ abstract class mssql_base extends \phpbb\db\driver\driver } /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** * Build db-specific query data * @access private */ diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index e7c9b63f20..5e0b359134 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -112,6 +112,15 @@ abstract class mysql_base extends \phpbb\db\driver\driver } /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression; + } + + /** * Build db-specific query data * @access private */ diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index d1a186f1ba..6dcab5dd7d 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -645,6 +645,15 @@ class oracle extends \phpbb\db\driver\driver return $expression . " ESCAPE '\\'"; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + function _sql_custom_build($stage, $data) { return $data; diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 83e9fa51f6..a3b9aa4c6b 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -371,6 +371,15 @@ class postgres extends \phpbb\db\driver\driver } /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression; + } + + /** * {@inheritDoc} */ function cast_expr_to_bigint($expression) diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 2112e5ba2f..d5da0e2438 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -277,7 +277,7 @@ class sqlite extends \phpbb\db\driver\driver */ function sql_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike LIKE, GLOB is unfortunately case sensitive. // We only catch * and ? here, not the character map possible on file globbing. $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); @@ -288,6 +288,23 @@ class sqlite extends \phpbb\db\driver\driver } /** + * {@inheritDoc} + * + * For SQLite an underscore is a not-known character... + */ + function sql_not_like_expression($expression) + { + // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive. + // We only catch * and ? here, not the character map possible on file globbing. + $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); + + $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression); + $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression); + + return 'NOT GLOB \'' . $this->sql_escape($expression) . '\''; + } + + /** * return sql error array * @access private */ diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 0922229e0a..4e3e0d3329 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -260,11 +260,11 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} * - * For SQLite an underscore is a not-known character... + * For SQLite an underscore is an unknown character. */ public function sql_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike LIKE, GLOB is unfortunately case sensitive. // We only catch * and ? here, not the character map possible on file globbing. $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); @@ -275,6 +275,23 @@ class sqlite3 extends \phpbb\db\driver\driver } /** + * {@inheritDoc} + * + * For SQLite an underscore is an unknown character. + */ + public function sql_not_like_expression($expression) + { + // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive + // We only catch * and ? here, not the character map possible on file globbing. + $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); + + $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression); + $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression); + + return 'NOT GLOB \'' . $this->sql_escape($expression) . '\''; + } + + /** * return sql error array * * @return array diff --git a/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php b/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php new file mode 100644 index 0000000000..13071e9891 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php @@ -0,0 +1,44 @@ +<?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\v310; + +class captcha_plugins extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\rc2', + ); + } + + public function update_data() + { + $captcha_plugin = $this->config['captcha_plugin']; + if (strpos($this->config['captcha_plugin'], 'phpbb_captcha_') === 0) + { + $captcha_plugin = substr($this->config['captcha_plugin'], strlen('phpbb_captcha_')); + } + + return array( + array('if', array( + (is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)), + array('config.update', array('captcha_plugin', 'core.captcha.plugins.' . $captcha_plugin)), + )), + array('if', array( + (!is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)), + array('config.update', array('captcha_plugin', 'core.captcha.plugins.nogd')), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/notifications_use_full_name.php b/phpBB/phpbb/db/migration/data/v310/notifications_use_full_name.php new file mode 100644 index 0000000000..f749b32119 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/notifications_use_full_name.php @@ -0,0 +1,122 @@ +<?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\v310; + +class notifications_use_full_name extends \phpbb\db\migration\migration +{ + protected $notification_types = array( + 'admin_activate_user', + 'approve_post', + 'approve_topic', + 'bookmark', + 'disapprove_post', + 'disapprove_topic', + 'group_request', + 'group_request_approved', + 'pm', + 'post', + 'post_in_queue', + 'quote', + 'report_pm', + 'report_pm_closed', + 'report_post', + 'report_post_closed', + 'topic', + 'topic_in_queue'); + + protected $notification_methods = array( + 'email', + 'jabber', + ); + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\rc3'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_notifications_name'))), + array('custom', array(array($this, 'update_notifications_method_name'))), + ); + } + + public function revert_data() + { + return array( + array('custom', array(array($this, 'revert_notifications_name'))), + array('custom', array(array($this, 'revert_notifications_method_name'))), + ); + } + + public function update_notifications_method_name() + { + foreach ($this->notification_methods as $notification_method) + { + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET method = 'notification.method.{$notification_method}' + WHERE method = '{$notification_method}'"; + $this->db->sql_query($sql); + } + } + + public function revert_notifications_method_name() + { + foreach ($this->notification_methods as $notification_method) + { + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET method = '{$notification_method}' + WHERE method = 'notification.method.{$notification_method}'"; + $this->db->sql_query($sql); + } + } + + public function update_notifications_name() + { + $sql = 'UPDATE ' . NOTIFICATION_TYPES_TABLE . ' + SET notification_type_enabled = 0 + WHERE ' . $this->db->sql_in_set('notification_type_name', $this->notification_types, true); + $this->db->sql_query($sql); + + foreach ($this->notification_types as $notification_type) + { + $sql = 'UPDATE ' . NOTIFICATION_TYPES_TABLE . " + SET notification_type_name = 'notification.type.{$notification_type}' + WHERE notification_type_name = '{$notification_type}'"; + $this->db->sql_query($sql); + + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET item_type = 'notification.type.{$notification_type}' + WHERE item_type = '{$notification_type}'"; + $this->db->sql_query($sql); + } + } + + public function revert_notifications_name() + { + foreach ($this->notification_types as $notification_type) + { + $sql = 'UPDATE ' . NOTIFICATION_TYPES_TABLE . " + SET notification_type_name = '{$notification_type}' + WHERE notification_type_name = 'notification.type.{$notification_type}'"; + $this->db->sql_query($sql); + + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET item_type = '{$notification_type}' + WHERE item_type = 'notification.type.{$notification_type}'"; + $this->db->sql_query($sql); + } + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_facebook.php b/phpBB/phpbb/db/migration/data/v310/profilefield_facebook.php index 5964e7a997..7324b893cc 100644 --- a/phpBB/phpbb/db/migration/data/v310/profilefield_facebook.php +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_facebook.php @@ -18,8 +18,9 @@ class profilefield_facebook extends \phpbb\db\migration\profilefield_base_migrat static public function depends_on() { return array( - '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_contact_field', '\phpbb\db\migration\data\v310\profilefield_show_novalue', + '\phpbb\db\migration\data\v310\profilefield_types', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php b/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php index 9bef0a4c0b..3b0963fc19 100644 --- a/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php @@ -18,8 +18,9 @@ class profilefield_googleplus extends \phpbb\db\migration\profilefield_base_migr static public function depends_on() { return array( - '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_contact_field', '\phpbb\db\migration\data\v310\profilefield_show_novalue', + '\phpbb\db\migration\data\v310\profilefield_types', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_skype.php b/phpBB/phpbb/db/migration/data/v310/profilefield_skype.php index 9a5de9d0eb..0dbe9041bb 100644 --- a/phpBB/phpbb/db/migration/data/v310/profilefield_skype.php +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_skype.php @@ -18,8 +18,9 @@ class profilefield_skype extends \phpbb\db\migration\profilefield_base_migration static public function depends_on() { return array( - '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_contact_field', '\phpbb\db\migration\data\v310\profilefield_show_novalue', + '\phpbb\db\migration\data\v310\profilefield_types', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_twitter.php b/phpBB/phpbb/db/migration/data/v310/profilefield_twitter.php index 68d038f609..850e096439 100644 --- a/phpBB/phpbb/db/migration/data/v310/profilefield_twitter.php +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_twitter.php @@ -18,8 +18,9 @@ class profilefield_twitter extends \phpbb\db\migration\profilefield_base_migrati static public function depends_on() { return array( - '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_contact_field', '\phpbb\db\migration\data\v310\profilefield_show_novalue', + '\phpbb\db\migration\data\v310\profilefield_types', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_youtube.php b/phpBB/phpbb/db/migration/data/v310/profilefield_youtube.php index bb90c0aa5c..40a569d2a2 100644 --- a/phpBB/phpbb/db/migration/data/v310/profilefield_youtube.php +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_youtube.php @@ -18,8 +18,9 @@ class profilefield_youtube extends \phpbb\db\migration\profilefield_base_migrati static public function depends_on() { return array( - '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_contact_field', '\phpbb\db\migration\data\v310\profilefield_show_novalue', + '\phpbb\db\migration\data\v310\profilefield_types', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/rc3.php b/phpBB/phpbb/db/migration/data/v310/rc3.php new file mode 100644 index 0000000000..0e6a452251 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/rc3.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\v310; + +class rc3 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\rc2', + '\phpbb\db\migration\data\v310\captcha_plugins', + '\phpbb\db\migration\data\v310\rename_too_long_indexes', + '\phpbb\db\migration\data\v310\search_type', + '\phpbb\db\migration\data\v310\topic_sort_username', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-RC3')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/rc4.php b/phpBB/phpbb/db/migration/data/v310/rc4.php new file mode 100644 index 0000000000..47de8291c1 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/rc4.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\v310; + +class rc4 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\rc3', + '\phpbb\db\migration\data\v310\notifications_use_full_name', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-RC4')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/rename_too_long_indexes.php b/phpBB/phpbb/db/migration/data/v310/rename_too_long_indexes.php new file mode 100644 index 0000000000..8d2a15d8ea --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/rename_too_long_indexes.php @@ -0,0 +1,38 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class rename_too_long_indexes extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_0'); + } + + public function update_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'search_wordmatch' => array( + 'unq_mtch', + ), + ), + 'add_unique_index' => array( + $this->table_prefix . 'search_wordmatch' => array( + 'un_mtch' => array('word_id', 'post_id', 'title_match'), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/search_type.php b/phpBB/phpbb/db/migration/data/v310/search_type.php new file mode 100644 index 0000000000..f89456ae19 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/search_type.php @@ -0,0 +1,34 @@ +<?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\v310; + +class search_type extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_data() + { + return array( + array('if', array( + (is_file($this->phpbb_root_path . 'phpbb/search/' . $this->config['search_type'] . $this->php_ext)), + array('config.update', array('search_type', '\\phpbb\\search\\' . $this->config['search_type'])), + )), + ); + } +} 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 f5970e74b2..58845b88ec 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 @@ -119,8 +119,9 @@ class soft_delete_mod_convert extends \phpbb\db\migration\migration { return new \phpbb\content_visibility( new \phpbb\auth\auth(), + $this->config, $this->db, - new \phpbb\user(), + new \phpbb\user('\phpbb\datetime'), $this->phpbb_root_path, $this->php_ext, $this->table_prefix . 'forums', diff --git a/phpBB/phpbb/db/migration/data/v310/topic_sort_username.php b/phpBB/phpbb/db/migration/data/v310/topic_sort_username.php new file mode 100644 index 0000000000..527da20590 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/topic_sort_username.php @@ -0,0 +1,44 @@ +<?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\v310; + +class topic_sort_username extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\dev'); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'topics' => array( + 'topic_first_poster_name' => array('VCHAR_UNI:255', '', 'true_sort'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'topics' => array( + 'topic_first_poster_name' => array('VCHAR_UNI:255', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php index d2df27613a..5cfbc5ca00 100644 --- a/phpBB/phpbb/db/migration/tool/permission.php +++ b/phpBB/phpbb/db/migration/tool/permission.php @@ -105,6 +105,7 @@ class permission implements \phpbb\db\migration\tool\tool_interface * @param string $auth_option The name of the permission (auth) option * @param bool $global True for checking a global permission setting, * False for a local permission setting + * @param int|false $copy_from If set, contains the id of the permission from which to copy the new one. * @return null */ public function add($auth_option, $global = true, $copy_from = false) @@ -243,7 +244,9 @@ class permission implements \phpbb\db\migration\tool\tool_interface * Add a new permission role * * @param string $role_name The new role name - * @param sting $role_type The type (u_, m_, a_) + * @param string $role_type The type (u_, m_, a_) + * @param string $role_description Description of the new role + * * @return null */ public function role_add($role_name, $role_type, $role_description = '') diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index 8b089a060f..44bea3c5d2 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -715,56 +715,26 @@ class migrator } /** - * Load migration data files from a directory - * - * @param \phpbb\finder $finder - * @param string $path Path to migration data files - * @param bool $check_fulfillable If TRUE (default), we will check - * if all of the migrations are fulfillable after loading them. - * If FALSE, we will not check. You SHOULD check at least once - * to prevent errors (if including multiple directories, check - * with the last call to prevent throwing errors unnecessarily). - * @return array Array of migration names - * @throws \phpbb\db\migration\exception + * Creates the migrations table if it does not exist. + * @return null */ - public function load_migrations(\phpbb\finder $finder, $path, $check_fulfillable = true) + public function create_migrations_table() { - if (!is_dir($path)) - { - throw new \phpbb\db\migration\exception('DIRECTORY INVALID', $path); - } - - $migrations = array(); - - $files = $finder - ->extension_directory("/") - ->find_from_paths(array('/' => $path)); - foreach ($files as $file) - { - $migrations[$file['path'] . $file['filename']] = ''; - } - $migrations = $finder->get_classes_from_files($migrations); - - foreach ($migrations as $migration) + // Make sure migrations have been installed. + if (!$this->db_tools->sql_table_exists($this->table_prefix . 'migrations')) { - if (!in_array($migration, $this->migrations)) - { - $this->migrations[] = $migration; - } - } - - if ($check_fulfillable) - { - foreach ($this->migrations as $name) - { - $unfulfillable = $this->unfulfillable($name); - if ($unfulfillable !== false) - { - throw new \phpbb\db\migration\exception('MIGRATION_NOT_FULFILLABLE', $name, $unfulfillable); - } - } + $this->db_tools->sql_create_table($this->table_prefix . 'migrations', array( + 'COLUMNS' => array( + 'migration_name' => array('VCHAR', ''), + 'migration_depends_on' => array('TEXT', ''), + 'migration_schema_done' => array('BOOL', 0), + 'migration_data_done' => array('BOOL', 0), + 'migration_data_state' => array('TEXT', ''), + 'migration_start_time' => array('TIMESTAMP', 0), + 'migration_end_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'migration_name', + )); } - - return $this->migrations; } } diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index 18defc4535..3567570137 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -1487,8 +1487,16 @@ class tools $return_array['textimage'] = $column_type === '[text]'; - $sql .= 'NOT NULL'; - $sql_default .= 'NOT NULL'; + 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; @@ -1503,7 +1511,15 @@ class tools { $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; } - $sql .= 'NOT NULL'; + + if (!is_null($column_data[1])) + { + $sql .= 'NOT NULL'; + } + else + { + $sql .= 'NULL'; + } if (isset($column_data[2])) { @@ -1528,7 +1544,7 @@ class tools // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) if (!preg_match('/number/i', $column_type)) { - $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; + $sql .= ($column_data[1] === '' || $column_data[1] === null) ? '' : 'NOT NULL'; } $return_array['auto_increment'] = false; @@ -1556,6 +1572,12 @@ class tools $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; @@ -1588,8 +1610,11 @@ class tools $sql .= ' ' . $column_type; } - $sql .= ' NOT NULL '; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; + if (!is_null($column_data[1])) + { + $sql .= ' NOT NULL '; + $sql .= "DEFAULT '{$column_data[1]}'"; + } break; } @@ -1791,7 +1816,8 @@ class tools $old_return_statements = $this->return_statements; $this->return_statements = true; - $indexes = $this->mssql_get_existing_indexes($table_name, $column_name); + $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(); @@ -2013,7 +2039,7 @@ class tools break; case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; + $statements[] = 'ALTER TABLE ' . $table_name . ' add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; break; case 'sqlite': @@ -2079,7 +2105,7 @@ class tools $statements = array(); $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - if (strlen($table_name . $index_name) - strlen($table_prefix) > 24) + 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); @@ -2249,10 +2275,23 @@ class tools } /** + * Removes table_name from the index_name if it is at the beginning + * + * @param $table_name + * @param $index_name + * @return string + */ + protected function strip_table_name_from_index_name($table_name, $index_name) + { + return (strpos(strtoupper($index_name), strtoupper($table_name)) === 0) ? substr($index_name, strlen($table_name) + 1) : $index_name; + } + + /** * Change column type (not name!) */ function sql_column_change($table_name, $column_name, $column_data, $inline = false) { + $original_column_data = $column_data; $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); $statements = array(); @@ -2264,12 +2303,14 @@ class tools $old_return_statements = $this->return_statements; $this->return_statements = true; - $indexes = $this->mssql_get_existing_indexes($table_name, $column_name); + $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)) + if (!empty($indexes) || !empty($unique_indexes)) { - foreach ($indexes as $index_name => $index_data) + $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); @@ -2299,6 +2340,16 @@ class tools } } + 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; @@ -2308,7 +2359,69 @@ class tools break; case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql']; + // We need the data here + $old_return_statements = $this->return_statements; + $this->return_statements = true; + + // Get list of existing indexes + $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, $this->strip_table_name_from_index_name($table_name, $index_name)); + $statements = array_merge($statements, $result); + } + } + + $temp_column_name = 'temp_' . substr(md5($column_name), 0, 25); + // Add a temporary table with the new type + $result = $this->sql_column_add($table_name, $temp_column_name, $original_column_data); + $statements = array_merge($statements, $result); + + // Copy the data to the new column + $statements[] = 'UPDATE ' . $table_name . ' SET ' . $temp_column_name . ' = ' . $column_name; + + // Drop the original column + $result = $this->sql_column_remove($table_name, $column_name); + $statements = array_merge($statements, $result); + + // Recreate the original column with the new type + $result = $this->sql_column_add($table_name, $column_name, $original_column_data); + $statements = array_merge($statements, $result); + + if (!empty($indexes)) + { + // Recreate indexes after we changed the column + foreach ($indexes as $index_name => $index_data) + { + $result = $this->sql_create_index($table_name, $this->strip_table_name_from_index_name($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, $this->strip_table_name_from_index_name($table_name, $index_name), $index_data); + $statements = array_merge($statements, $result); + } + } + + // Copy the data to the original column + $statements[] = 'UPDATE ' . $table_name . ' SET ' . $column_name . ' = ' . $temp_column_name; + + // Drop the temporary column again + $result = $this->sql_column_remove($table_name, $temp_column_name); + $statements = array_merge($statements, $result); + + $this->return_statements = $old_return_statements; break; case 'postgres': @@ -2492,45 +2605,78 @@ class tools * * @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 */ - protected function mssql_get_existing_indexes($table_name, $column_name) + public function get_existing_indexes($table_name, $column_name, $unique = false) { - $existing_indexes = array(); - if ($this->mssql_is_sql_server_2000()) + switch ($this->sql_layer) { - // 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}'"; + case 'mysql_40': + case 'mysql_41': + case 'postgres': + case 'sqlite': + case 'sqlite3': + // Not supported + throw new \Exception('DBMS is not supported'); + break; } - else + + $sql = ''; + $existing_indexes = array(); + + switch ($this->sql_layer) { - $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}'"; + 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 + WHERE ix.index_name = ixc.index_name + AND ixc.table_name = '" . strtoupper($table_name) . "' + AND ixc.column_name = '" . strtoupper($column_name) . "'"; + break; } $result = $this->db->sql_query($sql); - $existing_indexes = array(); while ($row = $this->db->sql_fetchrow($result)) { - $existing_indexes[$row['phpbb_index_name']] = array(); + 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); @@ -2539,35 +2685,47 @@ class tools 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 + switch ($this->sql_layer) { - $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)); + 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 + WHERE table_name = '" . strtoupper($table_name) . "' + AND " . $this->db->sql_in_set('index_name', array_keys($existing_indexes)); + break; } $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) { $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name']; |