diff options
Diffstat (limited to 'phpBB/includes/db')
71 files changed, 6711 insertions, 487 deletions
| diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index f63ff18cbe..983cdc18ea 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -21,7 +20,6 @@ if (!defined('IN_PHPBB'))  * Currently not supported is returning SQL for creating tables.  *  * @package dbal -* @note currently not used within phpBB3, but may be utilized later.  */  class phpbb_db_tools  { @@ -302,10 +300,10 @@ class phpbb_db_tools  	/**  	* Constructor. Set DB Object and set {@link $return_statements return_statements}.  	* -	* @param phpbb_dbal	$db					DBAL object +	* @param phpbb_db_driver	$db					Database connection  	* @param bool		$return_statements	True if only statements should be returned and no SQL being executed  	*/ -	function phpbb_db_tools(&$db, $return_statements = false) +	function phpbb_db_tools(phpbb_db_driver $db, $return_statements = false)  	{  		$this->db = $db;  		$this->return_statements = $return_statements; @@ -348,6 +346,17 @@ class phpbb_db_tools  	}  	/** +	* Setter for {@link $return_statements return_statements}. +	* +	* @param bool $return_statements True if SQL should not be executed but returned as strings +	* @return null +	*/ +	public function set_return_statements($return_statements) +	{ +		$this->return_statements = $return_statements; +	} + +	/**  	* Gets a list of tables in the database.  	*  	* @return array		Array of table names  (all lower case) @@ -676,6 +685,8 @@ class phpbb_db_tools  	* Handle passed database update array.  	* Expected structure...  	* Key being one of the following +	*	drop_tables: Drop tables +	*	add_tables: Add tables  	*	change_columns: Column changes (only type, not name)  	*	add_columns: Add columns to a table  	*	drop_keys: Dropping keys @@ -1504,7 +1515,7 @@ class phpbb_db_tools  			$column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]];  		} -		// Adjust default value if db-dependant specified +		// 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']; @@ -2473,5 +2484,3 @@ class phpbb_db_tools  		return $this->_sql_run_sql($statements);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/driver/driver.php index 9cc337955b..b915ee081b 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/driver/driver.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -20,7 +19,7 @@ if (!defined('IN_PHPBB'))  * Database Abstraction Layer  * @package dbal  */ -class dbal +class phpbb_db_driver  {  	var $db_connect_id;  	var $query_result; @@ -73,17 +72,17 @@ class dbal  	/**  	* Constructor  	*/ -	function dbal() +	function __construct()  	{  		$this->num_queries = array( -			'cached'		=> 0, -			'normal'		=> 0, -			'total'			=> 0, +			'cached'	=> 0, +			'normal'	=> 0, +			'total'		=> 0,  		);  		// Fill default sql layer based on the class being called.  		// This can be changed by the specified layer itself later if needed. -		$this->sql_layer = substr(get_class($this), 5); +		$this->sql_layer = substr(get_class($this), strlen('phpbb_db_driver_'));  		// Do not change this please! This variable is used to easy the use of it - and is hardcoded.  		$this->any_char = chr(0) . '%'; @@ -207,7 +206,7 @@ class dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -257,7 +256,7 @@ class dbal  				$this->sql_rowseek($rownum, $query_id);  			} -			if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) +			if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))  			{  				return $cache->sql_fetchfield($query_id, $field);  			} @@ -285,6 +284,37 @@ class dbal  	}  	/** +	* Build a case expression +	* +	* Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database! +	* +	* @param	string	$condition		The condition which must be true, to use action_true rather then action_else +	* @param	string	$action_true	SQL expression that is used, if the condition is true +	* @param	string	$action_else	SQL expression that is used, if the condition is false, optional +	* @return	string			CASE expression including the condition and statements +	*/ +	public function sql_case($condition, $action_true, $action_false = false) +	{ +		$sql_case = 'CASE WHEN ' . $condition; +		$sql_case .= ' THEN ' . $action_true; +		$sql_case .= ($action_false !== false) ? ' ELSE ' . $action_false : ''; +		$sql_case .= ' END'; +		return $sql_case; +	} + +	/** +	* Build a concatenated expression +	* +	* @param	string	$expr1		Base SQL expression where we append the second one +	* @param	string	$expr2		SQL expression that is appended to the first expression +	* @return	string		Concatenated string +	*/ +	public function sql_concatenate($expr1, $expr2) +	{ +		return $expr1 . ' || ' . $expr2; +	} + +	/**  	* Returns whether results of a query need to be buffered to run a transaction while iterating over them.  	*  	* @return bool Whether buffering is required. @@ -501,6 +531,28 @@ class dbal  	}  	/** +	* Returns SQL string to cast a string expression to an int. +	* +	* @param  string $expression An expression evaluating to string +	* @return string             Expression returning an int +	*/ +	function cast_expr_to_bigint($expression) +	{ +		return $expression; +	} + +	/** +	* Returns SQL string to cast an integer expression to a string. +	* +	* @param  string $expression An expression evaluating to int +	* @return string             Expression returning a string +	*/ +	function cast_expr_to_string($expression) +	{ +		return $expression; +	} + +	/**  	* Run LOWER() on DB column of type text (i.e. neither varchar nor char).  	*  	* @param string $column_name	The column name to use @@ -516,12 +568,12 @@ class dbal  	* Run more than one insert statement.  	*  	* @param string $table table name to run the statements on -	* @param array &$sql_ary multi-dimensional array holding the statement data. +	* @param array $sql_ary multi-dimensional array holding the statement data.  	*  	* @return bool false if no statements were executed.  	* @access public  	*/ -	function sql_multi_insert($table, &$sql_ary) +	function sql_multi_insert($table, $sql_ary)  	{  		if (!sizeof($sql_ary))  		{ @@ -714,8 +766,8 @@ class dbal  			// Show complete SQL error and path to administrators only  			// Additionally show complete error on installation or if extended debug mode is enabled -			// The DEBUG_EXTRA constant is for development only! -			if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG_EXTRA')) +			// The DEBUG constant is for development only! +			if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG'))  			{  				$message .= ($sql) ? '<br /><br />SQL<br /><br />' . htmlspecialchars($sql) : '';  			} @@ -770,9 +822,10 @@ class dbal  	*/  	function sql_report($mode, $query = '')  	{ -		global $cache, $starttime, $phpbb_root_path, $user; +		global $cache, $starttime, $phpbb_root_path, $phpbb_admin_path, $user; +		global $request; -		if (empty($_REQUEST['explain'])) +		if (is_object($request) && !$request->variable('explain', false))  		{  			return false;  		} @@ -794,14 +847,12 @@ class dbal  				$mtime = explode(' ', microtime());  				$totaltime = $mtime[0] + $mtime[1] - $starttime; -				echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -					<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> +				echo '<!DOCTYPE html> +					<html dir="ltr">  					<head> -						<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> -						<meta http-equiv="Content-Style-Type" content="text/css" /> -						<meta http-equiv="imagetoolbar" content="no" /> +						<meta charset="utf-8">  						<title>SQL Report</title> -						<link href="' . $phpbb_root_path . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> +						<link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />  					</head>  					<body id="errorpage">  					<div id="wrap"> @@ -991,10 +1042,3 @@ class dbal  		return $rows_total;  	}  } - -/** -* This variable holds the class name to use later -*/ -$sql_db = (!empty($dbms)) ? 'dbal_' . basename($dbms) : 'dbal'; - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/driver/firebird.php index 7072c58ac0..787c28b812 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/driver/firebird.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,14 +15,12 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * Firebird/Interbase Database Abstraction Layer  * Minimum Requirement is Firebird 2.1  * @package dbal  */ -class dbal_firebird extends dbal +class phpbb_db_driver_firebird extends phpbb_db_driver  {  	var $last_query_text = '';  	var $service_handle = false; @@ -151,13 +148,13 @@ class dbal_firebird extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			}  			$this->last_query_text = $query; -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -252,7 +249,7 @@ class dbal_firebird extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} @@ -270,17 +267,17 @@ class dbal_firebird extends dbal  					}  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -333,7 +330,7 @@ class dbal_firebird extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -399,7 +396,7 @@ class dbal_firebird extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -450,6 +447,23 @@ class dbal_firebird extends dbal  	}  	/** +	* @inheritdoc +	*/ +	function cast_expr_to_bigint($expression) +	{ +		// Precision must be from 1 to 18 +		return 'CAST(' . $expression . ' as DECIMAL(18, 0))'; +	} + +	/** +	* @inheritdoc +	*/ +	function cast_expr_to_string($expression) +	{ +		return 'CAST(' . $expression . ' as VARCHAR(255))'; +	} + +	/**  	* return sql error array  	* @access private  	*/ @@ -522,5 +536,3 @@ class dbal_firebird extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/driver/mssql.php index 2dd95c2508..89c2c2351b 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/driver/mssql.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,14 +15,12 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * MSSQL Database Abstraction Layer  * Minimum Requirement is MSSQL 2000+  * @package dbal  */ -class dbal_mssql extends dbal +class phpbb_db_driver_mssql extends phpbb_db_driver  {  	var $connect_error = ''; @@ -49,14 +46,7 @@ class dbal_mssql extends dbal  		@ini_set('mssql.textlimit', 2147483647);  		@ini_set('mssql.textsize', 2147483647); -		if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.1', '>='))) -		{ -			$this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link); -		} -		else -		{ -			$this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword) : @mssql_connect($this->server, $this->user, $sqlpassword); -		} +		$this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link);  		if ($this->db_connect_id && $this->dbname != '')  		{ @@ -108,6 +98,14 @@ class dbal_mssql extends dbal  	}  	/** +	* {@inheritDoc} +	*/ +	public function sql_concatenate($expr1, $expr2) +	{ +		return $expr1 . ' + ' . $expr2; +	} + +	/**  	* SQL Transaction  	* @access private  	*/ @@ -147,12 +145,12 @@ class dbal_mssql extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			} -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -162,22 +160,22 @@ class dbal_mssql extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -242,7 +240,7 @@ class dbal_mssql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -279,7 +277,7 @@ class dbal_mssql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -318,7 +316,7 @@ class dbal_mssql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -472,5 +470,3 @@ class dbal_mssql extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/driver/mssql_base.php b/phpBB/includes/db/driver/mssql_base.php new file mode 100644 index 0000000000..56c111c871 --- /dev/null +++ b/phpBB/includes/db/driver/mssql_base.php @@ -0,0 +1,65 @@ +<?php +/** +* +* @package dbal +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* MSSQL Database Base Abstraction Layer +* @package dbal + */ +abstract class phpbb_db_driver_mssql_base extends phpbb_db_driver +{ +	/** +	* {@inheritDoc} +	*/ +	public function sql_concatenate($expr1, $expr2) +	{ +		return $expr1 . ' + ' . $expr2; +	} + +	/** +	* Escape string used in sql query +	*/ +	function sql_escape($msg) +	{ +		return str_replace(array("'", "\0"), array("''", ''), $msg); +	} + +	/** +	* {@inheritDoc} +	*/ +	function sql_lower_text($column_name) +	{ +		return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; +	} + +	/** +	* Build LIKE expression +	* @access private +	*/ +	function _sql_like_expression($expression) +	{ +		return $expression . " ESCAPE '\\'"; +	} + +	/** +	* Build db-specific query data +	* @access private +	*/ +	function _sql_custom_build($stage, $data) +	{ +		return $data; +	} +} diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/driver/mssql_odbc.php index 04501cce8b..cde9d332ba 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/driver/mssql_odbc.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,8 +15,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * Unified ODBC functions  * Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... @@ -29,7 +26,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);  *  * @package dbal  */ -class dbal_mssql_odbc extends dbal +class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base  {  	var $last_query_text = '';  	var $connect_error = ''; @@ -168,13 +165,13 @@ class dbal_mssql_odbc extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			}  			$this->last_query_text = $query; -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -184,22 +181,22 @@ class dbal_mssql_odbc extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -265,7 +262,7 @@ class dbal_mssql_odbc extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -306,7 +303,7 @@ class dbal_mssql_odbc extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -321,40 +318,6 @@ class dbal_mssql_odbc extends dbal  	}  	/** -	* Escape string used in sql query -	*/ -	function sql_escape($msg) -	{ -		return str_replace(array("'", "\0"), array("''", ''), $msg); -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_lower_text($column_name) -	{ -		return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; -	} - -	/** -	* Build LIKE expression -	* @access private -	*/ -	function _sql_like_expression($expression) -	{ -		return $expression . " ESCAPE '\\'"; -	} - -	/** -	* Build db-specific query data -	* @access private -	*/ -	function _sql_custom_build($stage, $data) -	{ -		return $data; -	} - -	/**  	* return sql error array  	* @access private  	*/ @@ -418,5 +381,3 @@ class dbal_mssql_odbc extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/driver/mssqlnative.php index b91372ac61..6f433e10cf 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/driver/mssqlnative.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  * This is the MS SQL Server Native database abstraction layer.  * PHP mssql native driver required. @@ -20,8 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**   * Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array   * and maintain our own cursor index into that array. @@ -194,7 +191,7 @@ class result_mssqlnative  /**  * @package dbal  */ -class dbal_mssqlnative extends dbal +class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base  {  	var $m_insert_id = NULL;  	var $last_query_text = ''; @@ -306,13 +303,13 @@ class dbal_mssqlnative extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			}  			$this->last_query_text = $query; -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -324,22 +321,22 @@ class dbal_mssqlnative extends dbal  				// reset options for next query  				$this->query_options = array(); -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -412,7 +409,7 @@ class dbal_mssqlnative extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -472,7 +469,7 @@ class dbal_mssqlnative extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -486,31 +483,6 @@ class dbal_mssqlnative extends dbal  	}  	/** -	* Escape string used in sql query -	*/ -	function sql_escape($msg) -	{ -		return str_replace(array("'", "\0"), array("''", ''), $msg); -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_lower_text($column_name) -	{ -		return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; -	} - -	/** -	* Build LIKE expression -	* @access private -	*/ -	function _sql_like_expression($expression) -	{ -		return $expression . " ESCAPE '\\'"; -	} - -	/**  	* return sql error array  	* @access private  	*/ @@ -556,15 +528,6 @@ class dbal_mssqlnative extends dbal  	}  	/** -	* Build db-specific query data -	* @access private -	*/ -	function _sql_custom_build($stage, $data) -	{ -		return $data; -	} - -	/**  	* Close sql connection  	* @access private  	*/ @@ -648,5 +611,3 @@ class dbal_mssqlnative extends dbal  		$this->query_options = $options;  	}  } - -?> diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/driver/mysql.php index 252cb20bd4..f3744ac09d 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/driver/mysql.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,8 +15,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * MySQL4 Database Abstraction Layer  * Compatible with: @@ -27,7 +24,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);  * MySQL 5.0+  * @package dbal  */ -class dbal_mysql extends dbal +class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base  {  	var $multi_insert = true;  	var $connect_error = ''; @@ -178,12 +175,12 @@ class dbal_mysql extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			} -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -193,22 +190,22 @@ class dbal_mysql extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -222,25 +219,6 @@ class dbal_mysql extends dbal  	}  	/** -	* Build LIMIT query -	*/ -	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) -	{ -		$this->query_result = false; - -		// if $total is set to 0 we do not want to limit the number of rows -		if ($total == 0) -		{ -			// Having a value of -1 was always a bug -			$total = '18446744073709551615'; -		} - -		$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - -		return $this->sql_query($query, $cache_ttl); -	} - -	/**  	* Return number of affected rows  	*/  	function sql_affectedrows() @@ -260,7 +238,7 @@ class dbal_mysql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -281,7 +259,7 @@ class dbal_mysql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -309,7 +287,7 @@ class dbal_mysql extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -337,101 +315,6 @@ class dbal_mysql extends dbal  	}  	/** -	* Gets the estimated number of rows in a specified table. -	* -	* @param string $table_name		Table name -	* -	* @return string				Number of rows in $table_name. -	*								Prefixed with ~ if estimated (otherwise exact). -	* -	* @access public -	*/ -	function get_estimated_row_count($table_name) -	{ -		$table_status = $this->get_table_status($table_name); - -		if (isset($table_status['Engine'])) -		{ -			if ($table_status['Engine'] === 'MyISAM') -			{ -				return $table_status['Rows']; -			} -			else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) -			{ -				return '~' . $table_status['Rows']; -			} -		} - -		return parent::get_row_count($table_name); -	} - -	/** -	* Gets the exact number of rows in a specified table. -	* -	* @param string $table_name		Table name -	* -	* @return string				Exact number of rows in $table_name. -	* -	* @access public -	*/ -	function get_row_count($table_name) -	{ -		$table_status = $this->get_table_status($table_name); - -		if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') -		{ -			return $table_status['Rows']; -		} - -		return parent::get_row_count($table_name); -	} - -	/** -	* Gets some information about the specified table. -	* -	* @param string $table_name		Table name -	* -	* @return array -	* -	* @access protected -	*/ -	function get_table_status($table_name) -	{ -		$sql = "SHOW TABLE STATUS -			LIKE '" . $this->sql_escape($table_name) . "'"; -		$result = $this->sql_query($sql); -		$table_status = $this->sql_fetchrow($result); -		$this->sql_freeresult($result); - -		return $table_status; -	} - -	/** -	* Build LIKE expression -	* @access private -	*/ -	function _sql_like_expression($expression) -	{ -		return $expression; -	} - -	/** -	* Build db-specific query data -	* @access private -	*/ -	function _sql_custom_build($stage, $data) -	{ -		switch ($stage) -		{ -			case 'FROM': -				$data = '(' . $data . ')'; -			break; -		} - -		return $data; -	} - -	/**  	* return sql error array  	* @access private  	*/ @@ -587,5 +470,3 @@ class dbal_mysql extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/driver/mysql_base.php b/phpBB/includes/db/driver/mysql_base.php new file mode 100644 index 0000000000..ba44ea61aa --- /dev/null +++ b/phpBB/includes/db/driver/mysql_base.php @@ -0,0 +1,145 @@ +<?php +/** +* +* @package dbal +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Abstract MySQL Database Base Abstraction Layer +* @package dbal +*/ +abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver +{ +	/** +	* {@inheritDoc} +	*/ +	public function sql_concatenate($expr1, $expr2) +	{ +		return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')'; +	} + +	/** +	* Build LIMIT query +	*/ +	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) +	{ +		$this->query_result = false; + +		// if $total is set to 0 we do not want to limit the number of rows +		if ($total == 0) +		{ +			// MySQL 4.1+ no longer supports -1 in limit queries +			$total = '18446744073709551615'; +		} + +		$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); + +		return $this->sql_query($query, $cache_ttl); +	} + +	/** +	* Gets the estimated number of rows in a specified table. +	* +	* @param string $table_name		Table name +	* +	* @return string				Number of rows in $table_name. +	*								Prefixed with ~ if estimated (otherwise exact). +	* +	* @access public +	*/ +	function get_estimated_row_count($table_name) +	{ +		$table_status = $this->get_table_status($table_name); + +		if (isset($table_status['Engine'])) +		{ +			if ($table_status['Engine'] === 'MyISAM') +			{ +				return $table_status['Rows']; +			} +			else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) +			{ +				return '~' . $table_status['Rows']; +			} +		} + +		return parent::get_row_count($table_name); +	} + +	/** +	* Gets the exact number of rows in a specified table. +	* +	* @param string $table_name		Table name +	* +	* @return string				Exact number of rows in $table_name. +	* +	* @access public +	*/ +	function get_row_count($table_name) +	{ +		$table_status = $this->get_table_status($table_name); + +		if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') +		{ +			return $table_status['Rows']; +		} + +		return parent::get_row_count($table_name); +	} + +	/** +	* Gets some information about the specified table. +	* +	* @param string $table_name		Table name +	* +	* @return array +	* +	* @access protected +	*/ +	function get_table_status($table_name) +	{ +		$sql = "SHOW TABLE STATUS +			LIKE '" . $this->sql_escape($table_name) . "'"; +		$result = $this->sql_query($sql); +		$table_status = $this->sql_fetchrow($result); +		$this->sql_freeresult($result); + +		return $table_status; +	} + +	/** +	* Build LIKE expression +	* @access private +	*/ +	function _sql_like_expression($expression) +	{ +		return $expression; +	} + +	/** +	* Build db-specific query data +	* @access private +	*/ +	function _sql_custom_build($stage, $data) +	{ +		switch ($stage) +		{ +			case 'FROM': +				$data = '(' . $data . ')'; +			break; +		} + +		return $data; +	} +} diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/driver/mysqli.php index 69f1d26a40..0f7a73ee6e 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/driver/mysqli.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,15 +15,13 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * MySQLi Database Abstraction Layer  * mysqli-extension has to be compiled with:  * MySQL 4.1+ or MySQL 5.0+  * @package dbal  */ -class dbal_mysqli extends dbal +class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base  {  	var $multi_insert = true;  	var $connect_error = ''; @@ -106,6 +103,7 @@ class dbal_mysqli extends dbal  	/**  	* Version information about used database +	* @param bool $raw if true, only return the fetched sql_server_version  	* @param bool $use_cache If true, it is safe to retrieve the value from the cache  	* @return string sql server version  	*/ @@ -174,12 +172,12 @@ class dbal_mysqli extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			} -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -189,17 +187,17 @@ class dbal_mysqli extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{ -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -213,25 +211,6 @@ class dbal_mysqli extends dbal  	}  	/** -	* Build LIMIT query -	*/ -	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) -	{ -		$this->query_result = false; - -		// if $total is set to 0 we do not want to limit the number of rows -		if ($total == 0) -		{ -			// MySQL 4.1+ no longer supports -1 in limit queries -			$total = '18446744073709551615'; -		} - -		$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - -		return $this->sql_query($query, $cache_ttl); -	} - -	/**  	* Return number of affected rows  	*/  	function sql_affectedrows() @@ -251,7 +230,7 @@ class dbal_mysqli extends dbal  			$query_id = $this->query_result;  		} -		if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) +		if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -278,7 +257,7 @@ class dbal_mysqli extends dbal  			$query_id = $this->query_result;  		} -		if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) +		if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -306,7 +285,7 @@ class dbal_mysqli extends dbal  			$query_id = $this->query_result;  		} -		if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) +		if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -323,101 +302,6 @@ class dbal_mysqli extends dbal  	}  	/** -	* Gets the estimated number of rows in a specified table. -	* -	* @param string $table_name		Table name -	* -	* @return string				Number of rows in $table_name. -	*								Prefixed with ~ if estimated (otherwise exact). -	* -	* @access public -	*/ -	function get_estimated_row_count($table_name) -	{ -		$table_status = $this->get_table_status($table_name); - -		if (isset($table_status['Engine'])) -		{ -			if ($table_status['Engine'] === 'MyISAM') -			{ -				return $table_status['Rows']; -			} -			else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) -			{ -				return '~' . $table_status['Rows']; -			} -		} - -		return parent::get_row_count($table_name); -	} - -	/** -	* Gets the exact number of rows in a specified table. -	* -	* @param string $table_name		Table name -	* -	* @return string				Exact number of rows in $table_name. -	* -	* @access public -	*/ -	function get_row_count($table_name) -	{ -		$table_status = $this->get_table_status($table_name); - -		if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') -		{ -			return $table_status['Rows']; -		} - -		return parent::get_row_count($table_name); -	} - -	/** -	* Gets some information about the specified table. -	* -	* @param string $table_name		Table name -	* -	* @return array -	* -	* @access protected -	*/ -	function get_table_status($table_name) -	{ -		$sql = "SHOW TABLE STATUS -			LIKE '" . $this->sql_escape($table_name) . "'"; -		$result = $this->sql_query($sql); -		$table_status = $this->sql_fetchrow($result); -		$this->sql_freeresult($result); - -		return $table_status; -	} - -	/** -	* Build LIKE expression -	* @access private -	*/ -	function _sql_like_expression($expression) -	{ -		return $expression; -	} - -	/** -	* Build db-specific query data -	* @access private -	*/ -	function _sql_custom_build($stage, $data) -	{ -		switch ($stage) -		{ -			case 'FROM': -				$data = '(' . $data . ')'; -			break; -		} - -		return $data; -	} - -	/**  	* return sql error array  	* @access private  	*/ @@ -577,5 +461,3 @@ class dbal_mysqli extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/driver/oracle.php index 4a7a4ecc8c..e21e07055d 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/driver/oracle.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,13 +15,11 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * Oracle Database Abstraction Layer  * @package dbal  */ -class dbal_oracle extends dbal +class phpbb_db_driver_oracle extends phpbb_db_driver  {  	var $last_query_text = '';  	var $connect_error = ''; @@ -264,13 +261,13 @@ class dbal_oracle extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			}  			$this->last_query_text = $query; -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -441,22 +438,22 @@ class dbal_oracle extends dbal  					}  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -501,7 +498,7 @@ class dbal_oracle extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -553,7 +550,7 @@ class dbal_oracle extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -622,7 +619,7 @@ class dbal_oracle extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -804,5 +801,3 @@ class dbal_oracle extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/driver/postgres.php index bb116e0763..14854d179d 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/driver/postgres.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,19 +15,12 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -if (!class_exists('phpbb_error_collector')) -{ -	include($phpbb_root_path . 'includes/error_collector.' . $phpEx); -} -  /**  * PostgreSQL Database Abstraction Layer  * Minimum Requirement is Version 7.3+  * @package dbal  */ -class dbal_postgres extends dbal +class phpbb_db_driver_postgres extends phpbb_db_driver  {  	var $last_query_text = '';  	var $connect_error = ''; @@ -195,13 +187,13 @@ class dbal_postgres extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			}  			$this->last_query_text = $query; -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -211,22 +203,22 @@ class dbal_postgres extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -286,7 +278,7 @@ class dbal_postgres extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -307,7 +299,7 @@ class dbal_postgres extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -356,7 +348,7 @@ class dbal_postgres extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -389,6 +381,22 @@ class dbal_postgres extends dbal  	}  	/** +	* @inheritdoc +	*/ +	function cast_expr_to_bigint($expression) +	{ +		return 'CAST(' . $expression . ' as DECIMAL(255, 0))'; +	} + +	/** +	* @inheritdoc +	*/ +	function cast_expr_to_string($expression) +	{ +		return 'CAST(' . $expression . ' as VARCHAR(255))'; +	} + +	/**  	* return sql error array  	* @access private  	*/ @@ -481,5 +489,3 @@ class dbal_postgres extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/driver/sqlite.php index 557b057cce..7188f0daa2 100644 --- a/phpBB/includes/db/sqlite.php +++ b/phpBB/includes/db/driver/sqlite.php @@ -2,9 +2,8 @@  /**  *  * @package dbal -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -16,14 +15,12 @@ if (!defined('IN_PHPBB'))  	exit;  } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); -  /**  * Sqlite Database Abstraction Layer  * Minimum Requirement: 2.8.2+  * @package dbal  */ -class dbal_sqlite extends dbal +class phpbb_db_driver_sqlite extends phpbb_db_driver  {  	var $connect_error = ''; @@ -132,12 +129,12 @@ class dbal_sqlite extends dbal  			global $cache;  			// EXPLAIN only in extra debug mode -			if (defined('DEBUG_EXTRA')) +			if (defined('DEBUG'))  			{  				$this->sql_report('start', $query);  			} -			$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; +			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;  			$this->sql_add_num_queries($this->query_result);  			if ($this->query_result === false) @@ -147,22 +144,22 @@ class dbal_sqlite extends dbal  					$this->sql_error($query);  				} -				if (defined('DEBUG_EXTRA')) +				if (defined('DEBUG'))  				{  					$this->sql_report('stop', $query);  				} -				if ($cache_ttl && method_exists($cache, 'sql_save')) +				if ($cache && $cache_ttl)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$cache->sql_save($query, $this->query_result, $cache_ttl); +					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  				else if (strpos($query, 'SELECT') === 0 && $this->query_result)  				{  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG_EXTRA')) +			else if (defined('DEBUG'))  			{  				$this->sql_report('fromcache', $query);  			} @@ -213,7 +210,7 @@ class dbal_sqlite extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_fetchrow($query_id);  		} @@ -234,7 +231,7 @@ class dbal_sqlite extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_rowseek($rownum, $query_id);  		} @@ -262,7 +259,7 @@ class dbal_sqlite extends dbal  			$query_id = $this->query_result;  		} -		if (isset($cache->sql_rowset[$query_id])) +		if ($cache && $cache->sql_exists($query_id))  		{  			return $cache->sql_freeresult($query_id);  		} @@ -366,5 +363,3 @@ class dbal_sqlite extends dbal  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/migration/data/30x/3_0_1.php b/phpBB/includes/db/migration/data/30x/3_0_1.php new file mode 100644 index 0000000000..c996a0138a --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_1.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_1_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.1')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_10.php b/phpBB/includes/db/migration/data/30x/3_0_10.php new file mode 100644 index 0000000000..122f93d6b4 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_10.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_10 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.10', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_10_rc3'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.10')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_10_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_10_rc1.php new file mode 100644 index 0000000000..0ed05812dc --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_10_rc1.php @@ -0,0 +1,30 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_10_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.10-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_9'); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('email_max_chunk_size', 50)), + +			array('config.update', array('version', '3.0.10-rc1')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_10_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_10_rc2.php new file mode 100644 index 0000000000..b14b3b00aa --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_10_rc2.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_10_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.10-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_10_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.10-rc2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_10_rc3.php b/phpBB/includes/db/migration/data/30x/3_0_10_rc3.php new file mode 100644 index 0000000000..473057d65d --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_10_rc3.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_10_rc3 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.10-rc3', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_10_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.10-rc3')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_11.php b/phpBB/includes/db/migration/data/30x/3_0_11.php new file mode 100644 index 0000000000..e063c699cc --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_11.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_11 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.11', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.11')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_11_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_11_rc1.php new file mode 100644 index 0000000000..dddfc0e0e7 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_11_rc1.php @@ -0,0 +1,95 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_11_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.11-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_10'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'cleanup_deactivated_styles'))), +			array('custom', array(array(&$this, 'delete_orphan_private_messages'))), + +			array('config.update', array('version', '3.0.11-rc1')), +		); +	} + +	public function cleanup_deactivated_styles() +	{ +		// Updates users having current style a deactivated one +		$sql = 'SELECT style_id +			FROM ' . STYLES_TABLE . ' +			WHERE style_active = 0'; +		$result = $this->sql_query($sql); + +		$deactivated_style_ids = array(); +		while ($style_id = $this->db->sql_fetchfield('style_id', false, $result)) +		{ +			$deactivated_style_ids[] = (int) $style_id; +		} +		$this->db->sql_freeresult($result); + +		if (!empty($deactivated_style_ids)) +		{ +			$sql = 'UPDATE ' . USERS_TABLE . ' +				SET user_style = ' . (int) $this->config['default_style'] .' +				WHERE ' . $this->db->sql_in_set('user_style', $deactivated_style_ids); +			$this->sql_query($sql); +		} +	} + +	public function delete_orphan_private_messages() +	{ +		// Delete orphan private messages +		$batch_size = 500; + +		$sql_array = array( +			'SELECT'	=> 'p.msg_id', +			'FROM'		=> array( +				PRIVMSGS_TABLE	=> 'p', +			), +			'LEFT_JOIN'	=> array( +				array( +					'FROM'	=> array(PRIVMSGS_TO_TABLE => 't'), +					'ON'	=> 'p.msg_id = t.msg_id', +				), +			), +			'WHERE'		=> 't.user_id IS NULL', +		); +		$sql = $this->db->sql_build_query('SELECT', $sql_array); + +		$result = $this->db->sql_query_limit($sql, $batch_size); + +		$delete_pms = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$delete_pms[] = (int) $row['msg_id']; +		} +		$this->db->sql_freeresult($result); + +		if (!empty($delete_pms)) +		{ +			$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' +				WHERE ' . $this->db->sql_in_set('msg_id', $delete_pms); +			$this->sql_query($sql); + +			// Return false to have the Migrator call this function again +			return false; +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_11_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_11_rc2.php new file mode 100644 index 0000000000..fac8523e8c --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_11_rc2.php @@ -0,0 +1,50 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_11_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.11-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11_rc1'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns' => array( +				$this->table_prefix . 'profile_fields' => array( +					'field_show_novalue' => array('BOOL', 0), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns' => array( +				$this->table_prefix . 'profile_fields' => array( +					'field_show_novalue', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.11-rc2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_12_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_12_rc1.php new file mode 100644 index 0000000000..6a31a51201 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_12_rc1.php @@ -0,0 +1,123 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.12-RC1 **/ + +class phpbb_db_migration_data_30x_3_0_12_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.12-rc1', '>='); +	} + + 	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'update_module_auth'))), +			array('custom', array(array(&$this, 'update_bots'))), +			array('custom', array(array(&$this, 'disable_bots_from_receiving_pms'))), + +			array('config.update', array('version', '3.0.12-rc1')), +		); +	} + +	public function disable_bots_from_receiving_pms() +	{ +		// Disable receiving pms for bots +		$sql = 'SELECT user_id +			FROM ' . BOTS_TABLE; +		$result = $this->db->sql_query($sql); + +		$bot_user_ids = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$bot_user_ids[] = (int) $row['user_id']; +		} +		$this->db->sql_freeresult($result); + +		if (!empty($bot_user_ids)) +		{ +			$sql = 'UPDATE ' . USERS_TABLE . ' +				SET user_allow_pm = 0 +				WHERE ' . $this->db->sql_in_set('user_id', $bot_user_ids); +			$this->sql_query($sql); +		} +	} + +	public function update_module_auth() +	{ +		$sql = 'UPDATE ' . MODULES_TABLE . ' +			SET module_auth = \'acl_u_sig\' +			WHERE module_class = \'ucp\' +				AND module_basename = \'profile\' +				AND module_mode = \'signature\''; +		$this->sql_query($sql); +	} + +	public function update_bots() +	{ +		// Update bots +		if (!function_exists('user_delete')) +		{ +			include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext); +		} + +		$bots_updates = array( +			// Bot Deletions +			'NG-Search [Bot]'		=> false, +			'Nutch/CVS [Bot]'		=> false, +			'OmniExplorer [Bot]'	=> false, +			'Seekport [Bot]'		=> false, +			'Synoo [Bot]'			=> false, +			'WiseNut [Bot]'			=> false, + +			// Bot Updates +			// Bot name to bot user agent map +			'Baidu [Spider]'	=> 'Baiduspider', +			'Exabot [Bot]'		=> 'Exabot', +			'Voyager [Bot]'		=> 'voyager/', +			'W3C [Validator]'	=> 'W3C_Validator', +		); + +		foreach ($bots_updates as $bot_name => $bot_agent) +		{ +			$sql = 'SELECT user_id +				FROM ' . USERS_TABLE . ' +				WHERE user_type = ' . USER_IGNORE . " +					AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($bot_name)) . "'"; +			$result = $this->db->sql_query($sql); +			$bot_user_id = (int) $this->db->sql_fetchfield('user_id'); +			$this->db->sql_freeresult($result); + +			if ($bot_user_id) +			{ +				if ($bot_agent === false) +				{ +					$sql = 'DELETE FROM ' . BOTS_TABLE . " +						WHERE user_id = $bot_user_id"; +					$this->sql_query($sql); + +					user_delete('remove', $bot_user_id); +				} +				else +				{ +					$sql = 'UPDATE ' . BOTS_TABLE . " +						SET bot_agent = '" .  $this->db->sql_escape($bot_agent) . "' +						WHERE user_id = $bot_user_id"; +					$this->sql_query($sql); +				} +			} +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_1_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_1_rc1.php new file mode 100644 index 0000000000..562ccf077c --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_1_rc1.php @@ -0,0 +1,108 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_1_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.1-rc1', '>='); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns' => array( +				$this->table_prefix . 'forums' => array( +					'display_subforum_list' => array('BOOL', 1), +				), +				$this->table_prefix . 'sessions' => array( +					'session_forum_id' => array('UINT', 0), +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'groups' => array( +					'group_legend', +				), +			), +			'add_index' => array( +				$this->table_prefix . 'sessions' => array( +					'session_forum_id' => array('session_forum_id'), +				), +				$this->table_prefix . 'groups' => array( +					'group_legend_name' => array('group_legend', 'group_name'), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns' => array( +				$this->table_prefix . 'forums' => array( +					'display_subforum_list', +				), +				$this->table_prefix . 'sessions' => array( +					'session_forum_id', +				), +			), +			'add_index' => array( +				$this->table_prefix . 'groups' => array( +					'group_legend' => array('group_legend'), +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'sessions' => array( +					'session_forum_id', +				), +				$this->table_prefix . 'groups' => array( +					'group_legend_name', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'fix_unset_last_view_time'))), +			array('custom', array(array(&$this, 'reset_smiley_size'))), + +			array('config.update', array('version', '3.0.1-rc1')), +		); +	} + +	public function fix_unset_last_view_time() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . "topics +			SET topic_last_view_time = topic_last_post_time +			WHERE topic_last_view_time = 0"; +		$this->sql_query($sql); +	} + +	public function reset_smiley_size() +	{ +		// Update smiley sizes +		$smileys = array('icon_e_surprised.gif', 'icon_eek.gif', 'icon_cool.gif', 'icon_lol.gif', 'icon_mad.gif', 'icon_razz.gif', 'icon_redface.gif', 'icon_cry.gif', 'icon_evil.gif', 'icon_twisted.gif', 'icon_rolleyes.gif', 'icon_exclaim.gif', 'icon_question.gif', 'icon_idea.gif', 'icon_arrow.gif', 'icon_neutral.gif', 'icon_mrgreen.gif', 'icon_e_ugeek.gif'); + +		foreach ($smileys as $smiley) +		{ +			if (file_exists($this->phpbb_root_path . 'images/smilies/' . $smiley)) +			{ +				list($width, $height) = getimagesize($this->phpbb_root_path . 'images/smilies/' . $smiley); + +				$sql = 'UPDATE ' . SMILIES_TABLE . ' +					SET smiley_width = ' . $width . ', smiley_height = ' . $height . " +					WHERE smiley_url = '" . $this->db->sql_escape($smiley) . "'"; + +				$this->sql_query($sql); +			} +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_2.php b/phpBB/includes/db/migration/data/30x/3_0_2.php new file mode 100644 index 0000000000..eed5acef82 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_2.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_2_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_2_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_2_rc1.php new file mode 100644 index 0000000000..a960e90765 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_2_rc1.php @@ -0,0 +1,32 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_2_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.2-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('referer_validation', '1')), +			array('config.add', array('check_attachment_content', '1')), +			array('config.add', array('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title')), + +			array('config.update', array('version', '3.0.2-rc1')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_2_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_2_rc2.php new file mode 100644 index 0000000000..8917dfea77 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_2_rc2.php @@ -0,0 +1,80 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_2_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.2-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_2_rc1'); +	} + +	public function update_schema() +	{ +		return array( +			'change_columns' => array( +				$this->table_prefix . 'drafts' => array( +					'draft_subject' => array('STEXT_UNI', ''), +				), +				$this->table_prefix . 'forums' => array( +					'forum_last_post_subject' => array('STEXT_UNI', ''), +				), +				$this->table_prefix . 'posts' => array( +					'post_subject' => array('STEXT_UNI', '', 'true_sort'), +				), +				$this->table_prefix . 'privmsgs' => array( +					'message_subject' => array('STEXT_UNI', ''), +				), +				$this->table_prefix . 'topics' => array( +					'topic_title' => array('STEXT_UNI', '', 'true_sort'), +					'topic_last_post_subject' => array('STEXT_UNI', ''), +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'sessions' => array( +					'session_forum_id', +				), +			), +			'add_index' => array( +				$this->table_prefix . 'sessions' => array( +					'session_fid' => array('session_forum_id'), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'add_index' => array( +				$this->table_prefix . 'sessions' => array( +					'session_forum_id' => array( +						'session_forum_id', +					), +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'sessions' => array( +					'session_fid', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.2-rc2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_3.php b/phpBB/includes/db/migration/data/30x/3_0_3.php new file mode 100644 index 0000000000..8984cf7b76 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_3.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_3 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.3', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_3_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.3')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_3_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_3_rc1.php new file mode 100644 index 0000000000..4b102e1a2e --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_3_rc1.php @@ -0,0 +1,83 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_3_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.3-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_2'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns' => array( +				$this->table_prefix . 'styles_template' => array( +					'template_inherits_id' => array('UINT:4', 0), +					'template_inherit_path' => array('VCHAR', ''), +				), +				$this->table_prefix . 'groups' => array( +					'group_max_recipients' => array('UINT', 0), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns' => array( +				$this->table_prefix . 'styles_template' => array( +					'template_inherits_id', +					'template_inherit_path', +				), +				$this->table_prefix . 'groups' => array( +					'group_max_recipients', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('enable_queue_trigger', '0')), +			array('config.add', array('queue_trigger_posts', '3')), +			array('config.add', array('pm_max_recipients', '0')), +			array('custom', array(array(&$this, 'set_group_default_max_recipients'))), +			array('config.add', array('dbms_version', $this->db->sql_server_info(true))), +			array('permission.add', array('u_masspm_group', true, 'u_masspm')), +			array('custom', array(array(&$this, 'correct_acp_email_permissions'))), + +			array('config.update', array('version', '3.0.3-rc1')), +		); +	} + +	public function correct_acp_email_permissions() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . 'modules +			SET module_auth = \'acl_a_email && cfg_email_enable\' +			WHERE module_class = \'acp\' +				AND module_basename = \'email\''; +		$this->sql_query($sql); +	} + +	public function set_group_default_max_recipients() +	{ +		// Set maximum number of recipients for the registered users, bots, guests group +		$sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5 +			WHERE ' . $this->db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS')); +		$this->sql_query($sql); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_4.php b/phpBB/includes/db/migration/data/30x/3_0_4.php new file mode 100644 index 0000000000..9a0c132e78 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_4.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_4 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.4', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_4_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'rename_log_delete_topic'))), + +			array('config.update', array('version', '3.0.4')), +		); +	} + +	public function rename_log_delete_topic() +	{ +		if ($this->db->sql_layer == 'oracle') +		{ +			// log_operation is CLOB - but we can change this later +			$sql = 'UPDATE ' . $this->table_prefix . "log +				SET log_operation = 'LOG_DELETE_TOPIC' +				WHERE log_operation LIKE 'LOG_TOPIC_DELETED'"; +			$this->sql_query($sql); +		} +		else +		{ +			$sql = 'UPDATE ' . $this->table_prefix . "log +				SET log_operation = 'LOG_DELETE_TOPIC' +				WHERE log_operation = 'LOG_TOPIC_DELETED'"; +			$this->sql_query($sql); +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_4_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_4_rc1.php new file mode 100644 index 0000000000..8ad75a557b --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_4_rc1.php @@ -0,0 +1,123 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_4_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.4-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_3'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns' => array( +				$this->table_prefix . 'profile_fields' => array( +					'field_show_profile' => array('BOOL', 0), +				), +			), +			'change_columns' => array( +				$this->table_prefix . 'styles' => array( +					'style_id' => array('UINT', NULL, 'auto_increment'), +					'template_id' => array('UINT', 0), +					'theme_id' => array('UINT', 0), +					'imageset_id' => array('UINT', 0), +				), +				$this->table_prefix . 'styles_imageset' => array( +					'imageset_id' => array('UINT', NULL, 'auto_increment'), +				), +				$this->table_prefix . 'styles_imageset_data' => array( +					'image_id' => array('UINT', NULL, 'auto_increment'), +					'imageset_id' => array('UINT', 0), +				), +				$this->table_prefix . 'styles_theme' => array( +					'theme_id' => array('UINT', NULL, 'auto_increment'), +				), +				$this->table_prefix . 'styles_template' => array( +					'template_id' => array('UINT', NULL, 'auto_increment'), +				), +				$this->table_prefix . 'styles_template_data' => array( +					'template_id' => array('UINT', 0), +				), +				$this->table_prefix . 'forums' => array( +					'forum_style' => array('UINT', 0), +				), +				$this->table_prefix . 'users' => array( +					'user_style' => array('UINT', 0), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns' => array( +				$this->table_prefix . 'profile_fields' => array( +					'field_show_profile', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'update_custom_profile_fields'))), + +			array('config.update', array('version', '3.0.4-rc1')), +		); +	} + +	public function update_custom_profile_fields() +	{ +		// Update the Custom Profile Fields based on previous settings to the new format +		$sql = 'SELECT field_id, field_required, field_show_on_reg, field_hide +				FROM ' . PROFILE_FIELDS_TABLE; +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$sql_ary = array( +				'field_required'	=> 0, +				'field_show_on_reg'	=> 0, +				'field_hide'		=> 0, +				'field_show_profile'=> 0, +			); + +			if ($row['field_required']) +			{ +				$sql_ary['field_required'] = $sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1; +			} +			else if ($row['field_show_on_reg']) +			{ +				$sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1; +			} +			else if ($row['field_hide']) +			{ +				// Only administrators and moderators can see this CPF, if the view is enabled, they can see it, otherwise just admins in the acp_users module +				$sql_ary['field_hide'] = 1; +			} +			else +			{ +				// equivelant to "none", which is the "Display in user control panel" option +				$sql_ary['field_show_profile'] = 1; +			} + +			$this->sql_query('UPDATE ' . $this->table_prefix . 'profile_fields SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE field_id = ' . $row['field_id'], $errored, $error_ary); +		} + +		$this->db->sql_freeresult($result); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_5.php b/phpBB/includes/db/migration/data/30x/3_0_5.php new file mode 100644 index 0000000000..16d2dee457 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_5.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_5 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.5', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_5_rc1part2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.5')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_5_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_5_rc1.php new file mode 100644 index 0000000000..ea17cc1e31 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_5_rc1.php @@ -0,0 +1,124 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_5_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.5-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_4'); +	} + +	public function update_schema() +	{ +		return array( +			'change_columns' => array( +				$this->table_prefix . 'forums' => array( +					'forum_style' => array('UINT', 0), +				), +			), +		); +	} + +	public function update_data() +	{ +		$search_indexing_state = $this->config['search_indexing_state']; + +		return array( +			array('config.add', array('captcha_gd_wave', 0)), +			array('config.add', array('captcha_gd_3d_noise', 1)), +			array('config.add', array('captcha_gd_fonts', 1)), +			array('config.add', array('confirm_refresh', 1)), +			array('config.add', array('max_num_search_keywords', 10)), +			array('config.remove', array('search_indexing_state')), +			array('config.add', array('search_indexing_state', $search_indexing_state, true)), +			array('custom', array(array(&$this, 'hash_old_passwords'))), +			array('custom', array(array(&$this, 'update_ichiro_bot'))), +		); +	} + +	public function hash_old_passwords() +	{ +		$sql = 'SELECT user_id, user_password +				FROM ' . $this->table_prefix . 'users +				WHERE user_pass_convert = 1'; +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			if (strlen($row['user_password']) == 32) +			{ +				$sql_ary = array( +					'user_password'	=> phpbb_hash($row['user_password']), +				); + +				$this->sql_query('UPDATE ' . $this->table_prefix . 'users SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $row['user_id']); +			} +		} +		$this->db->sql_freeresult($result); +	} + +	public function update_ichiro_bot() +	{ +		// Adjust bot entry +		$sql = 'UPDATE ' . $this->table_prefix . "bots +			SET bot_agent = 'ichiro/' +			WHERE bot_agent = 'ichiro/2'"; +		$this->sql_query($sql); +	} + +	public function remove_duplicate_auth_options() +	{ +		// Before we are able to add a unique key to auth_option, we need to remove duplicate entries +		$sql = 'SELECT auth_option +			FROM ' . $this->table_prefix . 'acl_options +			GROUP BY auth_option +			HAVING COUNT(*) >= 2'; +		$result = $this->db->sql_query($sql); + +		$auth_options = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$auth_options[] = $row['auth_option']; +		} +		$this->db->sql_freeresult($result); + +		// Remove specific auth options +		if (!empty($auth_options)) +		{ +			foreach ($auth_options as $option) +			{ +				// 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) . "' +					ORDER BY auth_option_id DESC"; +				// sql_query_limit not possible here, due to bug in postgresql layer +				$result = $this->db->sql_query($sql); + +				// Skip first row, this is our original auth option we want to preserve +				$row = $this->db->sql_fetchrow($result); + +				while ($row = $this->db->sql_fetchrow($result)) +				{ +					// Ok, remove this auth option... +					$this->sql_query('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']); +					$this->sql_query('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']); +					$this->sql_query('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']); +					$this->sql_query('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']); +				} +				$this->db->sql_freeresult($result); +			} +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_5_rc1part2.php b/phpBB/includes/db/migration/data/30x/3_0_5_rc1part2.php new file mode 100644 index 0000000000..8538347b1a --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_5_rc1part2.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_5_rc1part2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.5-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_5_rc1'); +	} + +	public function update_schema() +	{ +		return array( +			'drop_keys'			=> array( +				$this->table_prefix . 'acl_options'		=> array('auth_option'), +			), +			'add_unique_index'	=> array( +				$this->table_prefix . 'acl_options'		=> array( +					'auth_option'		=> array('auth_option'), +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.5-rc1')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_6.php b/phpBB/includes/db/migration/data/30x/3_0_6.php new file mode 100644 index 0000000000..bb651dc7cd --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_6.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_6 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.6', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_6_rc4'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.6')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_6_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_6_rc1.php new file mode 100644 index 0000000000..38c282ebf0 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_6_rc1.php @@ -0,0 +1,324 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_6_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.6-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_5'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns' => array( +				$this->table_prefix . 'confirm' => array( +					'attempts' => array('UINT', 0), +				), +				$this->table_prefix . 'users' => array( +					'user_new' => array('BOOL', 1), +					'user_reminded' => array('TINT:4', 0), +					'user_reminded_time' => array('TIMESTAMP', 0), +				), +				$this->table_prefix . 'groups' => array( +					'group_skip_auth' => array('BOOL', 0, 'after' => 'group_founder_manage'), +				), +				$this->table_prefix . 'privmsgs' => array( +					'message_reported' => array('BOOL', 0), +				), +				$this->table_prefix . 'reports' => array( +					'pm_id' => array('UINT', 0), +				), +				$this->table_prefix . 'profile_fields'	=> array( +					'field_show_on_vt' => array('BOOL', 0), +				), +				$this->table_prefix . 'forums' => array( +					'forum_options' => array('UINT:20', 0), +				), +			), +			'change_columns' => array( +				$this->table_prefix . 'users' => array( +					'user_options' => array('UINT:11', 230271), +				), +			), +			'add_index' => array( +				$this->table_prefix . 'reports' => array( +					'post_id' => array('post_id'), +					'pm_id' => array('pm_id'), +				), +				$this->table_prefix . 'posts' => array( +					'post_username' => array('post_username:255'), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns' => array( +				$this->table_prefix . 'confirm' => array( +					'attempts', +				), +				$this->table_prefix . 'users' => array( +					'user_new', +					'user_reminded', +					'user_reminded_time', +				), +				$this->table_prefix . 'groups' => array( +					'group_skip_auth', +				), +				$this->table_prefix . 'privmsgs' => array( +					'message_reported', +				), +				$this->table_prefix . 'reports' => array( +					'pm_id', +				), +				$this->table_prefix . 'profile_fields'	=> array( +					'field_show_on_vt', +				), +				$this->table_prefix . 'forums' => array( +					'forum_options', +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'reports' => array( +					'post_id', +					'pm_id', +				), +				$this->table_prefix . 'posts' => array( +					'post_username', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('captcha_plugin', 'phpbb_captcha_nogd')), +			array('if', array( +				($this->config['captcha_gd']), +				array('config.update', array('captcha_plugin', 'phpbb_captcha_gd')), +			)), + +			array('config.add', array('feed_enable', 0)), +			array('config.add', array('feed_limit', 10)), +			array('config.add', array('feed_overall_forums', 1)), +			array('config.add', array('feed_overall_forums_limit', 15)), +			array('config.add', array('feed_overall_topics', 0)), +			array('config.add', array('feed_overall_topics_limit', 15)), +			array('config.add', array('feed_forum', 1)), +			array('config.add', array('feed_topic', 1)), +			array('config.add', array('feed_item_statistics', 1)), + +			array('config.add', array('smilies_per_page', 50)), +			array('config.add', array('allow_pm_report', 1)), +			array('config.add', array('min_post_chars', 1)), +			array('config.add', array('allow_quick_reply', 1)), +			array('config.add', array('new_member_post_limit', 0)), +			array('config.add', array('new_member_group_default', 0)), +			array('config.add', array('delete_time', $this->config['edit_time'])), + +			array('config.add', array('allow_avatar', 0)), +			array('if', array( +				($this->config['allow_avatar_upload'] || $this->config['allow_avatar_local'] || $this->config['allow_avatar_remote']), +				array('config.update', array('allow_avatar', 1)), +			)), +			array('config.add', array('allow_avatar_remote_upload', 0)), +			array('if', array( +				($this->config['allow_avatar_remote'] && $this->config['allow_avatar_upload']), +				array('config.update', array('allow_avatar_remote_upload', 1)), +			)), + +			array('module.add', array( +				'acp', +				'ACP_BOARD_CONFIGURATION', +				array( +					'module_basename'	=> 'acp_board', +					'modes'				=> array('feed'), +				), +			)), +			array('module.add', array( +				'acp', +				'ACP_CAT_USERS', +				array( +					'module_basename'	=> 'acp_users', +					'modes'				=> array('warnings'), +				), +			)), +			array('module.add', array( +				'acp', +				'ACP_SERVER_CONFIGURATION', +				array( +					'module_basename'	=> 'acp_send_statistics', +					'modes'				=> array('send_statistics'), +				), +			)), +			array('module.add', array( +				'acp', +				'ACP_FORUM_BASED_PERMISSIONS', +				array( +					'module_basename'	=> 'acp_permissions', +					'modes'				=> array('setting_forum_copy'), +				), +			)), +			array('module.add', array( +				'mcp', +				'MCP_REPORTS', +				array( +					'module_basename'	=> 'mcp_pm_reports', +					'modes'				=> array('pm_reports','pm_reports_closed','pm_report_details'), +				), +			)), +			array('custom', array(array(&$this, 'add_newly_registered_group'))), +			array('custom', array(array(&$this, 'set_user_options_default'))), + +			array('config.update', array('version', '3.0.6-rc1')), +		); +	} + +	public function set_user_options_default() +	{ +		// 229376 is the added value to enable all three signature options +		$sql = 'UPDATE ' . USERS_TABLE . ' SET user_options = user_options + 229376'; +		$this->sql_query($sql); +	} + +	public function add_newly_registered_group() +	{ +		// Add newly_registered group... but check if it already exists (we always supported running the updater on any schema) +		$sql = 'SELECT group_id +			FROM ' . GROUPS_TABLE . " +			WHERE group_name = 'NEWLY_REGISTERED'"; +		$result = $this->db->sql_query($sql); +		$group_id = (int) $this->db->sql_fetchfield('group_id'); +		$this->db->sql_freeresult($result); + +		if (!$group_id) +		{ +			$sql = 'INSERT INTO ' .  GROUPS_TABLE . " (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5)"; +			$this->sql_query($sql); + +			$group_id = $this->db->sql_nextid(); +		} + +		// Insert new user role... at the end of the chain +		$sql = 'SELECT role_id +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_name = 'ROLE_USER_NEW_MEMBER' +				AND role_type = 'u_'"; +		$result = $this->db->sql_query($sql); +		$u_role = (int) $this->db->sql_fetchfield('role_id'); +		$this->db->sql_freeresult($result); + +		if (!$u_role) +		{ +			$sql = 'SELECT MAX(role_order) as max_order_id +				FROM ' . ACL_ROLES_TABLE . " +				WHERE role_type = 'u_'"; +			$result = $this->db->sql_query($sql); +			$next_order_id = (int) $this->db->sql_fetchfield('max_order_id'); +			$this->db->sql_freeresult($result); + +			$next_order_id++; + +			$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', $next_order_id)"; +			$this->sql_query($sql); +			$u_role = $this->db->sql_nextid(); + +			// Now add the correct data to the roles... +			// The standard role says that new users are not able to send a PM, Mass PM, are not able to PM groups +			$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $u_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group')"; +			$this->sql_query($sql); + +			// Add user role to group +			$sql = 'INSERT INTO ' . ACL_GROUPS_TABLE . " (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES ($group_id, 0, 0, $u_role, 0)"; +			$this->sql_query($sql); +		} + +		// Insert new forum role +		$sql = 'SELECT role_id +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_name = 'ROLE_FORUM_NEW_MEMBER' +				AND role_type = 'f_'"; +		$result = $this->db->sql_query($sql); +		$f_role = (int) $this->db->sql_fetchfield('role_id'); +		$this->db->sql_freeresult($result); + +		if (!$f_role) +		{ +			$sql = 'SELECT MAX(role_order) as max_order_id +				FROM ' . ACL_ROLES_TABLE . " +				WHERE role_type = 'f_'"; +			$result = $this->db->sql_query($sql); +			$next_order_id = (int) $this->db->sql_fetchfield('max_order_id'); +			$this->db->sql_freeresult($result); + +			$next_order_id++; + +			$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES  ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', $next_order_id)"; +			$this->sql_query($sql); +			$f_role = $this->db->sql_nextid(); + +			$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $f_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove')"; +			$this->sql_query($sql); +		} + +		// Set every members user_new column to 0 (old users) only if there is no one yet (this makes sure we do not execute this more than once) +		$sql = 'SELECT 1 +			FROM ' . USERS_TABLE . ' +			WHERE user_new = 0'; +		$result = $this->db->sql_query_limit($sql, 1); +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		if (!$row) +		{ +			$sql = 'UPDATE ' . USERS_TABLE . ' SET user_new = 0'; +			$this->sql_query($sql); +		} + +		// To mimick the old "feature" we will assign the forum role to every forum, regardless of the setting (this makes sure there are no "this does not work!!!! YUO!!!" posts... +		// Check if the role is already assigned... +		$sql = 'SELECT forum_id +			FROM ' . ACL_GROUPS_TABLE . ' +			WHERE group_id = ' . $group_id . ' +				AND auth_role_id = ' . $f_role; +		$result = $this->db->sql_query($sql); +		$is_options = (int) $this->db->sql_fetchfield('forum_id'); +		$this->db->sql_freeresult($result); + +		// Not assigned at all... :/ +		if (!$is_options) +		{ +			// Get postable forums +			$sql = 'SELECT forum_id +				FROM ' . FORUMS_TABLE . ' +				WHERE forum_type != ' . FORUM_LINK; +			$result = $this->db->sql_query($sql); + +			while ($row = $this->db->sql_fetchrow($result)) +			{ +				$this->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (' . $group_id . ', ' . (int) $row['forum_id'] . ', 0, ' . $f_role . ', 0)'); +			} +			$this->db->sql_freeresult($result); +		} + +		// Clear permissions... +		include_once($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext); +		$auth_admin = new auth_admin(); +		$auth_admin->acl_clear_prefetch(); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_6_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_6_rc2.php new file mode 100644 index 0000000000..a939dbd489 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_6_rc2.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_6_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.6-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_6_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.6-rc2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_6_rc3.php b/phpBB/includes/db/migration/data/30x/3_0_6_rc3.php new file mode 100644 index 0000000000..b3f09d8ab8 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_6_rc3.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_6_rc3 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.6-rc3', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_6_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'update_cp_fields'))), + +			array('config.update', array('version', '3.0.6-rc3')), +		); +	} + +	public function update_cp_fields() +	{ +		// Update the Custom Profile Fields based on previous settings to the new format +		$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . ' +			SET field_show_on_vt = 1 +			WHERE field_hide = 0 +				AND (field_required = 1 OR field_show_on_reg = 1 OR field_show_profile = 1)'; +		$this->sql_query($sql); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_6_rc4.php b/phpBB/includes/db/migration/data/30x/3_0_6_rc4.php new file mode 100644 index 0000000000..fc2923f99b --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_6_rc4.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_6_rc4 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.6-rc4', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_6_rc3'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.6-rc4')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_7.php b/phpBB/includes/db/migration/data/30x/3_0_7.php new file mode 100644 index 0000000000..9ff2e9e4ab --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_7.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_7 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.7', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_7_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.7')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_7_pl1.php b/phpBB/includes/db/migration/data/30x/3_0_7_pl1.php new file mode 100644 index 0000000000..c9cc9d19ac --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_7_pl1.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_7_pl1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.7-pl1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_7'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.7-pl1')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_7_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_7_rc1.php new file mode 100644 index 0000000000..ffebf66f2d --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_7_rc1.php @@ -0,0 +1,76 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_7_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.7-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_6'); +	} + +	public function update_schema() +	{ +		return array( +			'drop_keys' => array( +				$this->table_prefix . 'log' => array( +					'log_time', +				), +			), +			'add_index' => array( +				$this->table_prefix . 'topics_track' => array( +					'topic_id' => array('topic_id'), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'add_index' => array( +				$this->table_prefix . 'log' => array( +					'log_time'	=> array('log_time'), +				), +			), +			'drop_keys' => array( +				$this->table_prefix . 'topics_track' => array( +					'topic_id', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('feed_overall', 1)), +			array('config.add', array('feed_http_auth', 0)), +			array('config.add', array('feed_limit_post', $this->config['feed_limit'])), +			array('config.add', array('feed_limit_topic', $this->config['feed_overall_topics_limit'])), +			array('config.add', array('feed_topics_new', $this->config['feed_overall_topics'])), +			array('config.add', array('feed_topics_active', $this->config['feed_overall_topics'])), +			array('custom', array(array(&$this, 'delete_text_templates'))), + +			array('config.update', array('version', '3.0.7-rc1')), +		); +	} + +	public function delete_text_templates() +	{ +		// Delete all text-templates from the template_data +		$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' +			WHERE template_filename ' . $this->db->sql_like_expression($this->db->any_char . '.txt'); +		$this->sql_query($sql); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_7_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_7_rc2.php new file mode 100644 index 0000000000..55bc2bc679 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_7_rc2.php @@ -0,0 +1,73 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_7_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.7-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_7_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'update_email_hash'))), + +			array('config.update', array('version', '3.0.7-rc2')), +		); +	} + +	public function update_email_hash($start = 0) +	{ +		$limit = 1000; + +		$sql = 'SELECT user_id, user_email, user_email_hash +			FROM ' . USERS_TABLE . ' +			WHERE user_type <> ' . USER_IGNORE . " +				AND user_email <> ''"; +		$result = $this->db->sql_query_limit($sql, $limit, $start); + +		$i = 0; +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$i++; + +			// Snapshot of the phpbb_email_hash() function +			// We cannot call it directly because the auto updater updates the DB first. :/ +			$user_email_hash = sprintf('%u', crc32(strtolower($row['user_email']))) . strlen($row['user_email']); + +			if ($user_email_hash != $row['user_email_hash']) +			{ +				$sql_ary = array( +					'user_email_hash'	=> $user_email_hash, +				); + +				$sql = 'UPDATE ' . USERS_TABLE . ' +					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +					WHERE user_id = ' . (int) $row['user_id']; +				$this->sql_query($sql); +			} +		} +		$this->db->sql_freeresult($result); + +		if ($i < $limit) +		{ +			// Completed +			return; +		} + +		// Return the next start, will be sent to $start when this function is called again +		return $start + $limit; +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_8.php b/phpBB/includes/db/migration/data/30x/3_0_8.php new file mode 100644 index 0000000000..8998ef9627 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_8.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_8 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.8', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_8_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.8')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_8_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_8_rc1.php new file mode 100644 index 0000000000..aeff35333e --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_8_rc1.php @@ -0,0 +1,221 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_8_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.8-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_7_pl1'); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array(&$this, 'update_file_extension_group_names'))), +			array('custom', array(array(&$this, 'update_module_auth'))), +			array('custom', array(array(&$this, 'update_bots'))), +			array('custom', array(array(&$this, 'delete_orphan_shadow_topics'))), +			array('module.add', array( +				'acp', +				'ACP_MESSAGES', +				array( +					'module_basename'	=> 'acp_board', +					'modes'				=> array('post'), +				), +			)), +			array('config.add', array('load_unreads_search', 1)), +			array('config.update_if_equals', array(600, 'queue_interval', 60)), +			array('config.update_if_equals', array(50, 'email_package_size', 20)), + +			array('config.update', array('version', '3.0.8-rc1')), +		); +	} + +	public function update_file_extension_group_names() +	{ +		// Update file extension group names to use language strings. +		$sql = 'SELECT lang_dir +			FROM ' . LANG_TABLE; +		$result = $this->db->sql_query($sql); + +		$extension_groups_updated = array(); +		while ($lang_dir = $this->db->sql_fetchfield('lang_dir')) +		{ +			$lang_dir = basename($lang_dir); + +			// The language strings we need are either in language/.../acp/attachments.php +			// in the update package if we're updating to 3.0.8-RC1 or later, +			// or they are in language/.../install.php when we're updating from 3.0.7-PL1 or earlier. +			// On an already updated board, they can also already be in language/.../acp/attachments.php +			// in the board root. +			$lang_files = array( +				"{$this->phpbb_root_path}install/update/new/language/$lang_dir/acp/attachments.{$this->php_ext}", +				"{$this->phpbb_root_path}language/$lang_dir/install.{$this->php_ext}", +				"{$this->phpbb_root_path}language/$lang_dir/acp/attachments.{$this->php_ext}", +			); + +			foreach ($lang_files as $lang_file) +			{ +				if (!file_exists($lang_file)) +				{ +					continue; +				} + +				$lang = array(); +				include($lang_file); + +				foreach($lang as $lang_key => $lang_val) +				{ +					if (isset($extension_groups_updated[$lang_key]) || strpos($lang_key, 'EXT_GROUP_') !== 0) +					{ +						continue; +					} + +					$sql_ary = array( +						'group_name'	=> substr($lang_key, 10), // Strip off 'EXT_GROUP_' +					); + +					$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' +						SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . " +						WHERE group_name = '" . $this->db->sql_escape($lang_val) . "'"; +					$this->sql_query($sql); + +					$extension_groups_updated[$lang_key] = true; +				} +			} +		} +		$this->db->sql_freeresult($result); +	} + +	public function update_module_auth() +	{ +		$sql = 'UPDATE ' . MODULES_TABLE . ' +			SET module_auth = \'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)\' +			WHERE module_class = \'ucp\' +				AND module_basename = \'profile\' +				AND module_mode = \'avatar\''; +		$this->sql_query($sql); +	} + +	public function update_bots() +	{ +		$bot_name = 'Bing [Bot]'; +		$bot_name_clean = utf8_clean_string($bot_name); + +		$sql = 'SELECT user_id +			FROM ' . USERS_TABLE . " +			WHERE username_clean = '" . $this->db->sql_escape($bot_name_clean) . "'"; +		$result = $this->db->sql_query($sql); +		$bing_already_added = (bool) $this->db->sql_fetchfield('user_id'); +		$this->db->sql_freeresult($result); + +		if (!$bing_already_added) +		{ +			$bot_agent = 'bingbot/'; +			$bot_ip = ''; +			$sql = 'SELECT group_id, group_colour +				FROM ' . GROUPS_TABLE . " +				WHERE group_name = 'BOTS'"; +			$result = $this->db->sql_query($sql); +			$group_row = $this->db->sql_fetchrow($result); +			$this->db->sql_freeresult($result); + +			if (!$group_row) +			{ +				// default fallback, should never get here +				$group_row['group_id'] = 6; +				$group_row['group_colour'] = '9E8DA7'; +			} + +			if (!function_exists('user_add')) +			{ +				include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext); +			} + +			$user_row = array( +				'user_type'				=> USER_IGNORE, +				'group_id'				=> $group_row['group_id'], +				'username'				=> $bot_name, +				'user_regdate'			=> time(), +				'user_password'			=> '', +				'user_colour'			=> $group_row['group_colour'], +				'user_email'			=> '', +				'user_lang'				=> $this->config['default_lang'], +				'user_style'			=> $this->config['default_style'], +				'user_timezone'			=> 0, +				'user_dateformat'		=> $this->config['default_dateformat'], +				'user_allow_massemail'	=> 0, +			); + +			$user_id = user_add($user_row); + +			$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array( +				'bot_active'	=> 1, +				'bot_name'		=> (string) $bot_name, +				'user_id'		=> (int) $user_id, +				'bot_agent'		=> (string) $bot_agent, +				'bot_ip'		=> (string) $bot_ip, +			)); + +			$this->sql_query($sql); +		} +	} + +	public function delete_orphan_shadow_topics() +	{ +		// Delete shadow topics pointing to not existing topics +		$batch_size = 500; + +		// Set of affected forums we have to resync +		$sync_forum_ids = array(); + +		$sql_array = array( +			'SELECT'	=> 't1.topic_id, t1.forum_id', +			'FROM'		=> array( +				TOPICS_TABLE	=> 't1', +			), +			'LEFT_JOIN'	=> array( +				array( +					'FROM'	=> array(TOPICS_TABLE	=> 't2'), +					'ON'	=> 't1.topic_moved_id = t2.topic_id', +				), +			), +			'WHERE'		=> 't1.topic_moved_id <> 0 +						AND t2.topic_id IS NULL', +		); +		$sql = $this->db->sql_build_query('SELECT', $sql_array); +		$result = $this->db->sql_query_limit($sql, $batch_size); + +		$topic_ids = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$topic_ids[] = (int) $row['topic_id']; + +			$sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id']; +		} +		$this->db->sql_freeresult($result); + +		if (!empty($topic_ids)) +		{ +			$sql = 'DELETE FROM ' . TOPICS_TABLE . ' +				WHERE ' . $this->db->sql_in_set('topic_id', $topic_ids); +			$this->db->sql_query($sql); + +			// Sync the forums we have deleted shadow topics from. +			sync('forum', 'forum_id', $sync_forum_ids, true, true); + +			return false; +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_9.php b/phpBB/includes/db/migration/data/30x/3_0_9.php new file mode 100644 index 0000000000..d5269ea6f0 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_9.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_9 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.9', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_9_rc4'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.9')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_9_rc1.php b/phpBB/includes/db/migration/data/30x/3_0_9_rc1.php new file mode 100644 index 0000000000..1f8622798e --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_9_rc1.php @@ -0,0 +1,124 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_9_rc1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.9-rc1', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_8'); +	} + +	public function update_schema() +	{ +		return array( +			'add_tables' => array( +				$this->table_prefix . 'login_attempts' => array( +					'COLUMNS' => array( +						// this column was removed from the database updater +						// after 3.0.9-RC3 was released. It might still exist +						// in 3.0.9-RCX installations and has to be dropped in +						// 3.0.12 after the db_tools class is capable of properly +						// removing a primary key. +						// 'attempt_id'			=> array('UINT', NULL, 'auto_increment'), +						'attempt_ip'			=> array('VCHAR:40', ''), +						'attempt_browser'		=> array('VCHAR:150', ''), +						'attempt_forwarded_for'	=> array('VCHAR:255', ''), +						'attempt_time'			=> array('TIMESTAMP', 0), +						'user_id'				=> array('UINT', 0), +						'username'				=> array('VCHAR_UNI:255', 0), +						'username_clean'		=> array('VCHAR_CI', 0), +					), +					//'PRIMARY_KEY' => 'attempt_id', +					'KEYS' => array( +						'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')), +						'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')), +						'att_time' => array('INDEX', array('attempt_time')), +						'user_id' => array('INDEX', 'user_id'), +					), +				), +			), +			'change_columns' => array( +				$this->table_prefix . 'bbcodes' => array( +					'bbcode_id' => array('USINT', 0), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_tables' => array( +				$this->table_prefix . 'login_attempts', +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('ip_login_limit_max', 50)), +			array('config.add', array('ip_login_limit_time', 21600)), +			array('config.add', array('ip_login_limit_use_forwarded', 0)), +			array('custom', array(array(&$this, 'update_file_extension_group_names'))), +			array('custom', array(array(&$this, 'fix_firebird_qa_captcha'))), + +			array('config.update', array('version', '3.0.9-rc1')), +		); +	} + +	public function update_file_extension_group_names() +	{ +		// Update file extension group names to use language strings, again. +		$sql = 'SELECT group_id, group_name +			FROM ' . EXTENSION_GROUPS_TABLE . ' +			WHERE group_name ' . $this->db->sql_like_expression('EXT_GROUP_' . $this->db->any_char); +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$sql_ary = array( +				'group_name'	=> substr($row['group_name'], 10), // Strip off 'EXT_GROUP_' +			); + +			$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' +				SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +				WHERE group_id = ' . $row['group_id']; +			$this->sql_query($sql); +		} +		$this->db->sql_freeresult($result); +	} + +	public function fix_firebird_qa_captcha() +	{ +		// Recover from potentially broken Q&A CAPTCHA table on firebird +		// Q&A CAPTCHA was uninstallable, so it's safe to remove these +		// without data loss +		if ($this->db_tools->sql_layer == 'firebird') +		{ +			$tables = array( +				$this->table_prefix . 'captcha_questions', +				$this->table_prefix . 'captcha_answers', +				$this->table_prefix . 'qa_confirm', +			); +			foreach ($tables as $table) +			{ +				if ($this->db_tools->sql_table_exists($table)) +				{ +					$this->db_tools->sql_table_drop($table); +				} +			} +		} +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_9_rc2.php b/phpBB/includes/db/migration/data/30x/3_0_9_rc2.php new file mode 100644 index 0000000000..c0e662aa45 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_9_rc2.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_9_rc2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.9-rc2', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_9_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.9-rc2')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_9_rc3.php b/phpBB/includes/db/migration/data/30x/3_0_9_rc3.php new file mode 100644 index 0000000000..d6d1f14b2e --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_9_rc3.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_9_rc3 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.9-rc3', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_9_rc2'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.9-rc3')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/30x/3_0_9_rc4.php b/phpBB/includes/db/migration/data/30x/3_0_9_rc4.php new file mode 100644 index 0000000000..e673249343 --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/3_0_9_rc4.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_3_0_9_rc4 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.0.9-rc4', '>='); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_9_rc3'); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.0.9-rc4')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/avatars.php b/phpBB/includes/db/migration/data/310/avatars.php new file mode 100644 index 0000000000..79547337f7 --- /dev/null +++ b/phpBB/includes/db/migration/data/310/avatars.php @@ -0,0 +1,67 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_avatars extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return isset($this->config['allow_avatar_gravatar']); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'change_columns'	=> array( +				$this->table_prefix . 'users'			=> array( +					'user_avatar_type'		=> array('VCHAR:255', ''), +				), +				$this->table_prefix . 'groups'			=> array( +					'group_avatar_type'		=> array('VCHAR:255', ''), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'change_columns'	=> array( +				$this->table_prefix . 'users'			=> array( +					'user_avatar_type'		=> array('TINT:2', ''), +				), +				$this->table_prefix . 'groups'			=> array( +					'group_avatar_type'		=> array('TINT:2', ''), +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('allow_avatar_gravatar', 0)), +			array('custom', array(array($this, 'update_module_auth'))), +		); +	} + +	public function update_module_auth() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . "modules +			SET module_auth = 'cfg_allow_avatar' +			WHERE module_class = 'ucp' +				AND module_basename = 'ucp_profile' +				AND module_mode = 'avatar'"; +		$this->db->sql_query($sql); +	} +} diff --git a/phpBB/includes/db/migration/data/310/boardindex.php b/phpBB/includes/db/migration/data/310/boardindex.php new file mode 100644 index 0000000000..965e32c15c --- /dev/null +++ b/phpBB/includes/db/migration/data/310/boardindex.php @@ -0,0 +1,23 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_boardindex extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return isset($this->config['board_index_text']); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('board_index_text', '')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/config_db_text.php b/phpBB/includes/db/migration/data/310/config_db_text.php new file mode 100644 index 0000000000..89f211adda --- /dev/null +++ b/phpBB/includes/db/migration/data/310/config_db_text.php @@ -0,0 +1,45 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_config_db_text extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_table_exists($this->table_prefix . 'config_text'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'add_tables' => array( +				$this->table_prefix . 'config_text' => array( +					'COLUMNS' => array( +						'config_name'	=> array('VCHAR', ''), +						'config_value'	=> array('MTEXT', ''), +					), +					'PRIMARY_KEY' => 'config_name', +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_tables' => array( +				$this->table_prefix . 'config_text', +			), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/dev.php b/phpBB/includes/db/migration/data/310/dev.php new file mode 100644 index 0000000000..13b36bbf30 --- /dev/null +++ b/phpBB/includes/db/migration/data/310/dev.php @@ -0,0 +1,405 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_dev extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.1.0-dev', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'phpbb_db_migration_data_310_extensions', +			'phpbb_db_migration_data_310_style_update_p2', +			'phpbb_db_migration_data_310_timezone_p2', +			'phpbb_db_migration_data_310_reported_posts_display', +		); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns'		=> array( +				$this->table_prefix . 'groups'		=> array( +					'group_teampage'	=> array('UINT', 0, 'after' => 'group_legend'), +				), +				$this->table_prefix . 'profile_fields'	=> array( +					'field_show_on_pm'		=> array('BOOL', 0), +				), +				$this->table_prefix . 'styles'		=> array( +					'style_path'			=> array('VCHAR:100', ''), +					'bbcode_bitfield'		=> array('VCHAR:255', 'kNg='), +					'style_parent_id'		=> array('UINT:4', 0), +					'style_parent_tree'		=> array('TEXT', ''), +				), +				$this->table_prefix . 'reports'		=> array( +					'reported_post_text'		=> array('MTEXT_UNI', ''), +					'reported_post_uid'			=> array('VCHAR:8', ''), +					'reported_post_bitfield'	=> array('VCHAR:255', ''), +				), +			), +			'change_columns'	=> array( +				$this->table_prefix . 'groups'		=> array( +					'group_legend'		=> array('UINT', 0), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns'		=> array( +				$this->table_prefix . 'groups'		=> array( +					'group_teampage', +				), +				$this->table_prefix . 'profile_fields'	=> array( +					'field_show_on_pm', +				), +				$this->table_prefix . 'styles'		=> array( +					'style_path', +					'bbcode_bitfield', +					'style_parent_id', +					'style_parent_tree', +				), +				$this->table_prefix . 'reports'		=> array( +					'reported_post_text', +					'reported_post_uid', +					'reported_post_bitfield', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('search_type', 'phpbb_search_' . $this->config['search_type'])), + +			array('config.add', array('fulltext_postgres_ts_name', 'simple')), +			array('config.add', array('fulltext_postgres_min_word_len', 4)), +			array('config.add', array('fulltext_postgres_max_word_len', 254)), +			array('config.add', array('fulltext_sphinx_stopwords', 0)), +			array('config.add', array('fulltext_sphinx_indexer_mem_limit', 512)), + +			array('config.add', array('load_jquery_cdn', 0)), +			array('config.add', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js')), + +			array('config.add', array('use_system_cron', 0)), + +			array('config.add', array('legend_sort_groupname', 0)), +			array('config.add', array('teampage_forums', 1)), +			array('config.add', array('teampage_memberships', 1)), + +			array('config.add', array('load_cpf_pm', 0)), + +			array('config.add', array('display_last_subject', 1)), + +			array('config.add', array('assets_version', 1)), + +			array('config.add', array('site_home_url', '')), +			array('config.add', array('site_home_text', '')), + +			array('permission.add', array('u_chgprofileinfo', true, 'u_sig')), + +			array('module.add', array( +				'acp', +				'ACP_GROUPS', +				array( +					'module_basename'	=> 'acp_groups', +					'modes'				=> array('position'), +				), +			)), +			array('module.add', array( +				'acp', +				'ACP_ATTACHMENTS', +				array( +					'module_basename'	=> 'acp_attachments', +					'modes'				=> array('manage'), +				), +			)), +			array('module.add', array( +				'acp', +				'ACP_STYLE_MANAGEMENT', +				array( +					'module_basename'	=> 'acp_styles', +					'modes'				=> array('install', 'cache'), +				), +			)), +			array('module.add', array( +				'ucp', +				'UCP_PROFILE', +				array( +					'module_basename'	=> 'ucp_profile', +					'modes'				=> array('autologin_keys'), +				), +			)), +			// Module will be renamed later +			array('module.add', array( +				'acp', +				'ACP_CAT_STYLES', +				'ACP_LANGUAGE' +			)), + +			array('module.remove', array( +				'acp', +				false, +				'ACP_TEMPLATES', +			)), +			array('module.remove', array( +				'acp', +				false, +				'ACP_THEMES', +			)), +			array('module.remove', array( +				'acp', +				false, +				'ACP_IMAGESETS', +			)), + +			array('custom', array(array($this, 'rename_module_basenames'))), +			array('custom', array(array($this, 'rename_styles_module'))), +			array('custom', array(array($this, 'add_group_teampage'))), +			array('custom', array(array($this, 'update_group_legend'))), +			array('custom', array(array($this, 'localise_global_announcements'))), +			array('custom', array(array($this, 'update_ucp_pm_basename'))), +			array('custom', array(array($this, 'update_ucp_profile_auth'))), +			array('custom', array(array($this, 'move_customise_modules'))), + +			array('config.update', array('version', '3.1.0-dev')), +		); +	} + +	public function move_customise_modules() +	{ +		// Move language management to new location in the Customise tab +		// First get language module id +		$sql = 'SELECT module_id FROM ' . MODULES_TABLE . " +			WHERE module_basename = 'acp_language'"; +		$result = $this->db->sql_query($sql); +		$language_module_id = $this->db->sql_fetchfield('module_id'); +		$this->db->sql_freeresult($result); +		// Next get language management module id of the one just created +		$sql = 'SELECT module_id FROM ' . MODULES_TABLE . " +			WHERE module_langname = 'ACP_LANGUAGE'"; +		$result = $this->db->sql_query($sql); +		$language_management_module_id = $this->db->sql_fetchfield('module_id'); +		$this->db->sql_freeresult($result); + +		if (!class_exists('acp_modules')) +		{ +			include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); +		} +		// acp_modules calls adm_back_link, which is undefined at this point +		if (!function_exists('adm_back_link')) +		{ +			include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext); +		} +		$module_manager = new acp_modules(); +		$module_manager->module_class = 'acp'; +		$module_manager->move_module($language_module_id, $language_management_module_id); +	} + +	public function update_ucp_pm_basename() +	{ +		$sql = 'SELECT module_id, module_basename +			FROM ' . MODULES_TABLE . " +			WHERE module_basename <> 'ucp_pm' AND +				module_langname='UCP_PM'"; +		$result = $this->db->sql_query_limit($sql, 1); + +		if ($row = $this->db->sql_fetchrow($result)) +		{ +			// This update is still not applied. Applying it + +			$sql = 'UPDATE ' . MODULES_TABLE . " +				SET module_basename = 'ucp_pm' +				WHERE  module_id = " . (int) $row['module_id']; + +			$this->sql_query($sql); +		} +		$this->db->sql_freeresult($result); +	} + +	public function update_ucp_profile_auth() +	{ +		// Update the auth setting for the module +		$sql = 'UPDATE ' . MODULES_TABLE . " +			SET module_auth = 'acl_u_chgprofileinfo' +			WHERE module_class = 'ucp' +				AND module_basename = 'ucp_profile' +				AND module_mode = 'profile_info'"; +		$this->sql_query($sql); +	} + +	public function rename_styles_module() +	{ +		// Rename styles module to Customise +		$sql = 'UPDATE ' . MODULES_TABLE . " +			SET module_langname = 'ACP_CAT_CUSTOMISE' +			WHERE module_langname = 'ACP_CAT_STYLES'"; +		$this->sql_query($sql); +	} + +	public function rename_module_basenames() +	{ +		// rename all module basenames to full classname +		$sql = 'SELECT module_id, module_basename, module_class +			FROM ' . MODULES_TABLE; +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$module_id = (int) $row['module_id']; +			unset($row['module_id']); + +			if (!empty($row['module_basename']) && !empty($row['module_class'])) +			{ +				// all the class names start with class name or with phpbb_ for auto loading +				if (strpos($row['module_basename'], $row['module_class'] . '_') !== 0 && +					strpos($row['module_basename'], 'phpbb_') !== 0) +				{ +					$row['module_basename'] = $row['module_class'] . '_' . $row['module_basename']; + +					$sql_update = $this->db->sql_build_array('UPDATE', $row); + +					$sql = 'UPDATE ' . MODULES_TABLE . ' +						SET ' . $sql_update . ' +						WHERE module_id = ' . $module_id; +					$this->sql_query($sql); +				} +			} +		} + +		$this->db->sql_freeresult($result); +	} + +	public function add_group_teampage() +	{ +		$sql = 'UPDATE ' . GROUPS_TABLE . ' +			SET group_teampage = 1 +			WHERE group_type = ' . GROUP_SPECIAL . " +				AND group_name = 'ADMINISTRATORS'"; +		$this->sql_query($sql); + +		$sql = 'UPDATE ' . GROUPS_TABLE . ' +			SET group_teampage = 2 +			WHERE group_type = ' . GROUP_SPECIAL . " +				AND group_name = 'GLOBAL_MODERATORS'"; +		$this->sql_query($sql); +	} + +	public function update_group_legend() +	{ +		$sql = 'SELECT group_id +			FROM ' . GROUPS_TABLE . ' +			WHERE group_legend = 1 +			ORDER BY group_name ASC'; +		$result = $this->db->sql_query($sql); + +		$next_legend = 1; +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$sql = 'UPDATE ' . GROUPS_TABLE . ' +				SET group_legend = ' . $next_legend . ' +				WHERE group_id = ' . (int) $row['group_id']; +			$this->sql_query($sql); + +			$next_legend++; +		} +		$this->db->sql_freeresult($result); +	} + +	public function localise_global_announcements() +	{ +		// Localise Global Announcements +		$sql = 'SELECT topic_id, topic_approved, (topic_replies + 1) AS topic_posts, topic_last_post_id, topic_last_post_subject, topic_last_post_time, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour +			FROM ' . TOPICS_TABLE . ' +			WHERE forum_id = 0 +				AND topic_type = ' . POST_GLOBAL; +		$result = $this->db->sql_query($sql); + +		$global_announcements = $update_lastpost_data = array(); +		$update_lastpost_data['forum_last_post_time'] = 0; +		$update_forum_data = array( +			'forum_posts'		=> 0, +			'forum_topics'		=> 0, +			'forum_topics_real'	=> 0, +		); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$global_announcements[] = (int) $row['topic_id']; + +			$update_forum_data['forum_posts'] += (int) $row['topic_posts']; +			$update_forum_data['forum_topics_real']++; +			if ($row['topic_approved']) +			{ +				$update_forum_data['forum_topics']++; +			} + +			if ($update_lastpost_data['forum_last_post_time'] < $row['topic_last_post_time']) +			{ +				$update_lastpost_data = array( +					'forum_last_post_id'		=> (int) $row['topic_last_post_id'], +					'forum_last_post_subject'	=> $row['topic_last_post_subject'], +					'forum_last_post_time'		=> (int) $row['topic_last_post_time'], +					'forum_last_poster_id'		=> (int) $row['topic_last_poster_id'], +					'forum_last_poster_name'	=> $row['topic_last_poster_name'], +					'forum_last_poster_colour'	=> $row['topic_last_poster_colour'], +				); +			} +		} +		$this->db->sql_freeresult($result); + +		if (!empty($global_announcements)) +		{ +			// Update the post/topic-count for the forum and the last-post if needed +			$sql = 'SELECT forum_id +				FROM ' . FORUMS_TABLE . ' +				WHERE forum_type = ' . FORUM_POST; +			$result = $this->db->sql_query_limit($sql, 1); +			$ga_forum_id = $this->db->sql_fetchfield('forum_id'); +			$this->db->sql_freeresult($result); + +			$sql = 'SELECT forum_last_post_time +				FROM ' . FORUMS_TABLE . ' +				WHERE forum_id = ' . $ga_forum_id; +			$result = $this->db->sql_query($sql); +			$lastpost = (int) $this->db->sql_fetchfield('forum_last_post_time'); +			$this->db->sql_freeresult($result); + +			$sql_update = 'forum_posts = forum_posts + ' . $update_forum_data['forum_posts'] . ', '; +			$sql_update .= 'forum_topics_real = forum_topics_real + ' . $update_forum_data['forum_topics_real'] . ', '; +			$sql_update .= 'forum_topics = forum_topics + ' . $update_forum_data['forum_topics']; +			if ($lastpost < $update_lastpost_data['forum_last_post_time']) +			{ +				$sql_update .= ', ' . $this->db->sql_build_array('UPDATE', $update_lastpost_data); +			} + +			$sql = 'UPDATE ' . FORUMS_TABLE . ' +				SET ' . $sql_update . ' +				WHERE forum_id = ' . $ga_forum_id; +			$this->sql_query($sql); + +			// Update some forum_ids +			$table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); +			foreach ($table_ary as $table) +			{ +				$sql = "UPDATE $table +					SET forum_id = $ga_forum_id +					WHERE " . $this->db->sql_in_set('topic_id', $global_announcements); +				$this->sql_query($sql); +			} +			unset($table_ary); +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/extensions.php b/phpBB/includes/db/migration/data/310/extensions.php new file mode 100644 index 0000000000..6a9caa1cfc --- /dev/null +++ b/phpBB/includes/db/migration/data/310/extensions.php @@ -0,0 +1,69 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_extensions extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_table_exists($this->table_prefix . 'ext'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'add_tables'		=> array( +				$this->table_prefix . 'ext'	=> array( +					'COLUMNS'			=> array( +						'ext_name'		=> array('VCHAR', ''), +						'ext_active'	=> array('BOOL', 0), +						'ext_state'		=> array('TEXT', ''), +					), +					'KEYS'				=> array( +						'ext_name'		=> array('UNIQUE', 'ext_name'), +					), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_tables'		=> array( +				$this->table_prefix . 'ext', +			), +		); +	} + +	public function update_data() +	{ +		return array( +			// Module will be renamed later +			array('module.add', array( +				'acp', +				'ACP_CAT_STYLES', +				'ACP_EXTENSION_MANAGEMENT' +			)), +			array('module.add', array( +				'acp', +				'ACP_EXTENSION_MANAGEMENT', +				array( +					'module_basename'	=> 'acp_extensions', +					'modes'				=> array('main'), +				), +			)), +			array('permission.add', array('a_extensions', true, 'a_styles')), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/forgot_password.php b/phpBB/includes/db/migration/data/310/forgot_password.php new file mode 100644 index 0000000000..a553e51f35 --- /dev/null +++ b/phpBB/includes/db/migration/data/310/forgot_password.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_forgot_password extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return isset($this->config['allow_password_reset']); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_data() +	{ +		return array( +			array('config.add', array('allow_password_reset', 1)), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/jquery_update.php b/phpBB/includes/db/migration/data/310/jquery_update.php new file mode 100644 index 0000000000..dc49f74fcb --- /dev/null +++ b/phpBB/includes/db/migration/data/310/jquery_update.php @@ -0,0 +1,31 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_jquery_update extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'; +	} + +	static public function depends_on() +	{ +		return array( +			'phpbb_db_migration_data_310_dev', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js')), +		); +	} + +} diff --git a/phpBB/includes/db/migration/data/310/notifications.php b/phpBB/includes/db/migration/data/310/notifications.php new file mode 100644 index 0000000000..82bfd4cb2d --- /dev/null +++ b/phpBB/includes/db/migration/data/310/notifications.php @@ -0,0 +1,160 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_notifications extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_table_exists($this->table_prefix . 'notifications'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_310_dev'); +	} + +	public function update_schema() +	{ +		return array( +			'add_tables'		=> array( +				$this->table_prefix . 'notification_types'	=> array( +					'COLUMNS'			=> array( +						'notification_type'			=> array('VCHAR:255', ''), +						'notification_type_enabled'	=> array('BOOL', 1), +					), +					'PRIMARY_KEY'		=> array('notification_type', 'notification_type_enabled'), +				), +				$this->table_prefix . 'notifications'		=> array( +					'COLUMNS'			=> array( +						'notification_id'  				=> array('UINT', NULL, 'auto_increment'), +						'item_type'			   			=> array('VCHAR:255', ''), +						'item_id'		  				=> array('UINT', 0), +						'item_parent_id'   				=> array('UINT', 0), +						'user_id'						=> array('UINT', 0), +						'notification_read'				=> array('BOOL', 0), +						'notification_time'				=> array('TIMESTAMP', 1), +						'notification_data'			   	=> array('TEXT_UNI', ''), +					), +					'PRIMARY_KEY'		=> 'notification_id', +					'KEYS'				=> array( +						'item_ident'		=> array('INDEX', array('item_type', 'item_id')), +						'user'				=> array('INDEX', array('user_id', 'notification_read')), +					), +				), +				$this->table_prefix . 'user_notifications'	=> array( +					'COLUMNS'			=> array( +						'item_type'			=> array('VCHAR:255', ''), +						'item_id'			=> array('UINT', 0), +						'user_id'			=> array('UINT', 0), +						'method'			=> array('VCHAR:255', ''), +						'notify'			=> array('BOOL', 1), +					), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_tables'	=> array( +				$this->table_prefix . 'notification_types', +				$this->table_prefix . 'notifications', +				$this->table_prefix . 'user_notifications', +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('module.add', array( +				'ucp', +				'UCP_MAIN', +				array( +					'module_basename'	=> 'ucp_notifications', +					'modes'				=> array('notification_list'), +				), +			)), +			array('module.add', array( +				'ucp', +				'UCP_PREFS', +				array( +					'module_basename'	=> 'ucp_notifications', +					'modes'				=> array('notification_options'), +				), +			)), +			array('config.add', array('load_notifications', 1)), +			array('custom', array(array($this, 'convert_notifications'))), +		); +	} + +	public function convert_notifications() +	{ +		$convert_notifications = array( +			array( +				'check'			=> ($this->config['allow_topic_notify']), +				'item_type'		=> 'post', +			), +			array( +				'check'			=> ($this->config['allow_forum_notify']), +				'item_type'		=> 'topic', +			), +			array( +				'check'			=> ($this->config['allow_bookmarks']), +				'item_type'		=> 'bookmark', +			), +			array( +				'check'			=> ($this->config['allow_privmsg']), +				'item_type'		=> 'pm', +			), +		); + +		foreach ($convert_notifications as $convert_data) +		{ +			if ($convert_data['check']) +			{ +				$sql = 'SELECT user_id, user_notify_type +					FROM ' . USERS_TABLE . ' +						WHERE user_notify = 1'; +				$result = $this->db->sql_query($sql); +				while ($row = $this->db->sql_fetchrow($result)) +				{ +					$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array( +						'item_type'		=> $convert_data['item_type'], +						'item_id'		=> 0, +						'user_id'		=> $row['user_id'], +						'method'		=> '', +					))); + +					if ($row['user_notify_type'] == NOTIFY_EMAIL || $row['user_notify_type'] == NOTIFY_BOTH) +					{ +						$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array( +							'item_type'		=> $convert_data['item_type'], +							'item_id'		=> 0, +							'user_id'		=> $row['user_id'], +							'method'		=> 'email', +						))); +					} + +					if ($row['user_notify_type'] == NOTIFY_IM || $row['user_notify_type'] == NOTIFY_BOTH) +					{ +						$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array( +							'item_type'		=> $convert_data['item_type'], +							'item_id'		=> 0, +							'user_id'		=> $row['user_id'], +							'method'		=> 'jabber', +						))); +					} +				} +				$this->db->sql_freeresult($result); +			} +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/reported_posts_display.php b/phpBB/includes/db/migration/data/310/reported_posts_display.php new file mode 100644 index 0000000000..80a0a0e43f --- /dev/null +++ b/phpBB/includes/db/migration/data/310/reported_posts_display.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_reported_posts_display extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_column_exists($this->table_prefix . 'reports', 'reported_post_enable_bbcode'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns'		=> array( +				$this->table_prefix . 'reports'		=> array( +					'reported_post_enable_bbcode'		=> array('BOOL', 1), +					'reported_post_enable_smilies'		=> array('BOOL', 1), +					'reported_post_enable_magic_url'	=> array('BOOL', 1), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns'		=> array( +				$this->table_prefix . 'reports'		=> array( +					'reported_post_enable_bbcode', +					'reported_post_enable_smilies', +					'reported_post_enable_magic_url', +				), +			), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/style_update_p1.php b/phpBB/includes/db/migration/data/310/style_update_p1.php new file mode 100644 index 0000000000..d43537559d --- /dev/null +++ b/phpBB/includes/db/migration/data/310/style_update_p1.php @@ -0,0 +1,185 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return !$this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns'	=> array( +				$this->table_prefix . 'styles'		=> array( +					'style_path'			=> array('VCHAR:100', ''), +					'bbcode_bitfield'		=> array('VCHAR:255', 'kNg='), +					'style_parent_id'		=> array('UINT', 0), +					'style_parent_tree'		=> array('TEXT', ''), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns'	=> array( +				$this->table_prefix . 'styles'		=> array( +					'style_path', +					'bbcode_bitfield', +					'style_parent_id', +					'style_parent_tree', +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array($this, 'styles_update'))), +		); +	} + +	public function styles_update() +	{ +		// Get list of valid 3.1 styles +		$available_styles = array('prosilver'); + +		$iterator = new DirectoryIterator($this->phpbb_root_path . 'styles'); +		$skip_dirs = array('.', '..', 'prosilver'); +		foreach ($iterator as $fileinfo) +		{ +			if ($fileinfo->isDir() && !in_array($fileinfo->getFilename(), $skip_dirs) && file_exists($fileinfo->getPathname() . '/style.cfg')) +			{ +				$style_cfg = parse_cfg_file($fileinfo->getPathname() . '/style.cfg'); +				if (isset($style_cfg['phpbb_version']) && version_compare($style_cfg['phpbb_version'], '3.1.0-dev', '>=')) +				{ +					// 3.1 style +					$available_styles[] = $fileinfo->getFilename(); +				} +			} +		} + +		// Get all installed styles +		if ($this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset')) +		{ +			$sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_id, i.imageset_path +				FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . 'styles_theme c, ' . $this->table_prefix . "styles_imageset i +				WHERE t.template_id = s.template_id +					AND c.theme_id = s.theme_id +					AND i.imageset_id = s.imageset_id"; +		} +		else +		{ +			$sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_id +				FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . "stles_theme c +				WHERE t.template_id = s.template_id +					AND c.theme_id = s.theme_id"; +		} +		$result = $this->db->sql_query($sql); + +		$styles = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$styles[] = $row; +		} +		$this->db->sql_freeresult($result); + +		// Decide which styles to keep, all others will be deleted +		$valid_styles = array(); +		foreach ($styles as $style_row) +		{ +			if ( +				// Delete styles with parent style (not supported yet) +				$style_row['template_inherits_id'] == 0 && +				// Check if components match +				$style_row['template_path'] == $style_row['theme_path'] && (!isset($style_row['imageset_path']) || $style_row['template_path'] == $style_row['imageset_path']) && +				// Check if components are valid +				in_array($style_row['template_path'], $available_styles) +				) +			{ +				// Valid style. Keep it +				$sql_ary = array( +					'style_path'	=> $style_row['template_path'], +					'bbcode_bitfield'	=> $style_row['bbcode_bitfield'], +					'style_parent_id'	=> 0, +					'style_parent_tree'	=> '', +				); +				$this->sql_query('UPDATE ' . STYLES_TABLE . ' +					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +					WHERE style_id = ' . $style_row['style_id']); +				$valid_styles[] = (int) $style_row['style_id']; +			} +		} + +		// Remove old entries from styles table +		if (!sizeof($valid_styles)) +		{ +			// No valid styles: remove everything and add prosilver +			$this->sql_query('DELETE FROM ' . STYLES_TABLE, $errored, $error_ary); + +			$sql_ary = array( +				'style_name'		=> 'prosilver', +				'style_copyright'	=> '© phpBB Group', +				'style_active'		=> 1, +				'style_path'		=> 'prosilver', +				'bbcode_bitfield'	=> 'lNg=', +				'style_parent_id'	=> 0, +				'style_parent_tree'	=> '', + +				// Will be removed in the next step +				'imageset_id'		=> 0, +				'template_id'		=> 0, +				'theme_id'			=> 0, +			); + +			$sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); +			$this->sql_query($sql); + +			$sql = 'SELECT style_id +				FROM ' . $table . " +				WHERE style_name = 'prosilver'"; +			$result = $this->sql_query($sql); +			$default_style = $this->db->sql_fetchfield($result); +			$this->db->sql_freeresult($result); + +			set_config('default_style', $default_style); + +			$sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = 0'; +			$this->sql_query($sql); +		} +		else +		{ +			// There are valid styles in styles table. Remove styles that are outdated +			$this->sql_query('DELETE FROM ' . STYLES_TABLE . ' +				WHERE ' . $this->db->sql_in_set('style_id', $valid_styles, true)); + +			// Change default style +			if (!in_array($this->config['default_style'], $valid_styles)) +			{ +				$this->sql_query('UPDATE ' . CONFIG_TABLE . " +					SET config_value = '" . $valid_styles[0] . "' +					WHERE config_name = 'default_style'"); +			} + +			// Reset styles for users +			$this->sql_query('UPDATE ' . USERS_TABLE . ' +				SET user_style = 0 +				WHERE ' . $this->db->sql_in_set('user_style', $valid_styles, true)); +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/style_update_p2.php b/phpBB/includes/db/migration/data/310/style_update_p2.php new file mode 100644 index 0000000000..7b10518a66 --- /dev/null +++ b/phpBB/includes/db/migration/data/310/style_update_p2.php @@ -0,0 +1,129 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return !$this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_310_style_update_p1'); +	} + +	public function update_schema() +	{ +		return array( +			'drop_columns'	=> array( +				$this->table_prefix . 'styles'		=> array( +					'imageset_id', +					'template_id', +					'theme_id', +				), +			), + +			'drop_tables'	=> array( +				$this->table_prefix . 'styles_imageset', +				$this->table_prefix . 'styles_imageset_data', +				$this->table_prefix . 'styles_template', +				$this->table_prefix . 'styles_template_data', +				$this->table_prefix . 'styles_theme', +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'add_columns'	=> array( +				$this->table_prefix . 'styles'		=> array( +					'imageset_id'	=> array('UINT', 0), +					'template_id'	=> array('UINT', 0), +					'theme_id'		=> array('UINT', 0), +				), +			), + +			'add_tables'	=> array( +				$this->table_prefix . 'styles_imageset'		=> array( +					'COLUMNS'		=> array( +						'imageset_id'				=> array('UINT', NULL, 'auto_increment'), +						'imageset_name'				=> array('VCHAR_UNI:255', ''), +						'imageset_copyright'		=> array('VCHAR_UNI', ''), +						'imageset_path'				=> array('VCHAR:100', ''), +					), +					'PRIMARY_KEY'		=> 'imageset_id', +					'KEYS'				=> array( +						'imgset_nm'			=> array('UNIQUE', 'imageset_name'), +					), +				), +				$this->table_prefix . 'styles_imageset_data'	=> array( +					'COLUMNS'		=> array( +						'image_id'				=> array('UINT', NULL, 'auto_increment'), +						'image_name'			=> array('VCHAR:200', ''), +						'image_filename'		=> array('VCHAR:200', ''), +						'image_lang'			=> array('VCHAR:30', ''), +						'image_height'			=> array('USINT', 0), +						'image_width'			=> array('USINT', 0), +						'imageset_id'			=> array('UINT', 0), +					), +					'PRIMARY_KEY'		=> 'image_id', +					'KEYS'				=> array( +						'i_d'			=> array('INDEX', 'imageset_id'), +					), +				), +				$this->table_prefix . 'styles_template'		=> array( +					'COLUMNS'		=> array( +						'template_id'			=> array('UINT', NULL, 'auto_increment'), +						'template_name'			=> array('VCHAR_UNI:255', ''), +						'template_copyright'	=> array('VCHAR_UNI', ''), +						'template_path'			=> array('VCHAR:100', ''), +						'bbcode_bitfield'		=> array('VCHAR:255', 'kNg='), +						'template_storedb'		=> array('BOOL', 0), +						'template_inherits_id'		=> array('UINT:4', 0), +						'template_inherit_path'		=> array('VCHAR', ''), +					), +					'PRIMARY_KEY'	=> 'template_id', +					'KEYS'			=> array( +						'tmplte_nm'				=> array('UNIQUE', 'template_name'), +					), +				), +				$this->table_prefix . 'styles_template_data'	=> array( +					'COLUMNS'		=> array( +						'template_id'			=> array('UINT', 0), +						'template_filename'		=> array('VCHAR:100', ''), +						'template_included'		=> array('TEXT', ''), +						'template_mtime'		=> array('TIMESTAMP', 0), +						'template_data'			=> array('MTEXT_UNI', ''), +					), +					'KEYS'			=> array( +						'tid'					=> array('INDEX', 'template_id'), +						'tfn'					=> array('INDEX', 'template_filename'), +					), +				), +				$this->table_prefix . 'styles_theme'			=> array( +					'COLUMNS'		=> array( +						'theme_id'				=> array('UINT', NULL, 'auto_increment'), +						'theme_name'			=> array('VCHAR_UNI:255', ''), +						'theme_copyright'		=> array('VCHAR_UNI', ''), +						'theme_path'			=> array('VCHAR:100', ''), +						'theme_storedb'			=> array('BOOL', 0), +						'theme_mtime'			=> array('TIMESTAMP', 0), +						'theme_data'			=> array('MTEXT_UNI', ''), +					), +					'PRIMARY_KEY'	=> 'theme_id', +					'KEYS'			=> array( +						'theme_name'		=> array('UNIQUE', 'theme_name'), +					), +				), +			), +		); +	} +} diff --git a/phpBB/includes/db/migration/data/310/teampage.php b/phpBB/includes/db/migration/data/310/teampage.php new file mode 100644 index 0000000000..4e77da17b7 --- /dev/null +++ b/phpBB/includes/db/migration/data/310/teampage.php @@ -0,0 +1,104 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_teampage extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_table_exists($this->table_prefix . 'teampage'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_310_dev'); +	} + +	public function update_schema() +	{ +		return array( +			'add_tables'		=> array( +				$this->table_prefix . 'teampage'	=> array( +					'COLUMNS'		=> array( +						'teampage_id'		=> array('UINT', NULL, 'auto_increment'), +						'group_id'			=> array('UINT', 0), +						'teampage_name'		=> array('VCHAR_UNI:255', ''), +						'teampage_position'	=> array('UINT', 0), +						'teampage_parent'	=> array('UINT', 0), +					), +					'PRIMARY_KEY'		=> 'teampage_id', +				), +			), +			'drop_columns'		=> array( +				$this->table_prefix . 'groups'		=> array( +					'group_teampage', +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_tables'		=> array( +				$this->table_prefix . 'teampage', +			), +			'add_columns'		=> array( +				$this->table_prefix . 'groups'		=> array( +					'group_teampage'	=> array('UINT', 0, 'after' => 'group_legend'), +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array($this, 'add_groups_teampage'))), +		); +	} + +	public function add_groups_teampage() +	{ +		$sql = 'SELECT teampage_id +			FROM ' . TEAMPAGE_TABLE; +		$result = $this->db->sql_query_limit($sql, 1); +		$added_groups_teampage = (bool) $this->db->sql_fetchfield('teampage_id'); +		$this->db->sql_freeresult($result); + +		if (!$added_groups_teampage) +		{ +			$sql = 'SELECT * +				FROM ' . GROUPS_TABLE . ' +				WHERE group_type = ' . GROUP_SPECIAL . " +					AND (group_name = 'ADMINISTRATORS' +						OR group_name = 'GLOBAL_MODERATORS') +				ORDER BY group_name ASC"; +			$result = $this->db->sql_query($sql); + +			$teampage_entries = array(); +			while ($row = $this->db->sql_fetchrow($result)) +			{ +				$teampage_entries[] = array( +					'group_id'			=> (int) $row['group_id'], +					'teampage_name'		=> '', +					'teampage_position'	=> sizeof($teampage_entries) + 1, +					'teampage_parent'	=> 0, +				); +			} +			$this->db->sql_freeresult($result); + +			if (sizeof($teampage_entries)) +			{ +				$this->db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_entries); +			} +			unset($teampage_entries); +		} + +	} +} diff --git a/phpBB/includes/db/migration/data/310/timezone.php b/phpBB/includes/db/migration/data/310/timezone.php new file mode 100644 index 0000000000..6e50cbe45f --- /dev/null +++ b/phpBB/includes/db/migration/data/310/timezone.php @@ -0,0 +1,163 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_timezone extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_dst'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_30x_3_0_11'); +	} + +	public function update_schema() +	{ +		return array( +			'change_columns'	=> array( +				$this->table_prefix . 'users'			=> array( +					'user_timezone'		=> array('VCHAR:100', ''), +				), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array($this, 'update_timezones'))), +		); +	} + +	public function update_timezones() +	{ +		// Update user timezones +		$sql = 'SELECT user_dst, user_timezone +			FROM ' . $this->table_prefix . 'users +			GROUP BY user_timezone, user_dst'; +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$sql = 'UPDATE ' . $this->table_prefix . "users +				SET user_timezone = '" . $this->db->sql_escape($this->convert_phpbb30_timezone($row['user_timezone'], $row['user_dst'])) . "' +				WHERE user_timezone = '" . $this->db->sql_escape($row['user_timezone']) . "' +					AND user_dst = " . (int) $row['user_dst']; +			$this->sql_query($sql); +		} +		$this->db->sql_freeresult($result); + +		// Update board default timezone +		$sql = 'UPDATE ' . $this->table_prefix . "config +			SET config_value = '" . $this->convert_phpbb30_timezone($this->config['board_timezone'], $this->config['board_dst']) . "' +			WHERE config_name = 'board_timezone'"; +		$this->sql_query($sql); +	} + +	/** +	* Determine the new timezone for a given phpBB 3.0 timezone and +	* "Daylight Saving Time" option +	* +	*	@param	$timezone	float	Users timezone in 3.0 +	*	@param	$dst		int		Users daylight saving time +	*	@return		string		Users new php Timezone which is used since 3.1 +	*/ +	public function convert_phpbb30_timezone($timezone, $dst) +	{ +		$offset = $timezone + $dst; + +		switch ($timezone) +		{ +			case '-12': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 12] Baker Island Time' +			case '-11': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 11] Niue Time, Samoa Standard Time' +			case '-10': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 10] Hawaii-Aleutian Standard Time, Cook Island Time' +			case '-9.5': +				return 'Pacific/Marquesas';			//'[UTC - 9:30] Marquesas Islands Time' +			case '-9': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 9] Alaska Standard Time, Gambier Island Time' +			case '-8': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 8] Pacific Standard Time' +			case '-7': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 7] Mountain Standard Time' +			case '-6': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 6] Central Standard Time' +			case '-5': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 5] Eastern Standard Time' +			case '-4.5': +				return 'America/Caracas';			//'[UTC - 4:30] Venezuelan Standard Time' +			case '-4': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 4] Atlantic Standard Time' +			case '-3.5': +				return 'America/St_Johns';			//'[UTC - 3:30] Newfoundland Standard Time' +			case '-3': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 3] Amazon Standard Time, Central Greenland Time' +			case '-2': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 2] Fernando de Noronha Time, South Georgia & the South Sandwich Islands Time' +			case '-1': +				return 'Etc/GMT+' . abs($offset);	//'[UTC - 1] Azores Standard Time, Cape Verde Time, Eastern Greenland Time' +			case '0': +				return (!$dst) ? 'UTC' : 'Etc/GMT-1';	//'[UTC] Western European Time, Greenwich Mean Time' +			case '1': +				return 'Etc/GMT-' . $offset;		//'[UTC + 1] Central European Time, West African Time' +			case '2': +				return 'Etc/GMT-' . $offset;		//'[UTC + 2] Eastern European Time, Central African Time' +			case '3': +				return 'Etc/GMT-' . $offset;		//'[UTC + 3] Moscow Standard Time, Eastern African Time' +			case '3.5': +				return 'Asia/Tehran';				//'[UTC + 3:30] Iran Standard Time' +			case '4': +				return 'Etc/GMT-' . $offset;		//'[UTC + 4] Gulf Standard Time, Samara Standard Time' +			case '4.5': +				return 'Asia/Kabul';				//'[UTC + 4:30] Afghanistan Time' +			case '5': +				return 'Etc/GMT-' . $offset;		//'[UTC + 5] Pakistan Standard Time, Yekaterinburg Standard Time' +			case '5.5': +				return 'Asia/Kolkata';				//'[UTC + 5:30] Indian Standard Time, Sri Lanka Time' +			case '5.75': +				return 'Asia/Kathmandu';			//'[UTC + 5:45] Nepal Time' +			case '6': +				return 'Etc/GMT-' . $offset;		//'[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirsk Standard Time' +			case '6.5': +				return 'Indian/Cocos';				//'[UTC + 6:30] Cocos Islands Time, Myanmar Time' +			case '7': +				return 'Etc/GMT-' . $offset;		//'[UTC + 7] Indochina Time, Krasnoyarsk Standard Time' +			case '8': +				return 'Etc/GMT-' . $offset;		//'[UTC + 8] Chinese Standard Time, Australian Western Standard Time, Irkutsk Standard Time' +			case '8.75': +				return 'Australia/Eucla';			//'[UTC + 8:45] Southeastern Western Australia Standard Time' +			case '9': +				return 'Etc/GMT-' . $offset;		//'[UTC + 9] Japan Standard Time, Korea Standard Time, Chita Standard Time' +			case '9.5': +				return 'Australia/ACT';				//'[UTC + 9:30] Australian Central Standard Time' +			case '10': +				return 'Etc/GMT-' . $offset;		//'[UTC + 10] Australian Eastern Standard Time, Vladivostok Standard Time' +			case '10.5': +				return 'Australia/Lord_Howe';		//'[UTC + 10:30] Lord Howe Standard Time' +			case '11': +				return 'Etc/GMT-' . $offset;		//'[UTC + 11] Solomon Island Time, Magadan Standard Time' +			case '11.5': +				return 'Pacific/Norfolk';			//'[UTC + 11:30] Norfolk Island Time' +			case '12': +				return 'Etc/GMT-12';				//'[UTC + 12] New Zealand Time, Fiji Time, Kamchatka Standard Time' +			case '12.75': +				return 'Pacific/Chatham';			//'[UTC + 12:45] Chatham Islands Time' +			case '13': +				return 'Pacific/Tongatapu';			//'[UTC + 13] Tonga Time, Phoenix Islands Time' +			case '14': +				return 'Pacific/Kiritimati';		//'[UTC + 14] Line Island Time' +			default: +				return 'UTC'; +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/timezone_p2.php b/phpBB/includes/db/migration/data/310/timezone_p2.php new file mode 100644 index 0000000000..113b979e4f --- /dev/null +++ b/phpBB/includes/db/migration/data/310/timezone_p2.php @@ -0,0 +1,43 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_timezone_p2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_dst'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_310_timezone'); +	} + +	public function update_schema() +	{ +		return array( +			'drop_columns'	=> array( +				$this->table_prefix . 'users'			=> array( +					'user_dst', +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'add_columns'	=> array( +				$this->table_prefix . 'users'			=> array( +					'user_dst'		=> array('BOOL', 0), +				), +			), +		); +	} +} diff --git a/phpBB/includes/db/migration/exception.php b/phpBB/includes/db/migration/exception.php new file mode 100644 index 0000000000..e84330dd71 --- /dev/null +++ b/phpBB/includes/db/migration/exception.php @@ -0,0 +1,79 @@ +<?php +/** +* +* @package db +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* The migrator is responsible for applying new migrations in the correct order. +* +* @package db +*/ +class phpbb_db_migration_exception extends \Exception +{ +	/** +	* Extra parameters sent to exception to aid in debugging +	* @var array +	*/ +	protected $parameters; + +	/** +	* Throw an exception. +	* +	* First argument is the error message. +	* Additional arguments will be output with the error message. +	*/ +	public function __construct() +	{ +		$parameters = func_get_args(); +		$message = array_shift($parameters); +		parent::__construct($message); + +		$this->parameters = $parameters; +	} + +	/** +	* Output the error as a string +	* +	* @return string +	*/ +	public function __toString() +	{ +		return $this->message . ': ' . var_export($this->parameters, true); +	} + +	/** +	* Get the parameters +	* +	* @return array +	*/ +	public function getParameters() +	{ +		return $this->parameters; +	} + +	/** +	* Get localised message (with $user->lang())  +	*  +	* @param phpbb_user $user +	* @return string +	*/ +	public function getLocalisedMessage(phpbb_user $user) +	{ +		$parameters = $this->getParameters(); +		array_unshift($parameters, $this->getMessage()); + +		return call_user_func_array(array($user, 'lang'), $parameters); +	} +} diff --git a/phpBB/includes/db/migration/migration.php b/phpBB/includes/db/migration/migration.php new file mode 100644 index 0000000000..5f14a6953c --- /dev/null +++ b/phpBB/includes/db/migration/migration.php @@ -0,0 +1,190 @@ +<?php +/** +* +* @package db +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Abstract base class for database migrations +* +* Each migration consists of a set of schema and data changes to be implemented +* in a subclass. This class provides various utility methods to simplify editing +* a phpBB. +* +* @package db +*/ +abstract class phpbb_db_migration +{ +	/** @var phpbb_config */ +	protected $config; + +	/** @var phpbb_db_driver */ +	protected $db; + +	/** @var phpbb_db_tools */ +	protected $db_tools; + +	/** @var string */ +	protected $table_prefix; + +	/** @var string */ +	protected $phpbb_root_path; + +	/** @var string */ +	protected $php_ext; + +	/** @var array Errors, if any occured */ +	protected $errors; + +	/** @var array List of queries executed through $this->sql_query() */ +	protected $queries = array(); + +	/** +	* Constructor +	* +	* @param phpbb_config $config +	* @param phpbb_db_driver $db +	* @param phpbb_db_tools $db_tools +	* @param string $phpbb_root_path +	* @param string $php_ext +	* @param string $table_prefix +	*/ +	public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) +	{ +		$this->config = $config; +		$this->db = $db; +		$this->db_tools = $db_tools; +		$this->table_prefix = $table_prefix; + +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $php_ext; + +		$this->errors = array(); +	} + +	/** +	* Defines other migrations to be applied first +	* +	* @return array An array of migration class names +	*/ +	static public function depends_on() +	{ +		return array(); +	} + +	/** +	* Allows you to check if the migration is effectively installed (entirely optional) +	* +	* This is checked when a migration is installed. If true is returned, the migration will be set as +	* installed without performing the database changes. +	* This function is intended to help moving to migrations from a previous database updater, where some +	* migrations may have been installed already even though they are not yet listed in the migrations table. +	* +	* @return bool True if this migration is installed, False if this migration is not installed (checked on install) +	*/ +	public function effectively_installed() +	{ +		return false; +	} + +	/** +	* Updates the database schema by providing a set of change instructions +	* +	* @return array Array of schema changes (compatible with db_tools->perform_schema_changes()) +	*/ +	public function update_schema() +	{ +		return array(); +	} + +	/** +	* Reverts the database schema by providing a set of change instructions +	* +	* @return array Array of schema changes (compatible with db_tools->perform_schema_changes()) +	*/ +	public function revert_schema() +	{ +		return array(); +	} + +	/** +	* Updates data by returning a list of instructions to be executed +	* +	* @return array Array of data update instructions +	*/ +	public function update_data() +	{ +		return array(); +	} + +	/** +	* Reverts data by returning a list of instructions to be executed +	* +	* @return array Array of data instructions that will be performed on revert +	* 	NOTE: calls to tools (such as config.add) are automatically reverted when +	* 		possible, so you should not attempt to revert those, this is mostly for +	* 		otherwise unrevertable calls (custom functions for example) +	*/ +	public function revert_data() +	{ +		return array(); +	} + +	/** +	* Wrapper for running queries to generate user feedback on updates +	* +	* @param string $sql SQL query to run on the database +	* @return mixed Query result from db->sql_query() +	*/ +	protected function sql_query($sql) +	{ +		$this->queries[] = $sql; + +		$this->db->sql_return_on_error(true); + +		if ($sql === 'begin') +		{ +			$result = $this->db->sql_transaction('begin'); +		} +		else if ($sql === 'commit') +		{ +			$result = $this->db->sql_transaction('commit'); +		} +		else +		{ +			$result = $this->db->sql_query($sql); +			if ($this->db->sql_error_triggered) +			{ +				$this->errors[] = array( +					'sql'	=> $this->db->sql_error_sql, +					'code'	=> $this->db->sql_error_returned, +				); +			} +		} + +		$this->db->sql_return_on_error(false); + +		return $result; +	} + +	/** +	* Get the list of queries run +	* +	* @return array +	*/ +	public function get_queries() +	{ +		return $this->queries; +	} +} diff --git a/phpBB/includes/db/migration/tool/config.php b/phpBB/includes/db/migration/tool/config.php new file mode 100644 index 0000000000..0b626bf455 --- /dev/null +++ b/phpBB/includes/db/migration/tool/config.php @@ -0,0 +1,150 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* Migration config tool +* +* @package db +*/ +class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interface +{ +	/** @var phpbb_config */ +	protected $config; + +	/** +	* Constructor +	* +	* @param phpbb_config $config +	*/ +	public function __construct(phpbb_config $config) +	{ +		$this->config = $config; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_name() +	{ +		return 'config'; +	} + +	/** +	* Add a config setting. +	* +	* @param string $config_name The name of the config setting +	* 	you would like to add +	* @param mixed $config_value The value of the config setting +	* @param bool $is_dynamic True if it is dynamic (changes very often) +	* 	and should not be stored in the cache, false if not. +	* @return null +	*/ +	public function add($config_name, $config_value, $is_dynamic = false) +	{ +		if (isset($this->config[$config_name])) +		{ +			return; +		} + +		$this->config->set($config_name, $config_value, !$is_dynamic); +	} + +	/** +	* Update an existing config setting. +	* +	* @param string $config_name The name of the config setting you would +	* 	like to update +	* @param mixed $config_value The value of the config setting +	* @return null +	*/ +	public function update($config_name, $config_value) +	{ +		if (!isset($this->config[$config_name])) +		{ +			throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name); +		} + +		$this->config->set($config_name, $config_value); +	} + +	/** +	* Update a config setting if the first argument equal to the +	* current config value +	* +	* @param string $compare If equal to the current config value, will be +	* 	updated to the new config value, otherwise not +	* @param string $config_name The name of the config setting you would +	* 	like to update +	* @param mixed $config_value The value of the config setting +	* @return null +	*/ +	public function update_if_equals($compare, $config_name, $config_value) +	{ +		if (!isset($this->config[$config_name])) +		{ +			throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name); +		} + +		$this->config->set_atomic($config_name, $compare, $config_value); +	} + +	/** +	* Remove an existing config setting. +	* +	* @param string $config_name The name of the config setting you would +	* 	like to remove +	* @return null +	*/ +	public function remove($config_name) +	{ +		if (!isset($this->config[$config_name])) +		{ +			return; +		} + +		$this->config->delete($config_name); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function reverse() +	{ +		$arguments = func_get_args(); +		$original_call = array_shift($arguments); + +		$call = false; +		switch ($original_call) +		{ +			case 'add': +				$call = 'remove'; +			break; + +			case 'remove': +				$call = 'add'; +			break; + +			case 'update_if_equals': +				$call = 'update_if_equals'; + +				// Set to the original value if the current value is what we compared to originally +				$arguments = array( +					$arguments[2], +					$arguments[1], +					$arguments[0], +				); +			break; +		} + +		if ($call) +		{ +			return call_user_func_array(array(&$this, $call), $arguments); +		} +	} +} diff --git a/phpBB/includes/db/migration/tool/interface.php b/phpBB/includes/db/migration/tool/interface.php new file mode 100644 index 0000000000..ced53b2023 --- /dev/null +++ b/phpBB/includes/db/migration/tool/interface.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* Migration tool interface +* +* @package db +*/ +interface phpbb_db_migration_tool_interface +{ +	/** +	* Retrieve a short name used for commands in migrations. +	* +	* @return string short name +	*/ +	public function get_name(); + +	/** +	* Reverse an original install action +	* +	* First argument is the original call to the class (e.g. add, remove) +	* After the first argument, send the original arguments to the function in the original call +	* +	* @return null +	*/ +	public function reverse(); +} diff --git a/phpBB/includes/db/migration/tool/module.php b/phpBB/includes/db/migration/tool/module.php new file mode 100644 index 0000000000..ec683d36af --- /dev/null +++ b/phpBB/includes/db/migration/tool/module.php @@ -0,0 +1,502 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* Migration module management tool +* +* @package db +*/ +class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interface +{ +	/** @var phpbb_cache_service */ +	protected $cache; + +	/** @var dbal */ +	protected $db; + +	/** @var phpbb_user */ +	protected $user; + +	/** @var string */ +	protected $phpbb_root_path; + +	/** @var string */ +	protected $php_ext; + +	/** @var string */ +	protected $modules_table; + +	/** +	* Constructor +	* +	* @param phpbb_db_driver $db +	* @param mixed $cache +	* @param phpbb_user $user +	* @param string $phpbb_root_path +	* @param string $php_ext +	* @param string $modules_table +	*/ +	public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_user $user, $phpbb_root_path, $php_ext, $modules_table) +	{ +		$this->db = $db; +		$this->cache = $cache; +		$this->user = $user; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $php_ext; +		$this->modules_table = $modules_table; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_name() +	{ +		return 'module'; +	} + +	/** +	* Module Exists +	* +	* Check if a module exists +	* +	* @param string $class The module class(acp|mcp|ucp) +	* @param int|string|bool $parent The parent module_id|module_langname (0 for no parent). +	*		Use false to ignore the parent check and check class wide. +	* @param int|string $module The module_id|module_langname you would like to +	* 		check for to see if it exists +	* @return bool true/false if module exists +	*/ +	public function exists($class, $parent, $module) +	{ +		// the main root directory should return true +		if (!$module) +		{ +			return true; +		} + +		$parent_sql = ''; +		if ($parent !== false) +		{ +			// Allows '' to be sent as 0 +			$parent = $parent ?: 0; + +			if (!is_numeric($parent)) +			{ +				$sql = 'SELECT module_id +					FROM ' . $this->modules_table . " +					WHERE module_langname = '" . $this->db->sql_escape($parent) . "' +						AND module_class = '" . $this->db->sql_escape($class) . "'"; +				$result = $this->db->sql_query($sql); +				$module_id = $this->db->sql_fetchfield('module_id'); +				$this->db->sql_freeresult($result); + +				if (!$module_id) +				{ +					return false; +				} + +				$parent_sql = 'AND parent_id = ' . (int) $module_id; +			} +			else +			{ +				$parent_sql = 'AND parent_id = ' . (int) $parent; +			} +		} + +		$sql = 'SELECT module_id +			FROM ' . $this->modules_table . " +			WHERE module_class = '" . $this->db->sql_escape($class) . "' +				$parent_sql +				AND " . ((is_numeric($module)) ? 'module_id = ' . (int) $module : "module_langname = '" . $this->db->sql_escape($module) . "'"); +		$result = $this->db->sql_query($sql); +		$module_id = $this->db->sql_fetchfield('module_id'); +		$this->db->sql_freeresult($result); + +		if ($module_id) +		{ +			return true; +		} + +		return false; +	} + +	/** +	* Module Add +	* +	* Add a new module +	* +	* @param string $class The module class(acp|mcp|ucp) +	* @param int|string $parent The parent module_id|module_langname (0 for no parent) +	* @param array $data an array of the data on the new module. +	* 	This can be setup in two different ways. +	*	1. The "manual" way.  For inserting a category or one at a time. +	*		It will be merged with the base array shown a bit below, +	*			but at the least requires 'module_langname' to be sent, and, +	*			if you want to create a module (instead of just a category) you must +	*			send module_basename and module_mode. +	*		array( +	*			'module_enabled'	=> 1, +	*			'module_display'	=> 1, +	*	   		'module_basename'	=> '', +	*			'module_class'		=> $class, +	*	   		'parent_id'			=> (int) $parent, +	*			'module_langname'	=> '', +	*	   		'module_mode'		=> '', +	*	   		'module_auth'		=> '', +	*		) +	*	2. The "automatic" way.  For inserting multiple at a time based on the +	*			specs in the info file for the module(s).  For this to work the +	*			modules must be correctly setup in the info file. +	*		An example follows (this would insert the settings, log, and flag +	*			modes from the includes/acp/info/acp_asacp.php file): +	* 		array( +	* 			'module_basename'	=> 'asacp', +	* 			'modes'				=> array('settings', 'log', 'flag'), +	* 		) +	* 		Optionally you may not send 'modes' and it will insert all of the +	* 			modules in that info file. +	* @param string|bool $include_path If you would like to use a custom include +	* 	path, specify that here +	* @return null +	*/ +	public function add($class, $parent = 0, $data = array(), $include_path = false) +	{ +		// Allows '' to be sent as 0 +		$parent = $parent ?: 0; + +		// allow sending the name as a string in $data to create a category +		if (!is_array($data)) +		{ +			$data = array('module_langname' => $data); +		} + +		if (!isset($data['module_langname'])) +		{ +			// The "automatic" way +			$basename = (isset($data['module_basename'])) ? $data['module_basename'] : ''; +			$basename = str_replace(array('/', '\\'), '', $basename); +			$class = str_replace(array('/', '\\'), '', $class); + +			$module = $this->get_module_info($class, $basename); + +			$result = ''; +			foreach ($module['modes'] as $mode => $module_info) +			{ +				if (!isset($data['modes']) || in_array($mode, $data['modes'])) +				{ +					$new_module = array( +						'module_basename'	=> $basename, +						'module_langname'	=> $module_info['title'], +						'module_mode'		=> $mode, +						'module_auth'		=> $module_info['auth'], +						'module_display'	=> (isset($module_info['display'])) ? $module_info['display'] : true, +						'before'			=> (isset($module_info['before'])) ? $module_info['before'] : false, +						'after'				=> (isset($module_info['after'])) ? $module_info['after'] : false, +					); + +					// Run the "manual" way with the data we've collected. +					$this->add($class, $parent, $new_module); +				} +			} + +			return; +		} + +		// The "manual" way +		$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); + +		if (!is_numeric($parent)) +		{ +			$sql = 'SELECT module_id +				FROM ' . $this->modules_table . " +				WHERE module_langname = '" . $this->db->sql_escape($parent) . "' +					AND module_class = '" . $this->db->sql_escape($class) . "'"; +			$result = $this->db->sql_query($sql); +			$module_id = $this->db->sql_fetchfield('module_id'); +			$this->db->sql_freeresult($result); + +			if (!$module_id) +			{ +				throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent); +			} + +			$parent = $data['parent_id'] = $module_id; +		} +		else if (!$this->exists($class, false, $parent)) +		{ +			throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent); +		} + +		if ($this->exists($class, $parent, $data['module_langname'])) +		{ +			return; +		} + +		if (!class_exists('acp_modules')) +		{ +			include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); +			$this->user->add_lang('acp/modules'); +		} +		$acp_modules = new acp_modules(); + +		$module_data = array( +			'module_enabled'	=> (isset($data['module_enabled'])) ? $data['module_enabled'] : 1, +			'module_display'	=> (isset($data['module_display'])) ? $data['module_display'] : 1, +			'module_basename'	=> (isset($data['module_basename'])) ? $data['module_basename'] : '', +			'module_class'		=> $class, +			'parent_id'			=> (int) $parent, +			'module_langname'	=> (isset($data['module_langname'])) ? $data['module_langname'] : '', +			'module_mode'		=> (isset($data['module_mode'])) ? $data['module_mode'] : '', +			'module_auth'		=> (isset($data['module_auth'])) ? $data['module_auth'] : '', +		); +		$result = $acp_modules->update_module_data($module_data, true); + +		// update_module_data can either return a string or an empty array... +		if (is_string($result)) +		{ +			// Error +			throw new phpbb_db_migration_exception('MODULE_ERROR', $result); +		} +		else +		{ +			// Success + +			// Move the module if requested above/below an existing one +			if (isset($data['before']) && $data['before']) +			{ +				$sql = 'SELECT left_id +					FROM ' . $this->modules_table . " +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND parent_id = " . (int) $parent . " +						AND module_langname = '" . $this->db->sql_escape($data['before']) . "'"; +				$this->db->sql_query($sql); +				$to_left = (int) $this->db->sql_fetchfield('left_id'); + +				$sql = 'UPDATE ' . $this->modules_table . " +					SET left_id = left_id + 2, right_id = right_id + 2 +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND left_id >= $to_left +						AND left_id < {$module_data['left_id']}"; +				$this->db->sql_query($sql); + +				$sql = 'UPDATE ' . $this->modules_table . " +					SET left_id = $to_left, right_id = " . ($to_left + 1) . " +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND module_id = {$module_data['module_id']}"; +				$this->db->sql_query($sql); +			} +			else if (isset($data['after']) && $data['after']) +			{ +				$sql = 'SELECT right_id +					FROM ' . $this->modules_table . " +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND parent_id = " . (int) $parent . " +						AND module_langname = '" . $this->db->sql_escape($data['after']) . "'"; +				$this->db->sql_query($sql); +				$to_right = (int) $this->db->sql_fetchfield('right_id'); + +				$sql = 'UPDATE ' . $this->modules_table . " +					SET left_id = left_id + 2, right_id = right_id + 2 +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND left_id >= $to_right +						AND left_id < {$module_data['left_id']}"; +				$this->db->sql_query($sql); + +				$sql = 'UPDATE ' . $this->modules_table . ' +					SET left_id = ' . ($to_right + 1) . ', right_id = ' . ($to_right + 2) . " +					WHERE module_class = '" . $this->db->sql_escape($class) . "' +						AND module_id = {$module_data['module_id']}"; +				$this->db->sql_query($sql); +			} +		} + +		// Clear the Modules Cache +		$this->cache->destroy("_modules_$class"); +	} + +	/** +	* Module Remove +	* +	* Remove a module +	* +	* @param string $class The module class(acp|mcp|ucp) +	* @param int|string|bool $parent The parent module_id|module_langname(0 for no parent). +	* 	Use false to ignore the parent check and check class wide. +	* @param int|string $module The module id|module_langname +	* @param string|bool $include_path If you would like to use a custom include path, +	* 	specify that here +	* @return null +	*/ +	public function remove($class, $parent = 0, $module = '', $include_path = false) +	{ +		// Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto +		if (is_array($module)) +		{ +			if (isset($module['module_langname'])) +			{ +				// Manual Method +				return $this->remove($class, $parent, $module['module_langname'], $include_path); +			} + +			// Failed. +			if (!isset($module['module_basename'])) +			{ +				throw new phpbb_db_migration_exception('MODULE_NOT_EXIST'); +			} + +			// Automatic method +			$basename = str_replace(array('/', '\\'), '', $module['module_basename']); +			$class = str_replace(array('/', '\\'), '', $class); + +			$module_info = $this->get_module_info($class, $basename); + +			foreach ($module_info['modes'] as $mode => $info) +			{ +				if (!isset($module['modes']) || in_array($mode, $module['modes'])) +				{ +					$this->remove($class, $parent, $info['title']); +				} +			} +		} +		else +		{ +			if (!$this->exists($class, $parent, $module)) +			{ +				return; +			} + +			$parent_sql = ''; +			if ($parent !== false) +			{ +				// Allows '' to be sent as 0 +				$parent = ($parent) ?: 0; + +				if (!is_numeric($parent)) +				{ +					$sql = 'SELECT module_id +						FROM ' . $this->modules_table . " +						WHERE module_langname = '" . $this->db->sql_escape($parent) . "' +							AND module_class = '" . $this->db->sql_escape($class) . "'"; +					$result = $this->db->sql_query($sql); +					$module_id = $this->db->sql_fetchfield('module_id'); +					$this->db->sql_freeresult($result); + +					// we know it exists from the module_exists check +					$parent_sql = 'AND parent_id = ' . (int) $module_id; +				} +				else +				{ +					$parent_sql = 'AND parent_id = ' . (int) $parent; +				} +			} + +			$module_ids = array(); +			if (!is_numeric($module)) +			{ +				$sql = 'SELECT module_id +					FROM ' . $this->modules_table . " +					WHERE module_langname = '" . $this->db->sql_escape($module) . "' +						AND module_class = '" . $this->db->sql_escape($class) . "' +						$parent_sql"; +				$result = $this->db->sql_query($sql); +				while ($module_id = $this->db->sql_fetchfield('module_id')) +				{ +					$module_ids[] = (int) $module_id; +				} +				$this->db->sql_freeresult($result); + +				$module_name = $module; +			} +			else +			{ +				$module = (int) $module; +				$sql = 'SELECT module_langname +					FROM ' . $this->modules_table . " +					WHERE module_id = $module +						AND module_class = '" . $this->db->sql_escape($class) . "' +						$parent_sql"; +				$result = $this->db->sql_query($sql); +				$module_name = $this->db->sql_fetchfield('module_id'); +				$this->db->sql_freeresult($result); + +				$module_ids[] = $module; +			} + +			if (!class_exists('acp_modules')) +			{ +				include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); +				$this->user->add_lang('acp/modules'); +			} +			$acp_modules = new acp_modules(); +			$acp_modules->module_class = $class; + +			foreach ($module_ids as $module_id) +			{ +				$result = $acp_modules->delete_module($module_id); +				if (!empty($result)) +				{ +					return; +				} +			} + +			$this->cache->destroy("_modules_$class"); +		} +	} + +	/** +	* {@inheritdoc} +	*/ +	public function reverse() +	{ +		$arguments = func_get_args(); +		$original_call = array_shift($arguments); + +		$call = false; +		switch ($original_call) +		{ +			case 'add': +				$call = 'remove'; +			break; + +			case 'remove': +				$call = 'add'; +			break; +		} + +		if ($call) +		{ +			return call_user_func_array(array(&$this, $call), $arguments); +		} +	} + +	/** +	* Wrapper for acp_modules::get_module_infos() +	* +	* @param string $class Module Class +	* @param string $basename Module Basename +	* @return array Module Information +	*/ +	protected function get_module_info($class, $basename) +	{ +		if (!class_exists('acp_modules')) +		{ +			include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); +		} +		$acp_modules = new acp_modules(); +		$module = $acp_modules->get_module_infos($basename, $class, true); + +		if (empty($module)) +		{ +			throw new phpbb_db_migration_exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename); +		} + +		return array_pop($module); +	} +} diff --git a/phpBB/includes/db/migration/tool/permission.php b/phpBB/includes/db/migration/tool/permission.php new file mode 100644 index 0000000000..2f09c0ac72 --- /dev/null +++ b/phpBB/includes/db/migration/tool/permission.php @@ -0,0 +1,622 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +/** +* Migration permission management tool +* +* @package db +*/ +class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_interface +{ +	/** @var phpbb_auth */ +	protected $auth; + +	/** @var phpbb_cache_service */ +	protected $cache; + +	/** @var dbal */ +	protected $db; + +	/** @var string */ +	protected $phpbb_root_path; + +	/** @var string */ +	protected $php_ext; + +	/** +	* Constructor +	* +	* @param phpbb_db_driver $db +	* @param mixed $cache +	* @param phpbb_auth $auth +	* @param string $phpbb_root_path +	* @param string $php_ext +	*/ +	public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_auth $auth, $phpbb_root_path, $php_ext) +	{ +		$this->db = $db; +		$this->cache = $cache; +		$this->auth = $auth; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $php_ext; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_name() +	{ +		return 'permission'; +	} + +	/** +	* Permission Exists +	* +	* Check if a permission (auth) setting exists +	* +	* @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 +	* @return bool true if it exists, false if not +	*/ +	public function exists($auth_option, $global = true) +	{ +		if ($global) +		{ +			$type_sql = ' AND is_global = 1'; +		} +		else +		{ +			$type_sql = ' AND is_local = 1'; +		} + +		$sql = 'SELECT auth_option_id +			FROM ' . ACL_OPTIONS_TABLE . " +			WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" +				. $type_sql; +		$result = $this->db->sql_query($sql); + +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		if ($row) +		{ +			return true; +		} + +		return false; +	} + +	/** +	* Permission Add +	* +	* Add a permission (auth) option +	* +	* @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 +	* @return null +	*/ +	public function add($auth_option, $global = true, $copy_from = false) +	{ +		if ($this->exists($auth_option, $global)) +		{ +			return; +		} + +		// We've added permissions, so set to true to notify the user. +		$this->permissions_added = true; + +		if (!class_exists('auth_admin')) +		{ +			include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext); +		} +		$auth_admin = new auth_admin(); + +		// We have to add a check to see if the !$global (if global, local, and if local, global) permission already exists.  If it does, acl_add_option currently has a bug which would break the ACL system, so we are having a work-around here. +		if ($this->exists($auth_option, !$global)) +		{ +			$sql_ary = array( +				'is_global'	=> 1, +				'is_local'	=> 1, +			); +			$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' +				SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . " +				WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'"; +			$this->db->sql_query($sql); +		} +		else +		{ +			if ($global) +			{ +				$auth_admin->acl_add_option(array('global' => array($auth_option))); +			} +			else +			{ +				$auth_admin->acl_add_option(array('local' => array($auth_option))); +			} +		} + +		// The permission has been added, now we can copy it if needed +		if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from])) +		{ +			$old_id = $auth_admin->acl_options['id'][$copy_from]; +			$new_id = $auth_admin->acl_options['id'][$auth_option]; + +			$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE); + +			foreach ($tables as $table) +			{ +				$sql = 'SELECT * +					FROM ' . $table . ' +					WHERE auth_option_id = ' . $old_id; +				$result = $this->db->sql_query($sql); + +				$sql_ary = array(); +				while ($row = $this->db->sql_fetchrow($result)) +				{ +					$row['auth_option_id'] = $new_id; +					$sql_ary[] = $row; +				} +				$this->db->sql_freeresult($result); + +				if (!empty($sql_ary)) +				{ +					$this->db->sql_multi_insert($table, $sql_ary); +				} +			} + +			$auth_admin->acl_clear_prefetch(); +		} +	} + +	/** +	* Permission Remove +	* +	* Remove a permission (auth) option +	* +	* @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 +	* @return null +	*/ +	public function remove($auth_option, $global = true) +	{ +		if (!$this->exists($auth_option, $global)) +		{ +			return; +		} + +		if ($global) +		{ +			$type_sql = ' AND is_global = 1'; +		} +		else +		{ +			$type_sql = ' AND is_local = 1'; +		} +		$sql = 'SELECT auth_option_id, is_global, is_local +			FROM ' . ACL_OPTIONS_TABLE . " +			WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" . +				$type_sql; +		$result = $this->db->sql_query($sql); +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		$id = (int) $row['auth_option_id']; + +		// If it is a local and global permission, do not remove the row! :P +		if ($row['is_global'] && $row['is_local']) +		{ +			$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' +				SET ' . (($global) ? 'is_global = 0' : 'is_local = 0') . ' +				WHERE auth_option_id = ' . $id; +			$this->db->sql_query($sql); +		} +		else +		{ +			// Delete time +			$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE, ACL_OPTIONS_TABLE); +			foreach ($tables as $table) +			{ +				$this->db->sql_query('DELETE FROM ' . $table . ' +					WHERE auth_option_id = ' . $id); +			} +		} + +		// Purge the auth cache +		$this->cache->destroy('_acl_options'); +		$this->auth->acl_clear_prefetch(); +	} + +	/** +	* Add a new permission role +	* +	* @param string $role_name The new role name +	* @param sting $role_type The type (u_, m_, a_) +	* @return null +	*/ +	public function role_add($role_name, $role_type, $role_description = '') +	{ +		$sql = 'SELECT role_id +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_name = '" . $this->db->sql_escape($role_name) . "'"; +		$this->db->sql_query($sql); +		$role_id = (int) $this->db->sql_fetchfield('role_id'); + +		if ($role_id) +		{ +			return; +		} + +		$sql = 'SELECT MAX(role_order) AS max_role_order +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_type = '" . $this->db->sql_escape($role_type) . "'"; +		$this->db->sql_query($sql); +		$role_order = (int) $this->db->sql_fetchfield('max_role_order'); +		$role_order = (!$role_order) ? 1 : $role_order + 1; + +		$sql_ary = array( +			'role_name'			=> $role_name, +			'role_description'	=> $role_description, +			'role_type'			=> $role_type, +			'role_order'		=> $role_order, +		); + +		$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); +		$this->db->sql_query($sql); +	} + +	/** +	* Update the name on a permission role +	* +	* @param string $old_role_name The old role name +	* @param string $new_role_name The new role name +	* @return null +	*/ +	public function role_update($old_role_name, $new_role_name) +	{ +		$sql = 'SELECT role_id +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'"; +		$this->db->sql_query($sql); +		$role_id = (int) $this->db->sql_fetchfield('role_id'); + +		if (!$role_id) +		{ +			throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $old_role_name); +		} + +		$sql = 'UPDATE ' . ACL_ROLES_TABLE . " +			SET role_name = '" . $this->db->sql_escape($new_role_name) . "' +			WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'"; +		$this->db->sql_query($sql); +	} + +	/** +	* Remove a permission role +	* +	* @param string $role_name The role name to remove +	* @return null +	*/ +	public function role_remove($role_name) +	{ +		$sql = 'SELECT role_id +			FROM ' . ACL_ROLES_TABLE . " +			WHERE role_name = '" . $this->db->sql_escape($role_name) . "'"; +		$this->db->sql_query($sql); +		$role_id = (int) $this->db->sql_fetchfield('role_id'); + +		if (!$role_id) +		{ +			return; +		} + +		$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' +			WHERE role_id = ' . $role_id; +		$this->db->sql_query($sql); + +		$sql = 'DELETE FROM ' . ACL_ROLES_TABLE . ' +			WHERE role_id = ' . $role_id; +		$this->db->sql_query($sql); + +		$this->auth->acl_clear_prefetch(); +	} + +	/** +	* Permission Set +	* +	* Allows you to set permissions for a certain group/role +	* +	* @param string $name The name of the role/group +	* @param string|array $auth_option The auth_option or array of +	* 	auth_options you would like to set +	* @param string $type The type (role|group) +	* @param bool $has_permission True if you want to give them permission, +	* 	false if you want to deny them permission +	* @return null +	*/ +	public function permission_set($name, $auth_option, $type = 'role', $has_permission = true) +	{ +		if (!is_array($auth_option)) +		{ +			$auth_option = array($auth_option); +		} + +		$new_auth = array(); +		$sql = 'SELECT auth_option_id +			FROM ' . ACL_OPTIONS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('auth_option', $auth_option); +		$result = $this->db->sql_query($sql); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$new_auth[] = (int) $row['auth_option_id']; +		} +		$this->db->sql_freeresult($result); + +		if (empty($new_auth)) +		{ +			return; +		} + +		$current_auth = array(); + +		$type = (string) $type; // Prevent PHP bug. + +		switch ($type) +		{ +			case 'role': +				$sql = 'SELECT role_id +					FROM ' . ACL_ROLES_TABLE . " +					WHERE role_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +				$role_id = (int) $this->db->sql_fetchfield('role_id'); + +				if (!$role_id) +				{ +					throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name); +				} + +				$sql = 'SELECT auth_option_id, auth_setting +					FROM ' . ACL_ROLES_DATA_TABLE . ' +					WHERE role_id = ' . $role_id; +				$result = $this->db->sql_query($sql); +				while ($row = $this->db->sql_fetchrow($result)) +				{ +					$current_auth[$row['auth_option_id']] = $row['auth_setting']; +				} +				$this->db->sql_freeresult($result); +			break; + +			case 'group': +				$sql = 'SELECT group_id +					FROM ' . GROUPS_TABLE . " +					WHERE group_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +				$group_id = (int) $this->db->sql_fetchfield('group_id'); + +				if (!$group_id) +				{ +					throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name); +				} + +				// If the group has a role set for them we will add the requested permissions to that role. +				$sql = 'SELECT auth_role_id +					FROM ' . ACL_GROUPS_TABLE . ' +					WHERE group_id = ' . $group_id . ' +						AND auth_role_id <> 0 +						AND forum_id = 0'; +				$this->db->sql_query($sql); +				$role_id = (int) $this->db->sql_fetchfield('auth_role_id'); +				if ($role_id) +				{ +					$sql = 'SELECT role_name +						FROM ' . ACL_ROLES_TABLE . ' +						WHERE role_id = ' . $role_id; +					$this->db->sql_query($sql); +					$role_name = $this->db->sql_fetchfield('role_name'); + +					return $this->permission_set($role_name, $auth_option, 'role', $has_permission); +				} + +				$sql = 'SELECT auth_option_id, auth_setting +					FROM ' . ACL_GROUPS_TABLE . ' +					WHERE group_id = ' . $group_id; +				$result = $this->db->sql_query($sql); +				while ($row = $this->db->sql_fetchrow($result)) +				{ +					$current_auth[$row['auth_option_id']] = $row['auth_setting']; +				} +				$this->db->sql_freeresult($result); +			break; +		} + +		$sql_ary = array(); +		switch ($type) +		{ +			case 'role': +				foreach ($new_auth as $auth_option_id) +				{ +					if (!isset($current_auth[$auth_option_id])) +					{ +						$sql_ary[] = array( +							'role_id'			=> $role_id, +							'auth_option_id'	=> $auth_option_id, +							'auth_setting'		=> $has_permission, +						); +					} +				} + +				$this->db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary); +			break; + +			case 'group': +				foreach ($new_auth as $auth_option_id) +				{ +					if (!isset($current_auth[$auth_option_id])) +					{ +						$sql_ary[] = array( +							'group_id'			=> $group_id, +							'auth_option_id'	=> $auth_option_id, +							'auth_setting'		=> $has_permission, +						); +					} +				} + +				$this->db->sql_multi_insert(ACL_GROUPS_TABLE, $sql_ary); +			break; +		} + +		$this->auth->acl_clear_prefetch(); +	} + +	/** +	* Permission Unset +	* +	* Allows you to unset (remove) permissions for a certain group/role +	* +	* @param string $name The name of the role/group +	* @param string|array $auth_option The auth_option or array of +	* 	auth_options you would like to set +	* @param string $type The type (role|group) +	* @return null +	*/ +	public function permission_unset($name, $auth_option, $type = 'role') +	{ +		if (!is_array($auth_option)) +		{ +			$auth_option = array($auth_option); +		} + +		$to_remove = array(); +		$sql = 'SELECT auth_option_id +			FROM ' . ACL_OPTIONS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('auth_option', $auth_option); +		$result = $this->db->sql_query($sql); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$to_remove[] = (int) $row['auth_option_id']; +		} +		$this->db->sql_freeresult($result); + +		if (empty($to_remove)) +		{ +			return; +		} + +		$type = (string) $type; // Prevent PHP bug. + +		switch ($type) +		{ +			case 'role': +				$sql = 'SELECT role_id +					FROM ' . ACL_ROLES_TABLE . " +					WHERE role_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +				$role_id = (int) $this->db->sql_fetchfield('role_id'); + +				if (!$role_id) +				{ +					throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name); +				} + +				$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' +					WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove); +				$this->db->sql_query($sql); +			break; + +			case 'group': +				$sql = 'SELECT group_id +					FROM ' . GROUPS_TABLE . " +					WHERE group_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +				$group_id = (int) $this->db->sql_fetchfield('group_id'); + +				if (!$group_id) +				{ +					throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name); +				} + +				// If the group has a role set for them we will remove the requested permissions from that role. +				$sql = 'SELECT auth_role_id +					FROM ' . ACL_GROUPS_TABLE . ' +					WHERE group_id = ' . $group_id . ' +						AND auth_role_id <> 0'; +				$this->db->sql_query($sql); +				$role_id = (int) $this->db->sql_fetchfield('auth_role_id'); +				if ($role_id) +				{ +					$sql = 'SELECT role_name +						FROM ' . ACL_ROLES_TABLE . ' +						WHERE role_id = ' . $role_id; +					$this->db->sql_query($sql); +					$role_name = $this->db->sql_fetchfield('role_name'); + +					return $this->permission_unset($role_name, $auth_option, 'role'); +				} + +				$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' +					WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove); +				$this->db->sql_query($sql); +			break; +		} + +		$this->auth->acl_clear_prefetch(); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function reverse() +	{ +		$arguments = func_get_args(); +		$original_call = array_shift($arguments); + +		$call = false; +		switch ($original_call) +		{ +			case 'add': +				$call = 'remove'; +			break; + +			case 'remove': +				$call = 'add'; +			break; + +			case 'permission_set': +				$call = 'permission_unset'; +			break; + +			case 'permission_unset': +				$call = 'permission_set'; +			break; + +			case 'role_add': +				$call = 'role_remove'; +			break; + +			case 'role_remove': +				$call = 'role_add'; +			break; + +			case 'role_update': +				// Set to the original value if the current value is what we compared to originally +				$arguments = array( +					$arguments[1], +					$arguments[0], +				); +			break; +		} + +		if ($call) +		{ +			return call_user_func_array(array(&$this, $call), $arguments); +		} +	} +} diff --git a/phpBB/includes/db/migrator.php b/phpBB/includes/db/migrator.php new file mode 100644 index 0000000000..ca3ffc8043 --- /dev/null +++ b/phpBB/includes/db/migrator.php @@ -0,0 +1,746 @@ +<?php +/** +* +* @package db +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* The migrator is responsible for applying new migrations in the correct order. +* +* @package db +*/ +class phpbb_db_migrator +{ +	/** @var phpbb_config */ +	protected $config; + +	/** @var phpbb_db_driver */ +	protected $db; + +	/** @var phpbb_db_tools */ +	protected $db_tools; + +	/** @var string */ +	protected $table_prefix; + +	/** @var string */ +	protected $phpbb_root_path; + +	/** @var string */ +	protected $php_ext; + +	/** @var string */ +	protected $migrations_table; + +	/** +	* State of all migrations +	* +	* (SELECT * FROM migrations table) +	* +	* @var array +	*/ +	protected $migration_state = array(); + +	/** +	* Array of all migrations available to be run +	* +	* @var array +	*/ +	protected $migrations = array(); + +	/** +	* 'name,' 'class,' and 'state' of the last migration run +	* +	* 'effectively_installed' set and set to true if the migration was effectively_installed +	* +	* @var array +	*/ +	public $last_run_migration = false; + +	/** +	* Constructor of the database migrator +	*/ +	public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools) +	{ +		$this->config = $config; +		$this->db = $db; +		$this->db_tools = $db_tools; + +		$this->migrations_table = $migrations_table; + +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $php_ext; + +		$this->table_prefix = $table_prefix; + +		foreach ($tools as $tool) +		{ +			$this->tools[$tool->get_name()] = $tool; +		} + +		$this->load_migration_state(); +	} + +	/** +	* Loads all migrations and their application state from the database. +	* +	* @return null +	*/ +	public function load_migration_state() +	{ +		$this->migration_state = array(); + +		// prevent errors in case the table does not exist yet +		$this->db->sql_return_on_error(true); + +		$sql = "SELECT * +			FROM " . $this->migrations_table; +		$result = $this->db->sql_query($sql); + +		if (!$this->db->sql_error_triggered) +		{ +			while ($migration = $this->db->sql_fetchrow($result)) +			{ +				$this->migration_state[$migration['migration_name']] = $migration; + +				$this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']); +			} +		} + +		$this->db->sql_freeresult($result); + +		$this->db->sql_return_on_error(false); +	} + +	/** +	* Sets the list of available migration class names to the given array. +	* +	* @param array $class_names An array of migration class names +	* @return null +	*/ +	public function set_migrations($class_names) +	{ +		$this->migrations = $class_names; +	} + +	/** +	* Runs a single update step from the next migration to be applied. +	* +	* The update step can either be a schema or a (partial) data update. To +	* check if update() needs to be called again use the finished() method. +	* +	* @return null +	*/ +	public function update() +	{ +		foreach ($this->migrations as $name) +		{ +			if (!isset($this->migration_state[$name]) || +				!$this->migration_state[$name]['migration_schema_done'] || +				!$this->migration_state[$name]['migration_data_done']) +			{ +				if (!$this->try_apply($name)) +				{ +					continue; +				} +				else +				{ +					return; +				} +			} +		} +	} + +	/** +	* Attempts to apply a step of the given migration or one of its dependencies +	* +	* @param	string	The class name of the migration +	* @return	bool	Whether any update step was successfully run +	*/ +	protected function try_apply($name) +	{ +		if (!class_exists($name)) +		{ +			return false; +		} + +		$migration = $this->get_migration($name); + +		$state = (isset($this->migration_state[$name])) ? +			$this->migration_state[$name] : +			array( +				'migration_depends_on'	=> $migration->depends_on(), +				'migration_schema_done' => false, +				'migration_data_done'	=> false, +				'migration_data_state'	=> '', +				'migration_start_time'	=> 0, +				'migration_end_time'	=> 0, +			); + +		foreach ($state['migration_depends_on'] as $depend) +		{ +			if (!isset($this->migration_state[$depend]) || +				!$this->migration_state[$depend]['migration_schema_done'] || +				!$this->migration_state[$depend]['migration_data_done']) +			{ +				return $this->try_apply($depend); +			} +		} + +		$this->last_run_migration = array( +			'name'	=> $name, +			'class'	=> $migration, +			'state'	=> $state, +		); + +		if (!isset($this->migration_state[$name])) +		{ +			if ($migration->effectively_installed()) +			{ +				$state = array( +					'migration_depends_on'	=> $migration->depends_on(), +					'migration_schema_done' => true, +					'migration_data_done'	=> true, +					'migration_data_state'	=> '', +					'migration_start_time'	=> 0, +					'migration_end_time'	=> 0, +				); + +				$this->last_run_migration['effectively_installed'] = true; +			} +			else +			{ +				$state['migration_start_time'] = time(); +			} +		} + +		if (!$state['migration_schema_done']) +		{ +			$this->apply_schema_changes($migration->update_schema()); +			$state['migration_schema_done'] = true; +		} +		else if (!$state['migration_data_done']) +		{ +			try +			{ +				$result = $this->process_data_step($migration->update_data(), $state['migration_data_state']); + +				$state['migration_data_state'] = ($result === true) ? '' : $result; +				$state['migration_data_done'] = ($result === true); +				$state['migration_end_time'] = ($result === true) ? time() : 0; +			} +			catch (phpbb_db_migration_exception $e) +			{ +				// Revert the schema changes +				$this->revert($name); + +				// Rethrow exception +				throw $e; +			} +		} + +		$this->set_migration_state($name, $state); + +		return true; +	} + +	/** +	* Runs a single revert step from the last migration installed +	* +	* YOU MUST ADD/SET ALL MIGRATIONS THAT COULD BE DEPENDENT ON THE MIGRATION TO REVERT TO BEFORE CALLING THIS METHOD! +	* The revert step can either be a schema or a (partial) data revert. To +	* 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) +	{ +		if (!isset($this->migration_state[$migration])) +		{ +			// Not installed +			return; +		} + +		foreach ($this->migration_state as $name => $state) +		{ +			if (!empty($state['migration_depends_on']) && in_array($migration, $state['migration_depends_on'])) +			{ +				$this->revert($name); +			} +		} + +		$this->try_revert($migration); +	} + +	/** +	* Attempts to revert a step of the given migration or one of its dependencies +	* +	* @param	string	The class name of the migration +	* @return	bool	Whether any update step was successfully run +	*/ +	protected function try_revert($name) +	{ +		if (!class_exists($name)) +		{ +			return false; +		} + +		$migration = $this->get_migration($name); + +		$state = $this->migration_state[$name]; + +		$this->last_run_migration = array( +			'name'	=> $name, +			'class'	=> $migration, +		); + +		if ($state['migration_data_done']) +		{ +			if ($state['migration_data_state'] !== 'revert_data') +			{ +				$result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true); + +				$state['migration_data_state'] = ($result === true) ? 'revert_data' : $result; +			} +			else +			{ +				$result = $this->process_data_step($migration->revert_data(), '', false); + +				$state['migration_data_state'] = ($result === true) ? '' : $result; +				$state['migration_data_done'] = ($result === true) ? false : true; +			} + +			$this->set_migration_state($name, $state); +		} +		else +		{ +			$this->apply_schema_changes($migration->revert_schema()); + +			$sql = 'DELETE FROM ' . $this->migrations_table . " +				WHERE migration_name = '" . $this->db->sql_escape($name) . "'"; +			$this->db->sql_query($sql); + +			unset($this->migration_state[$name]); +		} + +		return true; +	} + +	/** +	* Apply schema changes from a migration +	* +	* Just calls db_tools->perform_schema_changes +	* +	* @param array $schema_changes from migration +	*/ +	protected function apply_schema_changes($schema_changes) +	{ +		$this->db_tools->perform_schema_changes($schema_changes); +	} + +	/** +	* Process the data step of the migration +	* +	* @param array $steps The steps to run +	* @param bool|string $state Current state of the migration +	* @param bool $revert true to revert a data step +	* @return bool|string migration state. True if completed, serialized array if not finished +	*/ +	protected function process_data_step($steps, $state, $revert = false) +	{ +		$state = ($state) ? unserialize($state) : false; + +		// reverse order of steps if reverting +		if ($revert === true) +		{ +			$steps = array_reverse($steps); +		} + +		foreach ($steps as $step_identifier => $step) +		{ +			$last_result = false; +			if ($state) +			{ +				// Continue until we reach the step that matches the last step called +				if ($state['step'] != $step_identifier) +				{ +					continue; +				} + +				// We send the result from last time to the callable function +				$last_result = $state['result']; + +				// Set state to false since we reached the point we were at +				$state = false; +			} + +			try +			{ +				// Result will be null or true if everything completed correctly +				$result = $this->run_step($step, $last_result, $revert); +				if ($result !== null && $result !== true) +				{ +					return serialize(array( +						'result'	=> $result, +						'step'		=> $step_identifier, +					)); +				} +			} +			catch (phpbb_db_migration_exception $e) +			{ +				// We should try rolling back here +				foreach ($steps as $reverse_step_identifier => $reverse_step) +				{ +					// If we've reached the current step we can break because we reversed everything that was run +					if ($reverse_step_identifier == $step_identifier) +					{ +						break; +					} + +					// Reverse the step that was run +					$result = $this->run_step($reverse_step, false, !$revert); +				} + +				// rethrow the exception +				throw $e; +			} +		} + +		return true; +	} + +	/** +	* Run a single step +	* +	* An exception should be thrown if an error occurs +	* +	* @param mixed $step Data step from migration +	* @param mixed $last_result Result to pass to the callable (only for 'custom' method) +	* @param bool $reverse False to install, True to attempt uninstallation by reversing the call +	* @return null +	*/ +	protected function run_step($step, $last_result = false, $reverse = false) +	{ +		$callable_and_parameters = $this->get_callable_from_step($step, $last_result, $reverse); + +		if ($callable_and_parameters === false) +		{ +			return; +		} + +		$callable = $callable_and_parameters[0]; +		$parameters = $callable_and_parameters[1]; + +		return call_user_func_array($callable, $parameters); +	} + +	/** +	* Get a callable statement from a data step +	* +	* @param array $step Data step from migration +	* @param mixed $last_result Result to pass to the callable (only for 'custom' method) +	* @param bool $reverse False to install, True to attempt uninstallation by reversing the call +	* @return array Array with parameters for call_user_func_array(), 0 is the callable, 1 is parameters +	*/ +	protected function get_callable_from_step(array $step, $last_result = false, $reverse = false) +	{ +		$type = $step[0]; +		$parameters = $step[1]; + +		$parts = explode('.', $type); + +		$class = $parts[0]; +		$method = false; + +		if (isset($parts[1])) +		{ +			$method = $parts[1]; +		} + +		switch ($class) +		{ +			case 'if': +				if (!isset($parameters[0])) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_CONDITION', $step); +				} + +				if (!isset($parameters[1])) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step); +				} + +				$condition = $parameters[0]; + +				if (!$condition) +				{ +					return false; +				} + +				$step = $parameters[1]; + +				return $this->get_callable_from_step($step); +			break; +			case 'custom': +				if (!is_callable($parameters[0])) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE', $step); +				} + +				return array( +					$parameters[0], +					array($last_result), +				); +			break; + +			default: +				if (!$method) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNKNOWN_TYPE', $step); +				} + +				if (!isset($this->tools[$class])) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_TOOL', $step); +				} + +				if (!method_exists(get_class($this->tools[$class]), $method)) +				{ +					throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_METHOD', $step); +				} + +				// Attempt to reverse operations +				if ($reverse) +				{ +					array_unshift($parameters, $method); + +					return array( +						array($this->tools[$class], 'reverse'), +						$parameters, +					); +				} + +				return array( +					array($this->tools[$class], $method), +					$parameters, +				); +			break; +		} +	} + +	/** +	* Insert/Update migration row into the database +	* +	* @param string $name Name of the migration +	* @param array $state +	* @return null +	*/ +	protected function set_migration_state($name, $state) +	{ +		$migration_row = $state; +		$migration_row['migration_depends_on'] = serialize($state['migration_depends_on']); + +		if (isset($this->migration_state[$name])) +		{ +			$sql = 'UPDATE ' . $this->migrations_table . ' +				SET ' . $this->db->sql_build_array('UPDATE', $migration_row) . " +				WHERE migration_name = '" . $this->db->sql_escape($name) . "'"; +			$this->db->sql_query($sql); +		} +		else +		{ +			$migration_row['migration_name'] = $name; +			$sql = 'INSERT INTO ' . $this->migrations_table . ' +				' . $this->db->sql_build_array('INSERT', $migration_row); +			$this->db->sql_query($sql); +		} + +		$this->migration_state[$name] = $state; + +		$this->last_run_migration['state'] = $state; +	} + +	/** +	* Checks if a migration's dependencies can even theoretically be satisfied. +	* +	* @param string	$name The class name of the migration +	* @return bool|string False if fulfillable, string of missing migration name if unfulfillable +	*/ +	public function unfulfillable($name) +	{ +		if (isset($this->migration_state[$name])) +		{ +			return false; +		} + +		if (!class_exists($name)) +		{ +			return $name; +		} + +		$migration = $this->get_migration($name); +		$depends = $migration->depends_on(); + +		foreach ($depends as $depend) +		{ +			$unfulfillable = $this->unfulfillable($depend); +			if ($unfulfillable !== false) +			{ +				return $unfulfillable; +			} +		} + +		return false; +	} + +	/** +	* Checks whether all available, fulfillable migrations have been applied. +	* +	* @return bool Whether the migrations have been applied +	*/ +	public function finished() +	{ +		foreach ($this->migrations as $name) +		{ +			if (!isset($this->migration_state[$name])) +			{ +				// skip unfulfillable migrations, but fulfillables mean we +				// are not finished yet +				if ($this->unfulfillable($name) !== false) +				{ +					continue; +				} +				return false; +			} + +			$migration = $this->migration_state[$name]; + +			if (!$migration['migration_schema_done'] || !$migration['migration_data_done']) +			{ +				return false; +			} +		} + +		return true; +	} + +	/** +	* Gets a migration state (whether it is installed and to what extent) +	* +	* @param string $migration String migration name to check if it is installed +	* @return bool|array False if the migration has not at all been installed, array +	*/ +	public function migration_state($migration) +	{ +		if (!isset($this->migration_state[$migration])) +		{ +			return false; +		} + +		return $this->migration_state[$migration]; +	} + +	/** +	* Helper to get a migration +	* +	* @param string $name Name of the migration +	* @return phpbb_db_migration +	*/ +	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); +	} + +	/** +	* This function adds all migrations sent to it to the migrations table +	* +	* THIS SHOULD NOT GENERALLY BE USED! THIS IS FOR THE PHPBB INSTALLER. +	* THIS WILL THROW ERRORS IF MIGRATIONS ALREADY EXIST IN THE TABLE, DO NOT CALL MORE THAN ONCE! +	* +	* @param array $migrations Array of migrations (names) to add to the migrations table +	* @return null +	*/ +	public function populate_migrations($migrations) +	{ +		foreach ($migrations as $name) +		{ +			if ($this->migration_state($name) === false) +			{ +				$state = array( +					'migration_depends_on'	=> $name::depends_on(), +					'migration_schema_done' => true, +					'migration_data_done'	=> true, +					'migration_data_state'	=> '', +					'migration_start_time'	=> time(), +					'migration_end_time'	=> time(), +				); +				$this->set_migration_state($name, $state); +			} +		} +	} + +	/** +	* Load migration data files from a directory +	* +	* @param phpbb_extension_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 +	*/ +	public function load_migrations(phpbb_extension_finder $finder, $path, $check_fulfillable = true) +	{ +		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) +		{ +			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); +				} +			} +		} + +		return $this->migrations; +	} +} diff --git a/phpBB/includes/db/sql_insert_buffer.php b/phpBB/includes/db/sql_insert_buffer.php new file mode 100644 index 0000000000..c18f908429 --- /dev/null +++ b/phpBB/includes/db/sql_insert_buffer.php @@ -0,0 +1,150 @@ +<?php +/** +* +* @package dbal +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Collects rows for insert into a database until the buffer size is reached. +* Then flushes the buffer to the database and starts over again. +* +* Benefits over collecting a (possibly huge) insert array and then using +* $db->sql_multi_insert() include: +* +*  - Going over max packet size of the database connection is usually prevented +*    because the data is submitted in batches. +* +*  - Reaching database connection timeout is usually prevented because +*    submission of batches talks to the database every now and then. +* +*  - Usage of less PHP memory because data no longer needed is discarded on +*    buffer flush. +* +* Attention: +* Please note that users of this class have to call flush() to flush the +* remaining rows to the database after their batch insert operation is +* finished. +* +* Usage: +* <code> +*	$buffer = new phpbb_db_sql_insert_buffer($db, 'test_table', 1234); +* +*	while (do_stuff()) +*	{ +*		$buffer->insert(array( +*			'column1' => 'value1', +*			'column2' => 'value2', +*		)); +*	} +* +*	$buffer->flush(); +* </code> +* +* @package dbal +*/ +class phpbb_db_sql_insert_buffer +{ +	/** @var phpbb_db_driver */ +	protected $db; + +	/** @var string */ +	protected $table_name; + +	/** @var int */ +	protected $max_buffered_rows; + +	/** @var array */ +	protected $buffer = array(); + +	/** +	* @param phpbb_db_driver $db +	* @param string          $table_name +	* @param int             $max_buffered_rows +	*/ +	public function __construct(phpbb_db_driver $db, $table_name, $max_buffered_rows = 500) +	{ +		$this->db = $db; +		$this->table_name = $table_name; +		$this->max_buffered_rows = $max_buffered_rows; +	} + +	/** +	* Inserts a single row into the buffer if multi insert is supported by the +	* database (otherwise an insert query is sent immediately). Then flushes +	* the buffer if the number of rows in the buffer is now greater than or +	* equal to $max_buffered_rows. +	* +	* @param array $row +	* +	* @return bool		True when some data was flushed to the database. +	*					False otherwise. +	*/ +	public function insert(array $row) +	{ +		$this->buffer[] = $row; + +		// Flush buffer if it is full or when DB does not support multi inserts. +		// In the later case, the buffer will always only contain one row. +		if (!$this->db->multi_insert || sizeof($this->buffer) >= $this->max_buffered_rows) +		{ +			return $this->flush(); +		} + +		return false; +	} + +	/** +	* Inserts a row set, i.e. an array of rows, by calling insert(). +	* +	* Please note that it is in most cases better to use insert() instead of +	* first building a huge rowset. Or at least sizeof($rows) should be kept +	* small. +	* +	* @param array $rows  +	* +	* @return bool		True when some data was flushed to the database. +	*					False otherwise. +	*/ +	public function insert_all(array $rows) +	{ +		// Using bitwise |= because PHP does not have logical ||= +		$result = 0; + +		foreach ($rows as $row) +		{ +			$result |= (int) $this->insert($row); +		} + +		return (bool) $result; +	} + +	/** +	* Flushes the buffer content to the DB and clears the buffer. +	* +	* @return bool		True when some data was flushed to the database. +	*					False otherwise. +	*/ +	public function flush() +	{ +		if (!empty($this->buffer)) +		{ +			$this->db->sql_multi_insert($this->table_name, $this->buffer); +			$this->buffer = array(); + +			return true; +		} + +		return false; +	} +} | 
