diff options
Diffstat (limited to 'phpBB/phpbb')
66 files changed, 1313 insertions, 172 deletions
| diff --git a/phpBB/phpbb/auth/provider/base.php b/phpBB/phpbb/auth/provider/base.php index 4c49070eaf..dea27ccc25 100644 --- a/phpBB/phpbb/auth/provider/base.php +++ b/phpBB/phpbb/auth/provider/base.php @@ -61,7 +61,7 @@ abstract class base implements \phpbb\auth\provider\provider_interface  	/**  	* {@inheritdoc}  	*/ -	public function get_auth_link_data() +	public function get_auth_link_data($user_id = 0)  	{  		return;  	} diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index c71950c698..c48b771ab0 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -289,7 +289,6 @@ class ldap extends \phpbb\auth\provider\base  	/**  	 * {@inheritdoc}  	 */ -  	public function acp()  	{  		// These are fields required in the config table @@ -308,7 +307,7 @@ class ldap extends \phpbb\auth\provider\base  			'TEMPLATE_VARS'	=> array(  				'AUTH_LDAP_BASE_DN'		=> $new_config['ldap_base_dn'],  				'AUTH_LDAP_EMAIL'		=> $new_config['ldap_email'], -				'AUTH_LDAP_PASSORD'		=> $new_config['ldap_password'], +				'AUTH_LDAP_PASSORD'		=> $new_config['ldap_password'] !== '' ? '********' : '',  				'AUTH_LDAP_PORT'		=> $new_config['ldap_port'],  				'AUTH_LDAP_SERVER'		=> $new_config['ldap_server'],  				'AUTH_LDAP_UID'			=> $new_config['ldap_uid'], diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index c0ce3f1fba..be0fbf5831 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -553,13 +553,13 @@ class oauth extends \phpbb\auth\provider\base  	/**  	* {@inheritdoc}  	*/ -	public function get_auth_link_data() +	public function get_auth_link_data($user_id = 0)  	{  		$block_vars = array();  		// Get all external accounts tied to the current user  		$data = array( -			'user_id' => (int) $this->user->data['user_id'], +			'user_id' => ($user_id <= 0) ? (int) $this->user->data['user_id'] : (int) $user_id,  		);  		$sql = 'SELECT oauth_provider_id, provider FROM ' . $this->auth_provider_oauth_token_account_assoc . '  			WHERE ' . $this->db->sql_build_array('SELECT', $data); @@ -616,10 +616,13 @@ class oauth extends \phpbb\auth\provider\base  			return 'LOGIN_LINK_MISSING_DATA';  		} +		// Remove user specified in $link_data if possible +		$user_id = isset($link_data['user_id']) ? $link_data['user_id'] : $this->user->data['user_id']; +  		// Remove the link  		$sql = 'DELETE FROM ' . $this->auth_provider_oauth_token_account_assoc . "  			WHERE provider = '" . $this->db->sql_escape($link_data['oauth_service']) . "' -				AND user_id = " . (int) $this->user->data['user_id']; +				AND user_id = " . (int) $user_id;  		$this->db->sql_query($sql);  		// Clear all tokens belonging to the user on this servce diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php index 023cf402ca..9b6afae255 100644 --- a/phpBB/phpbb/auth/provider/oauth/token_storage.php +++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php @@ -13,7 +13,6 @@  namespace phpbb\auth\provider\oauth; -  use OAuth\OAuth1\Token\StdOAuth1Token;  use OAuth\Common\Token\TokenInterface;  use OAuth\Common\Storage\TokenStorageInterface; @@ -117,7 +116,8 @@ class token_storage implements TokenStorageInterface  	{  		$service = $this->get_service_name_for_db($service); -		if ($this->cachedToken) { +		if ($this->cachedToken) +		{  			return true;  		} @@ -232,7 +232,8 @@ class token_storage implements TokenStorageInterface  	{  		$service = $this->get_service_name_for_db($service); -		if ($this->cachedToken instanceof TokenInterface) { +		if ($this->cachedToken instanceof TokenInterface) +		{  			return $this->cachedToken;  		} diff --git a/phpBB/phpbb/auth/provider/provider_interface.php b/phpBB/phpbb/auth/provider/provider_interface.php index 613297cefc..35e0f559a1 100644 --- a/phpBB/phpbb/auth/provider/provider_interface.php +++ b/phpBB/phpbb/auth/provider/provider_interface.php @@ -166,6 +166,10 @@ interface provider_interface  	/**  	* Returns an array of data necessary to build the ucp_auth_link page  	* +	* @param int $user_id User ID for whom the data should be retrieved. +	*						defaults to 0, which is not a valid ID. The method +	*						should fall back to the current user's ID in this +	*						case.  	* @return	array|null	If this function is not implemented on an auth  	*						provider then it returns null. If it is implemented  	*						it will return an array of up to four elements of @@ -181,7 +185,7 @@ interface provider_interface  	*							'VARS'				=> array(...),  	*						)  	*/ -	public function get_auth_link_data(); +	public function get_auth_link_data($user_id = 0);  	/**  	* Unlinks an external account from a phpBB account. diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php index 8888686b2d..36087f8ba0 100644 --- a/phpBB/phpbb/avatar/driver/local.php +++ b/phpBB/phpbb/avatar/driver/local.php @@ -23,8 +23,10 @@ class local extends \phpbb\avatar\driver\driver  	*/  	public function get_data($row)  	{ +		$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $this->path_helper->get_web_root_path(); +  		return array( -			'src' => $this->path_helper->get_web_root_path() . $this->config['avatar_gallery_path'] . '/' . $row['avatar'], +			'src' => $root_path . $this->config['avatar_gallery_path'] . '/' . $row['avatar'],  			'width' => $row['avatar_width'],  			'height' => $row['avatar_height'],  		); diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 003b23659f..a1d84345e1 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -24,6 +24,11 @@ class upload extends \phpbb\avatar\driver\driver  	protected $mimetype_guesser;  	/** +	* @var \phpbb\event\dispatcher_interface +	*/ +	protected $dispatcher; + +	/**  	* Construct a driver object  	*  	* @param \phpbb\config\config $config phpBB configuration @@ -31,15 +36,17 @@ class upload extends \phpbb\avatar\driver\driver  	* @param string $php_ext PHP file extension  	* @param \phpbb_path_helper $path_helper phpBB path helper  	* @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser +	* @param \phpbb\event\dispatcher_interface $dispatcher phpBB Event dispatcher object  	* @param \phpbb\cache\driver\driver_interface $cache Cache driver  	*/ -	public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) +	public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\cache\driver\driver_interface $cache = null)  	{  		$this->config = $config;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext;  		$this->path_helper = $path_helper;  		$this->mimetype_guesser = $mimetype_guesser; +		$this->dispatcher = $dispatcher;  		$this->cache = $cache;  	} @@ -48,8 +55,10 @@ class upload extends \phpbb\avatar\driver\driver  	*/  	public function get_data($row, $ignore_config = false)  	{ +		$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $this->path_helper->get_web_root_path(); +  		return array( -			'src' => $this->path_helper->get_web_root_path() . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'], +			'src' => $root_path . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'],  			'width' => $row['avatar_width'],  			'height' => $row['avatar_height'],  		); @@ -135,6 +144,15 @@ class upload extends \phpbb\avatar\driver\driver  		$prefix = $this->config['avatar_salt'] . '_';  		$file->clean_filename('avatar', $prefix, $row['id']); +		// If there was an error during upload, then abort operation +		if (sizeof($file->error)) +		{ +			$file->remove(); +			$error = $file->error; +			return false; +		} + +		// Calculate new destination  		$destination = $this->config['avatar_path'];  		// Adjust destination path (no trailing slash) @@ -149,16 +167,45 @@ class upload extends \phpbb\avatar\driver\driver  			$destination = '';  		} -		// Move file and overwrite any existing image -		$file->move_file($destination, true); +		/** +		* Before moving new file in place (and eventually overwriting the existing avatar with the newly uploaded avatar) +		* +		* @event core.avatar_driver_upload_move_file_before +		* @var	string	destination			Destination directory where the file is going to be moved +		* @var	string	prefix				Prefix for the avatar filename +		* @var	array	row					Array with avatar row data +		* @var	array	error				Array of errors, if filled in by this event file will not be moved +		* @since 3.1.6-RC1 +		*/ +		$vars = array( +			'destination', +			'prefix', +			'row', +			'error', +		); +		extract($this->dispatcher->trigger_event('core.avatar_driver_upload_move_file_before', compact($vars))); -		if (sizeof($file->error)) +		if (!sizeof($error)) +		{ +			// Move file and overwrite any existing image +			$file->move_file($destination, true); +		} + +		// If there was an error during move, then clean up leftovers +		$error = array_merge($error, $file->error); +		if (sizeof($error))  		{  			$file->remove(); -			$error = array_merge($error, $file->error);  			return false;  		} +		// Delete current avatar if not overwritten +		$ext = substr(strrchr($row['avatar'], '.'), 1); +		if ($ext && $ext !== $file->get('extension')) +		{ +			$this->delete($row); +		} +  		return array(  			'avatar' => $row['id'] . '_' . time() . '.' . $file->get('extension'),  			'avatar_width' => $file->get('width'), @@ -183,10 +230,32 @@ class upload extends \phpbb\avatar\driver\driver  	*/  	public function delete($row)  	{ + +		$error = array(); +		$destination = $this->config['avatar_path']; +		$prefix = $this->config['avatar_salt'] . '_';  		$ext = substr(strrchr($row['avatar'], '.'), 1); -		$filename = $this->phpbb_root_path . $this->config['avatar_path'] . '/' . $this->config['avatar_salt'] . '_' . $row['id'] . '.' . $ext; +		$filename = $this->phpbb_root_path . $destination . '/' . $prefix . $row['id'] . '.' . $ext; + +		/** +		* Before deleting an existing avatar +		* +		* @event core.avatar_driver_upload_delete_before +		* @var	string	destination			Destination directory where the file is going to be deleted +		* @var	string	prefix				Prefix for the avatar filename +		* @var	array	row					Array with avatar row data +		* @var	array	error				Array of errors, if filled in by this event file will not be deleted +		* @since 3.1.6-RC1 +		*/ +		$vars = array( +			'destination', +			'prefix', +			'row', +			'error', +		); +		extract($this->dispatcher->trigger_event('core.avatar_driver_upload_delete_before', compact($vars))); -		if (file_exists($filename)) +		if (!sizeof($error) && file_exists($filename))  		{  			@unlink($filename);  		} diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index fd5bce4515..9a7c4aec7f 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -279,6 +279,7 @@ class file extends \phpbb\cache\driver\base  		if ($var_name[0] == '_')  		{  			global $phpEx; +			$var_name = $this->clean_varname($var_name);  			return file_exists($this->cache_dir . 'data' . $var_name . ".$phpEx");  		}  		else @@ -334,6 +335,7 @@ class file extends \phpbb\cache\driver\base  	{  		global $phpEx; +		$filename = $this->clean_varname($filename);  		$file = "{$this->cache_dir}$filename.$phpEx";  		$type = substr($filename, 0, strpos($filename, '_')); @@ -516,6 +518,7 @@ class file extends \phpbb\cache\driver\base  	{  		global $phpEx; +		$filename = $this->clean_varname($filename);  		$file = "{$this->cache_dir}$filename.$phpEx";  		$lock = new \phpbb\lock\flock($file); @@ -584,4 +587,15 @@ class file extends \phpbb\cache\driver\base  		return $return_value;  	} + +	/** +	* Replace slashes in the file name +	* +	* @param string $varname name of a cache variable +	* @return string $varname name that is safe to use as a filename +	*/ +	protected function clean_varname($varname) +	{ +		return str_replace('/', '-', $varname); +	}  } diff --git a/phpBB/phpbb/cache/driver/memcache.php b/phpBB/phpbb/cache/driver/memcache.php index 406ab11ddd..caa82fb0b1 100644 --- a/phpBB/phpbb/cache/driver/memcache.php +++ b/phpBB/phpbb/cache/driver/memcache.php @@ -50,7 +50,7 @@ class memcache extends \phpbb\cache\driver\memory  		parent::__construct();  		$this->memcache = new \Memcache; -		foreach(explode(',', PHPBB_ACM_MEMCACHE) as $u) +		foreach (explode(',', PHPBB_ACM_MEMCACHE) as $u)  		{  			$parts = explode('/', $u);  			$this->memcache->addServer(trim($parts[0]), trim($parts[1])); diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index a7ba994cc3..2771369e57 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -125,7 +125,7 @@ class qa  	*/  	public function is_available()  	{ -		global $config, $db, $phpbb_root_path, $phpEx, $user; +		global $config, $db, $user;  		// load language file for pretty display in the ACP dropdown  		$user->add_lang('captcha_qa'); @@ -263,7 +263,7 @@ class qa  	*/  	function garbage_collect($type = 0)  	{ -		global $db, $config; +		global $db;  		$sql = 'SELECT c.confirm_id  			FROM ' . $this->table_qa_confirm . ' c @@ -310,8 +310,6 @@ class qa  		$db_tool = new \phpbb\db\tools($db); -		$tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm); -  		$schemas = array(  				$this->table_captcha_questions		=> array (  					'COLUMNS' => array( @@ -352,7 +350,7 @@ class qa  				),  		); -		foreach($schemas as $table => $schema) +		foreach ($schemas as $table => $schema)  		{  			if (!$db_tool->sql_table_exists($table))  			{ @@ -366,7 +364,7 @@ class qa  	*/  	function validate()  	{ -		global $config, $db, $user; +		global $user;  		$error = ''; @@ -414,7 +412,7 @@ class qa  		if (!sizeof($this->question_ids))  		{ -			return false; +			return;  		}  		$this->confirm_id = md5(unique_id($user->ip));  		$this->question = (int) array_rand($this->question_ids); @@ -440,7 +438,7 @@ class qa  		if (!sizeof($this->question_ids))  		{ -			return false; +			return;  		}  		$this->question = (int) array_rand($this->question_ids); @@ -611,8 +609,8 @@ class qa  	*/  	function acp_page($id, &$module)  	{ -		global $db, $user, $auth, $template; -		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $user, $template; +		global $config;  		$user->add_lang('acp/board');  		$user->add_lang('captcha_qa'); @@ -674,11 +672,7 @@ class qa  		else  		{  			// okay, show the editor -			$error = false; -			$input_question = request_var('question_text', '', true); -			$input_answers = request_var('answers', '', true); -			$input_lang = request_var('lang_iso', '', true); -			$input_strict = request_var('strict', false); +			$question_input = $this->acp_get_question_input();  			$langs = $this->get_languages();  			foreach ($langs as $lang => $entry) @@ -697,13 +691,11 @@ class qa  			{  				if ($question = $this->acp_get_question_data($question_id))  				{ -					$answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']); -  					$template->assign_vars(array( -						'QUESTION_TEXT'		=> ($input_question) ? $input_question : $question['question_text'], -						'LANG_ISO'			=> ($input_lang) ? $input_lang : $question['lang_iso'], -						'STRICT'			=> (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'], -						'ANSWERS'			=> $answers, +						'QUESTION_TEXT'		=> ($question_input['question_text']) ? $question_input['question_text'] : $question['question_text'], +						'LANG_ISO'			=> ($question_input['lang_iso']) ? $question_input['lang_iso'] : $question['lang_iso'], +						'STRICT'			=> (isset($_REQUEST['strict'])) ? $question_input['strict'] : $question['strict'], +						'ANSWERS'			=> implode("\n", $question['answers']),  					));  				}  				else @@ -714,18 +706,16 @@ class qa  			else  			{  				$template->assign_vars(array( -					'QUESTION_TEXT'		=> $input_question, -					'LANG_ISO'			=> $input_lang, -					'STRICT'			=> $input_strict, -					'ANSWERS'			=> $input_answers, +					'QUESTION_TEXT'		=> $question_input['question_text'], +					'LANG_ISO'			=> $question_input['lang_iso'], +					'STRICT'			=> $question_input['strict'], +					'ANSWERS'			=> (is_array($question_input['answers'])) ? implode("\n", $question_input['answers']) : '',  				));  			}  			if ($submit && check_form_key($form_key))  			{ -				$data = $this->acp_get_question_input(); - -				if (!$this->validate_input($data)) +				if (!$this->validate_input($question_input))  				{  					$template->assign_vars(array(  						'S_ERROR'			=> true, @@ -735,11 +725,11 @@ class qa  				{  					if ($question_id)  					{ -						$this->acp_update_question($data, $question_id); +						$this->acp_update_question($question_input, $question_id);  					}  					else  					{ -						$this->acp_add_question($data); +						$this->acp_add_question($question_input);  					}  					add_log('admin', 'LOG_CONFIG_VISUAL'); @@ -819,6 +809,8 @@ class qa  			return $question;  		} + +		return false;  	}  	/** @@ -827,13 +819,21 @@ class qa  	function acp_get_question_input()  	{  		$answers = utf8_normalize_nfc(request_var('answers', '', true)); + +		// Convert answers into array and filter if answers are set +		if (strlen($answers)) +		{ +			$answers = array_filter(array_map('trim', explode("\n", $answers)), function ($value) { +				return $value !== ''; +			}); +		} +  		$question = array(  			'question_text'	=> request_var('question_text', '', true),  			'strict'		=> request_var('strict', false),  			'lang_iso'		=> request_var('lang_iso', ''), -			'answers'		=> (strlen($answers)) ? explode("\n", $answers) : '', +			'answers'		=> $answers,  		); -  		return $question;  	} diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index 02338a5c2f..0ba0489cb7 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -143,12 +143,43 @@ class content_visibility  	*/  	public function get_visibility_sql($mode, $forum_id, $table_alias = '')  	{ +		$where_sql = ''; + +		$get_visibility_sql_overwrite = false; + +		/** +		* Allow changing the result of calling get_visibility_sql +		* +		* @event core.phpbb_content_visibility_get_visibility_sql_before +		* @var	string		where_sql						Extra visibility conditions. It must end with either an SQL "AND" or an "OR" +		* @var	string		mode							Either "topic" or "post" depending on the query this is being used in +		* @var	array		forum_id						The forum id in which the search is made. +		* @var	string		table_alias						Table alias to prefix in SQL queries +		* @var	mixed		get_visibility_sql_overwrite	If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event +		* 													If false, get_visibility_sql continues normally +		* 													It must be either boolean or string +		* @since 3.1.4-RC1 +		*/ +		$vars = array( +			'where_sql', +			'mode', +			'forum_id', +			'table_alias', +			'get_visibility_sql_overwrite', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_visibility_sql_before', compact($vars))); + +		if ($get_visibility_sql_overwrite !== false) +		{ +			return $get_visibility_sql_overwrite; +		} +  		if ($this->auth->acl_get('m_approve', $forum_id))  		{ -			return '1 = 1'; +			return $where_sql . '1 = 1';  		} -		return $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; +		return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;  	}  	/** @@ -206,7 +237,7 @@ class content_visibility  			if (!sizeof($forum_ids))  			{  				// The user can see all posts/topics in all specified forums -				return $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums); +				return $where_sql . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ')';  			}  			else  			{ @@ -217,8 +248,8 @@ class content_visibility  		else  		{  			// The user is just a normal user -			return $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' -				AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true); +			return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' +				AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . ')';  		}  		$where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index c6c470e91b..a07a396e73 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -13,6 +13,7 @@  namespace phpbb\controller; +use Symfony\Component\HttpFoundation\JsonResponse;  use Symfony\Component\HttpFoundation\Response;  use Symfony\Component\Routing\Generator\UrlGenerator;  use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -142,6 +143,12 @@ class helper  		$base_url = $context->getBaseUrl(); +		// Append page name if base URL does not contain it +		if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false) +		{ +			$base_url .= '/' . $page_name; +		} +  		// If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it.  		$base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url); @@ -206,12 +213,31 @@ class helper  	public function message($message, array $parameters = array(), $title = 'INFORMATION', $code = 200)  	{  		array_unshift($parameters, $message); +		$message_text = call_user_func_array(array($this->user, 'lang'), $parameters); +		$message_title = $this->user->lang($title); + +		if ($this->request->is_ajax()) +		{ +			global $refresh_data; + +			return new JsonResponse( +				array( +					'MESSAGE_TITLE'		=> $message_title, +					'MESSAGE_TEXT'		=> $message_text, +					'S_USER_WARNING'	=> false, +					'S_USER_NOTICE'		=> false, +					'REFRESH_DATA'		=> (!empty($refresh_data)) ? $refresh_data : null +				), +				$code +			); +		} +  		$this->template->assign_vars(array( -			'MESSAGE_TEXT'	=> call_user_func_array(array($this->user, 'lang'), $parameters), -			'MESSAGE_TITLE'	=> $this->user->lang($title), +			'MESSAGE_TEXT'	=> $message_text, +			'MESSAGE_TITLE'	=> $message_title,  		)); -		return $this->render('message_body.html', $this->user->lang($title), $code); +		return $this->render('message_body.html', $message_title, $code);  	}  	/** diff --git a/phpBB/phpbb/cron/task/core/tidy_search.php b/phpBB/phpbb/cron/task/core/tidy_search.php index ce16b3f988..eb3970254f 100644 --- a/phpBB/phpbb/cron/task/core/tidy_search.php +++ b/phpBB/phpbb/cron/task/core/tidy_search.php @@ -20,24 +20,60 @@ namespace phpbb\cron\task\core;  */  class tidy_search extends \phpbb\cron\task\base  { +	/** +	* phpBB root path +	* @var string +	*/  	protected $phpbb_root_path; + +	/** +	* PHP file extension +	* @var string +	*/  	protected $php_ext; + +	/** +	* Auth object +	* @var \phpbb\auth\auth +	*/  	protected $auth; + +	/** +	* Config object +	* @var \phpbb\config\config +	*/  	protected $config; + +	/** +	* Database object +	* @var \phpbb\db\driver\driver_interface +	*/  	protected $db; + +	/** +	* User object +	* @var \phpbb\user +	*/  	protected $user;  	/** +	* Event dispatcher object +	* @var \phpbb\event\dispatcher_interface +	*/ +	protected $phpbb_dispatcher; + +	/**  	* Constructor.  	* -	* @param string $phpbb_root_path The root path +	* @param string $phpbb_root_path The phpBB root path  	* @param string $php_ext The PHP file extension -	* @param \phpbb\auth\auth $auth The auth -	* @param \phpbb\config\config $config The config -	* @param \phpbb\db\driver\driver_interface $db The db connection -	* @param \phpbb\user $user The user +	* @param \phpbb\auth\auth $auth The auth object +	* @param \phpbb\config\config $config The config object +	* @param \phpbb\db\driver\driver_interface $db The database object +	* @param \phpbb\user $user The user object +	* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher The event dispatcher object  	*/ -	public function __construct($phpbb_root_path, $php_ext, \phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\user $user) +	public function __construct($phpbb_root_path, $php_ext, \phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\event\dispatcher_interface $phpbb_dispatcher)  	{  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext; @@ -45,6 +81,7 @@ class tidy_search extends \phpbb\cron\task\base  		$this->config = $config;  		$this->db = $db;  		$this->user = $user; +		$this->phpbb_dispatcher = $phpbb_dispatcher;  	}  	/** @@ -58,7 +95,7 @@ class tidy_search extends \phpbb\cron\task\base  		// We do some additional checks in the module to ensure it can actually be utilised  		$error = false; -		$search = new $search_type($error, $this->phpbb_root_path, $this->php_ext, $this->auth, $this->config, $this->db, $this->user); +		$search = new $search_type($error, $this->phpbb_root_path, $this->php_ext, $this->auth, $this->config, $this->db, $this->user, $this->phpbb_dispatcher);  		if (!$error)  		{ diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_14.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_14.php new file mode 100644 index 0000000000..51475f5a05 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_14.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_14 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return phpbb_version_compare($this->config['version'], '3.0.14', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); +	} + +	static public function depends_on() +	{ +		return array('\phpbb\db\migration\data\v30x\release_3_0_14_rc1'); +	} + +	public function update_data() +	{ +		return array( +			array('if', array( +				phpbb_version_compare($this->config['version'], '3.0.14', '<'), +				array('config.update', array('version', '3.0.14')), +			)), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_14_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_14_rc1.php new file mode 100644 index 0000000000..421ef06dd3 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_14_rc1.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_14_rc1 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return phpbb_version_compare($this->config['version'], '3.0.14-RC1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); +	} + +	static public function depends_on() +	{ +		return array('\phpbb\db\migration\data\v30x\release_3_0_13'); +	} + +	public function update_data() +	{ +		return array( +			array('if', array( +				phpbb_version_compare($this->config['version'], '3.0.14-RC1', '<'), +				array('config.update', array('version', '3.0.14-RC1')), +			)), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v310/avatars.php b/phpBB/phpbb/db/migration/data/v310/avatars.php index 2698adeed5..9b03a8fa94 100644 --- a/phpBB/phpbb/db/migration/data/v310/avatars.php +++ b/phpBB/phpbb/db/migration/data/v310/avatars.php @@ -17,7 +17,29 @@ class avatars extends \phpbb\db\migration\migration  {  	public function effectively_installed()  	{ -		return isset($this->config['allow_avatar_gravatar']); +		// Get current avatar type of guest user +		$sql = 'SELECT user_avatar_type +			FROM ' . $this->table_prefix . 'users +			WHERE user_id = ' . ANONYMOUS; +		$result = $this->db->sql_query($sql); +		$backup_type = $this->db->sql_fetchfield('user_avatar_type'); +		$this->db->sql_freeresult($result); + +		// Try to set avatar type to string +		$sql = 'UPDATE ' . $this->table_prefix . "users +			SET user_avatar_type = 'avatar.driver.upload' +			WHERE user_id = " . ANONYMOUS; +		$this->db->sql_return_on_error(true); +		$effectively_installed = $this->db->sql_query($sql); +		$this->db->sql_return_on_error(); + +		// Restore avatar type of guest user to previous state +		$sql = 'UPDATE ' . $this->table_prefix . "users +			SET user_avatar_type = '{$backup_type}' +			WHERE user_id = " . ANONYMOUS; +		$this->db->sql_query($sql); + +		return $effectively_installed !== false;  	}  	static public function depends_on() diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php index e8d3a3af64..3b0d53d803 100644 --- a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php @@ -136,7 +136,7 @@ class style_update_p1 extends \phpbb\db\migration\migration  		if (!sizeof($valid_styles))  		{  			// No valid styles: remove everything and add prosilver -			$this->sql_query('DELETE FROM ' . STYLES_TABLE, $errored, $error_ary); +			$this->sql_query('DELETE FROM ' . STYLES_TABLE);  			$sql_ary = array(  				'style_name'		=> 'prosilver', @@ -157,13 +157,13 @@ class style_update_p1 extends \phpbb\db\migration\migration  			$this->sql_query($sql);  			$sql = 'SELECT style_id -				FROM ' . $table . " +				FROM ' . STYLES_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); +			$this->config->set('default_style', $default_style);  			$sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = 0';  			$this->sql_query($sql); diff --git a/phpBB/phpbb/db/migration/data/v31x/v314.php b/phpBB/phpbb/db/migration/data/v31x/v314.php new file mode 100644 index 0000000000..b7793ca569 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v314.php @@ -0,0 +1,32 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v314 extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v30x\release_3_0_14', +			'\phpbb\db\migration\data\v31x\v314rc2', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.1.4')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v314rc1.php b/phpBB/phpbb/db/migration/data/v31x/v314rc1.php new file mode 100644 index 0000000000..10cdbe3f9c --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v314rc1.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v314rc1 extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v31x\v313', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.1.4-RC1')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v314rc2.php b/phpBB/phpbb/db/migration/data/v31x/v314rc2.php new file mode 100644 index 0000000000..b75b7a9be8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v314rc2.php @@ -0,0 +1,32 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v314rc2 extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v30x\release_3_0_14_rc1', +			'\phpbb\db\migration\data\v31x\v314rc1', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.1.4-RC2')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v315.php b/phpBB/phpbb/db/migration/data/v31x/v315.php new file mode 100644 index 0000000000..778cdf717e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v315.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v315 extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v31x\v315rc1', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.1.5')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v315rc1.php b/phpBB/phpbb/db/migration/data/v31x/v315rc1.php new file mode 100644 index 0000000000..4cf4472aa7 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v315rc1.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v315rc1 extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v31x\v314', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.1.5-RC1')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php index 1a91127d2d..ceff6d7d5a 100644 --- a/phpBB/phpbb/db/migration/tool/permission.php +++ b/phpBB/phpbb/db/migration/tool/permission.php @@ -425,13 +425,27 @@ class permission implements \phpbb\db\migration\tool\tool_interface  				$role_id = (int) $this->db->sql_fetchfield('auth_role_id');  				if ($role_id)  				{ -					$sql = 'SELECT role_name +					$sql = 'SELECT role_name, role_type  						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); +					$role_data = $this->db->sql_fetchrow(); +					$role_name = $role_data['role_name']; +					$role_type = $role_data['role_type']; + +					// Filter new auth options to match the role type: a_ | f_ | m_ | u_ +					// Set new auth options to the role only if options matching the role type were found +					$auth_option = array_filter($auth_option, +						function ($option) use ($role_type) +						{ +							return strpos($option, $role_type) === 0; +						} +					); + +					if (sizeof($auth_option)) +					{ +						return $this->permission_set($role_name, $auth_option, 'role', $has_permission); +					}  				}  				$sql = 'SELECT auth_option_id, auth_setting diff --git a/phpBB/phpbb/db/sql_insert_buffer.php b/phpBB/phpbb/db/sql_insert_buffer.php index 14e3c54f09..18e4814a77 100644 --- a/phpBB/phpbb/db/sql_insert_buffer.php +++ b/phpBB/phpbb/db/sql_insert_buffer.php @@ -107,7 +107,7 @@ class sql_insert_buffer  	* first building a huge rowset. Or at least sizeof($rows) should be kept  	* small.  	* -	* @param array $rows  +	* @param array $rows  	*  	* @return bool		True when some data was flushed to the database.  	*					False otherwise. diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 638c13e86d..a214356ac3 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -399,7 +399,6 @@ class container_builder  	*/  	protected function get_container_filename()  	{ -		$filename = str_replace(array('/', '.'), array('slash', 'dot'), $this->phpbb_root_path); -		return $this->phpbb_root_path . 'cache/container_' . $filename . '.' . $this->php_ext; +		return $this->phpbb_root_path . 'cache/container_' . md5($this->phpbb_root_path) . '.' . $this->php_ext;  	}  } diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index f7021875f3..02c2a1b9d6 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -24,6 +24,12 @@ class md_exporter  	/** @var string phpBB Root Path */  	protected $root_path; +	/** @var string The minimum version for the events to return */ +	protected $min_version; + +	/** @var string The maximum version for the events to return */ +	protected $max_version; +  	/** @var string */  	protected $filter; @@ -36,8 +42,10 @@ class md_exporter  	/**  	* @param string $phpbb_root_path  	* @param mixed $extension	String 'vendor/ext' to filter, null for phpBB core +	* @param string $min_version +	* @param string $max_version  	*/ -	public function __construct($phpbb_root_path, $extension = null) +	public function __construct($phpbb_root_path, $extension = null, $min_version = null, $max_version = null)  	{  		$this->root_path = $phpbb_root_path;  		$this->path = $this->root_path; @@ -49,6 +57,8 @@ class md_exporter  		$this->events = array();  		$this->events_by_file = array();  		$this->filter = $this->current_event = ''; +		$this->min_version = $min_version; +		$this->max_version = $max_version;  	}  	/** @@ -147,15 +157,64 @@ class md_exporter  			}  			list($file_details, $details) = explode("\n* Since: ", $details, 2); -			list($since, $description) = explode("\n* Purpose: ", $details, 2); + +			$changed_versions = array(); +			if (strpos($details, "\n* Changed: ") !== false) +			{ +				list($since, $details) = explode("\n* Changed: ", $details, 2); +				while (strpos($details, "\n* Changed: ") !== false) +				{ +					list($changed, $details) = explode("\n* Changed: ", $details, 2); +					$changed_versions[] = $changed; +				} +				list($changed, $description) = explode("\n* Purpose: ", $details, 2); +				$changed_versions[] = $changed; +			} +			else +			{ +				list($since, $description) = explode("\n* Purpose: ", $details, 2); +				$changed_versions = array(); +			}  			$files = $this->validate_file_list($file_details);  			$since = $this->validate_since($since); +			$changes = array(); +			foreach ($changed_versions as $changed) +			{ +				list($changed_version, $changed_description) = $this->validate_changed($changed); + +				if (isset($changes[$changed_version])) +				{ +					throw new \LogicException("Duplicate change information found for event '{$this->current_event}'"); +				} + +				$changes[$changed_version] = $changed_description; +			} +			$description = trim($description, "\n") . "\n"; + +			if (!$this->version_is_filtered($since)) +			{ +				$is_filtered = false; +				foreach ($changes as $version => $null) +				{ +					if ($this->version_is_filtered($version)) +					{ +						$is_filtered = true; +						break; +					} +				} + +				if (!$is_filtered) +				{ +					continue; +				} +			}  			$this->events[$event_name] = array(  				'event'			=> $this->current_event,  				'files'			=> $files,  				'since'			=> $since, +				'changed'		=> $changes,  				'description'	=> $description,  			);  		} @@ -164,20 +223,48 @@ class md_exporter  	}  	/** +	 * The version to check +	 * +	 * @param string $version +	 * @return bool +	 */ +	protected function version_is_filtered($version) +	{ +		return (!$this->min_version || phpbb_version_compare($this->min_version, $version, '<=')) +		&& (!$this->max_version || phpbb_version_compare($this->max_version, $version, '>=')); +	} + +	/**  	* Format the php events as a wiki table +	* +	* @param string $action  	* @return string		Number of events found  	*/ -	public function export_events_for_wiki() +	public function export_events_for_wiki($action = '')  	{  		if ($this->filter === 'adm')  		{ -			$wiki_page = '= ACP Template Events =' . "\n"; +			if ($action === 'diff') +			{ +				$wiki_page = '=== ACP Template Events ===' . "\n"; +			} +			else +			{ +				$wiki_page = '= ACP Template Events =' . "\n"; +			}  			$wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";  			$wiki_page .= '! Identifier !! Placement !! Added in Release !! Explanation' . "\n";  		}  		else  		{ -			$wiki_page = '= Template Events =' . "\n"; +			if ($action === 'diff') +			{ +				$wiki_page = '=== Template Events ===' . "\n"; +			} +			else +			{ +				$wiki_page = '= Template Events =' . "\n"; +			}  			$wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";  			$wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Subsilver Placement (If applicable) !! Added in Release !! Explanation' . "\n";  		} @@ -227,7 +314,7 @@ class md_exporter  	*/  	public function validate_since($since)  	{ -		if (!preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?$#', $since)) +		if (!$this->validate_version($since))  		{  			throw new \LogicException("Invalid since information found for event '{$this->current_event}'");  		} @@ -236,6 +323,44 @@ class md_exporter  	}  	/** +	* Validate "Changed" Information +	* +	* @param string $changed +	* @return string +	* @throws \LogicException +	*/ +	public function validate_changed($changed) +	{ +		if (strpos($changed, ' ') !== false) +		{ +			list($version, $description) = explode(' ', $changed, 2); +		} +		else +		{ +			$version = $changed; +			$description = ''; +		} + +		if (!$this->validate_version($version)) +		{ +			throw new \LogicException("Invalid changed information found for event '{$this->current_event}'"); +		} + +		return array($version, $description); +	} + +	/** +	* Validate "version" Information +	* +	* @param string $version +	* @return bool True if valid, false otherwise +	*/ +	public function validate_version($version) +	{ +		return preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?$#', $version); +	} + +	/**  	* Validate the files list  	*  	* @param string $file_details diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index 35144eeeec..d2ab0595c0 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -25,6 +25,12 @@ class php_exporter  	/** @var string phpBB Root Path */  	protected $root_path; +	/** @var string The minimum version for the events to return */ +	protected $min_version; + +	/** @var string The maximum version for the events to return */ +	protected $max_version; +  	/** @var string */  	protected $current_file; @@ -43,14 +49,18 @@ class php_exporter  	/**  	* @param string $phpbb_root_path  	* @param mixed $extension	String 'vendor/ext' to filter, null for phpBB core +	* @param string $min_version +	* @param string $max_version  	*/ -	public function __construct($phpbb_root_path, $extension = null) +	public function __construct($phpbb_root_path, $extension = null, $min_version = null, $max_version = null)  	{  		$this->root_path = $phpbb_root_path;  		$this->path = $phpbb_root_path;  		$this->events = $this->file_lines = array();  		$this->current_file = $this->current_event = '';  		$this->current_event_line = 0; +		$this->min_version = $min_version; +		$this->max_version = $max_version;  		$this->path = $this->root_path;  		if ($extension) @@ -148,11 +158,20 @@ class php_exporter  	/**  	* Format the php events as a wiki table +	* +	* @param string $action  	* @return string  	*/ -	public function export_events_for_wiki() +	public function export_events_for_wiki($action = '')  	{ -		$wiki_page = '= PHP Events (Hook Locations) =' . "\n"; +		if ($action === 'diff') +		{ +			$wiki_page = '=== PHP Events (Hook Locations) ===' . "\n"; +		} +		else +		{ +			$wiki_page = '= PHP Events (Hook Locations) =' . "\n"; +		}  		$wiki_page .= '{| class="sortable zebra" cellspacing="0" cellpadding="5"' . "\n";  		$wiki_page .= '! Identifier !! Placement !! Arguments !! Added in Release !! Explanation' . "\n";  		foreach ($this->events as $event) @@ -215,6 +234,34 @@ class php_exporter  					$since_line_num = $this->find_since();  					$since = $this->validate_since($this->file_lines[$since_line_num]); +					$changed_line_nums = $this->find_changed('changed'); +					if (empty($changed_line_nums)) +					{ +						$changed_line_nums = $this->find_changed('change'); +					} +					$changed_versions = array(); +					if (!empty($changed_line_nums)) +					{ +						foreach ($changed_line_nums as $changed_line_num) +						{ +							$changed_versions[] = $this->validate_changed($this->file_lines[$changed_line_num]); +						} +					} + +					if (!$this->version_is_filtered($since)) +					{ +						$valid_version = false; +						foreach ($changed_versions as $changed) +						{ +							$valid_version = $valid_version || $this->version_is_filtered($changed); +						} + +						if (!$valid_version) +						{ +							continue; +						} +					} +  					// Find event description line  					$description_line_num = $this->find_description();  					$description = substr(trim($this->file_lines[$description_line_num]), strlen('* ')); @@ -243,6 +290,18 @@ class php_exporter  	}  	/** +	 * The version to check +	 * +	 * @param string $version +	 * @return bool +	 */ +	protected function version_is_filtered($version) +	{ +		return (!$this->min_version || phpbb_version_compare($this->min_version, $version, '<=')) +			&& (!$this->max_version || phpbb_version_compare($this->max_version, $version, '>=')); +	} + +	/**  	* Find the name of the event inside the dispatch() line  	*  	* @param int $event_line @@ -449,6 +508,33 @@ class php_exporter  	}  	/** +	* Find the "@changed" Information lines +	* +	* @param string $tag_name Should be 'changed' or 'change' +	* @return array Absolute line numbers +	* @throws \LogicException +	*/ +	public function find_changed($tag_name) +	{ +		$lines = array(); +		$last_line = 0; +		try +		{ +			while ($line = $this->find_tag($tag_name, array('since'), $last_line)) +			{ +				$lines[] = $line; +				$last_line = $line; +			} +		} +		catch (\LogicException $e) +		{ +			// Not changed? No problem! +		} + +		return $lines; +	} + +	/**  	* Find the "@event" Information line  	*  	* @return int Absolute line number @@ -464,13 +550,14 @@ class php_exporter  	* @param string $find_tag		Name of the tag we are trying to find  	* @param array $disallowed_tags		List of tags that must not appear between  	*									the tag and the actual event +	* @param int $skip_to_line		Skip lines until this one  	* @return int Absolute line number  	* @throws \LogicException  	*/ -	public function find_tag($find_tag, $disallowed_tags) +	public function find_tag($find_tag, $disallowed_tags, $skip_to_line = 0)  	{ -		$find_tag_line = 0; -		$found_comment_end = false; +		$find_tag_line = $skip_to_line ? $this->current_event_line - $skip_to_line + 1 : 0; +		$found_comment_end = ($skip_to_line) ? true : false;  		while (strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t "), '* @' . $find_tag . ' ') !== 0)  		{  			if ($found_comment_end && ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '/**') @@ -561,6 +648,27 @@ class php_exporter  	}  	/** +	* Validate "@changed" Information +	* +	* @param string $line +	* @return string +	* @throws \LogicException +	*/ +	public function validate_changed($line) +	{ +		$match = array(); +		$line = str_replace("\t", ' ', ltrim($line, "\t ")); +		preg_match('#^\* @change(d)? (\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?)( (?:.*))?$#', $line, $match); +		if (!isset($match[2])) +		{ +			throw new \LogicException("Invalid '@changed' information for event " +				. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); +		} + +		return $match[2]; +	} + +	/**  	* Validate "@event" Information  	*  	* @param string $event_name diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 0c5205530b..3d995b4e4a 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -521,15 +521,77 @@ class log implements \phpbb\log\log_interface  			$sql_keywords = $this->generate_sql_keyword($keywords);  		} -		if ($count_logs) -		{ -			$sql = 'SELECT COUNT(l.log_id) AS total_entries -				FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u -				WHERE l.log_type = ' . (int) $log_type . ' +		$get_logs_sql_ary = array( +			'SELECT' => 'l.*, u.username, u.username_clean, u.user_colour', +			'FROM' => array( +						$this->log_table => 'l', +						USERS_TABLE => 'u', +					), +			'WHERE' => 'l.log_type = ' . (int) $log_type . "  					AND l.user_id = u.user_id -					AND l.log_time >= ' . (int) $log_time . "  					$sql_keywords -					$sql_additional"; +					$sql_additional", + +			'ORDER_BY' => $sort_by, +		); + +		if ($log_time) +		{ +			$get_logs_sql_ary['WHERE'] = 'l.log_time >= ' . (int) $log_time . ' +					AND ' . $get_logs_sql_ary['WHERE']; +		} + +		/** +		* Modify the query to obtain the logs data +		* +		* @event core.get_logs_main_query_before +		* @var	array	get_logs_sql_ary	The array in the format of the query builder with the query +		*									to get the log count and the log list +		* @var	string	mode				Mode of the entries we display +		* @var	bool	count_logs			Do we count all matching entries? +		* @var	int		limit				Limit the number of entries +		* @var	int		offset				Offset when fetching the entries +		* @var	mixed	forum_id			Limit entries to the forum_id, +		*									can also be an array of forum_ids +		* @var	int		topic_id			Limit entries to the topic_id +		* @var	int		user_id				Limit entries to the user_id +		* @var	int		log_time			Limit maximum age of log entries +		* @var	string	sort_by				SQL order option +		* @var	string	keywords			Will only return entries that have the +		*									keywords in log_operation or log_data +		* @var	string	profile_url			URL to the users profile +		* @var	int		log_type			Limit logs to a certain type. If log_type +		*									is false, no entries will be returned. +		* @var	string	sql_additional		Additional conditions for the entries, +		*									e.g.: 'AND l.forum_id = 1' +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'get_logs_sql_ary', +			'mode', +			'count_logs', +			'limit', +			'offset', +			'forum_id', +			'topic_id', +			'user_id', +			'log_time', +			'sort_by', +			'keywords', +			'profile_url', +			'log_type', +			'sql_additional', +		); +		extract($this->dispatcher->trigger_event('core.get_logs_main_query_before', compact($vars))); + +		if ($count_logs) +		{ +			$count_logs_sql_ary = $get_logs_sql_ary; + +			$count_logs_sql_ary['SELECT'] = 'COUNT(l.log_id) AS total_entries'; +			unset($count_logs_sql_ary['ORDER_BY']); + +			$sql = $this->db->sql_build_query('SELECT', $count_logs_sql_ary);  			$result = $this->db->sql_query($sql);  			$this->entry_count = (int) $this->db->sql_fetchfield('total_entries');  			$this->db->sql_freeresult($result); @@ -548,14 +610,7 @@ class log implements \phpbb\log\log_interface  			}  		} -		$sql = 'SELECT l.*, u.username, u.username_clean, u.user_colour -			FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u -			WHERE l.log_type = ' . (int) $log_type . ' -				AND u.user_id = l.user_id -				' . (($log_time) ? 'AND l.log_time >= ' . (int) $log_time : '') . " -				$sql_keywords -				$sql_additional -			ORDER BY $sort_by"; +		$sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary);  		$result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset);  		$i = 0; diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php index a0bbed6fcd..6ee1d2984a 100644 --- a/phpBB/phpbb/notification/method/base.php +++ b/phpBB/phpbb/notification/method/base.php @@ -60,7 +60,7 @@ abstract class base implements \phpbb\notification\method\method_interface  	/**  	* Notification Method Base Constructor -	*  +	*  	* @param \phpbb\user_loader $user_loader  	* @param \phpbb\db\driver\driver_interface $db  	* @param \phpbb\cache\driver\driver_interface $cache @@ -85,7 +85,7 @@ abstract class base implements \phpbb\notification\method\method_interface  	/**  	* Set notification manager (required) -	*  +	*  	* @param \phpbb\notification\manager $notification_manager  	*/  	public function set_notification_manager(\phpbb\notification\manager $notification_manager) diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index bde4573117..c3aee088f9 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -69,7 +69,7 @@ abstract class messenger_base extends \phpbb\notification\method\base  			$user = $this->user_loader->get_user($notification->user_id); -			if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users)) +			if ($user['user_type'] == USER_IGNORE || ($user['user_type'] == USER_INACTIVE && $user['user_inactive_reason'] == INACTIVE_MANUAL) || in_array($notification->user_id, $banned_users))  			{  				continue;  			} diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php index dfc0157558..7c5c18aa47 100644 --- a/phpBB/phpbb/notification/type/admin_activate_user.php +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -104,7 +104,7 @@ class admin_activate_user extends \phpbb\notification\type\base  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->item_id); +		return $this->user_loader->get_avatar($this->item_id, false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php index 4baf516fed..96bfc86322 100644 --- a/phpBB/phpbb/notification/type/group_request.php +++ b/phpBB/phpbb/notification/type/group_request.php @@ -96,7 +96,7 @@ class group_request extends \phpbb\notification\type\base  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->item_id); +		return $this->user_loader->get_avatar($this->item_id, false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 330a70c85a..d2f34f95d0 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -100,7 +100,7 @@ class pm extends \phpbb\notification\type\base  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('from_user_id')); +		return $this->user_loader->get_avatar($this->get_data('from_user_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index 421eff6372..e25fdcd808 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -165,7 +165,7 @@ class post extends \phpbb\notification\type\base  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('poster_id')); +		return $this->user_loader->get_avatar($this->get_data('poster_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index d39143f4b7..749cfe0b8e 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -223,7 +223,7 @@ class report_pm extends \phpbb\notification\type\pm  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('reporter_id')); +		return $this->user_loader->get_avatar($this->get_data('reporter_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php index 9f301ee2cc..1c99db60c3 100644 --- a/phpBB/phpbb/notification/type/report_pm_closed.php +++ b/phpBB/phpbb/notification/type/report_pm_closed.php @@ -130,7 +130,7 @@ class report_pm_closed extends \phpbb\notification\type\pm  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('closer_id')); +		return $this->user_loader->get_avatar($this->get_data('closer_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php index 027cca716b..aed31e8642 100644 --- a/phpBB/phpbb/notification/type/report_post.php +++ b/phpBB/phpbb/notification/type/report_post.php @@ -196,7 +196,7 @@ class report_post extends \phpbb\notification\type\post_in_queue  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('reporter_id')); +		return $this->user_loader->get_avatar($this->get_data('reporter_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php index a0bb187a0d..3f4378628b 100644 --- a/phpBB/phpbb/notification/type/report_post_closed.php +++ b/phpBB/phpbb/notification/type/report_post_closed.php @@ -137,7 +137,7 @@ class report_post_closed extends \phpbb\notification\type\post  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('closer_id')); +		return $this->user_loader->get_avatar($this->get_data('closer_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 5f57087b73..fb08a9eee1 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -119,7 +119,7 @@ class topic extends \phpbb\notification\type\base  	*/  	public function get_avatar()  	{ -		return $this->user_loader->get_avatar($this->get_data('poster_id')); +		return $this->user_loader->get_avatar($this->get_data('poster_id'), false, true);  	}  	/** diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index caa65080ac..f80c3e3df6 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -153,11 +153,23 @@ class helper  	 */  	public function string_compare($string_a, $string_b)  	{ -		$difference = strlen($string_a) != strlen($string_b); +		// Return if input variables are not strings or if length does not match +		if (!is_string($string_a) || !is_string($string_b) || strlen($string_a) != strlen($string_b)) +		{ +			return false; +		} + +		// Use hash_equals() if it's available +		if (function_exists('hash_equals')) +		{ +			return hash_equals($string_a, $string_b); +		} + +		$difference = 0;  		for ($i = 0; $i < strlen($string_a) && $i < strlen($string_b); $i++)  		{ -			$difference |= $string_a[$i] != $string_b[$i]; +			$difference |= ord($string_a[$i]) ^ ord($string_b[$i]);  		}  		return $difference === 0; diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index fbb49d86a0..aa9147ecf4 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -56,7 +56,7 @@ class manager  	* @param array $hashing_algorithms Hashing driver  	*			service collection  	* @param \phpbb\passwords\helper $helper Passwords helper object -	* @param string $defaults List of default driver types +	* @param array $defaults List of default driver types  	*/  	public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults)  	{ diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php index 9b3dcadf32..82f59b5c20 100644 --- a/phpBB/phpbb/permissions.php +++ b/phpBB/phpbb/permissions.php @@ -277,13 +277,14 @@ class permissions  		'm_approve'		=> array('lang' => 'ACL_M_APPROVE', 'cat' => 'post_actions'),  		'm_report'		=> array('lang' => 'ACL_M_REPORT', 'cat' => 'post_actions'),  		'm_chgposter'	=> array('lang' => 'ACL_M_CHGPOSTER', 'cat' => 'post_actions'), +		'm_info'		=> array('lang' => 'ACL_M_INFO', 'cat' => 'post_actions'), +		'm_softdelete'	=> array('lang' => 'ACL_M_SOFTDELETE', 'cat' => 'post_actions'),  		'm_move'	=> array('lang' => 'ACL_M_MOVE', 'cat' => 'topic_actions'),  		'm_lock'	=> array('lang' => 'ACL_M_LOCK', 'cat' => 'topic_actions'),  		'm_split'	=> array('lang' => 'ACL_M_SPLIT', 'cat' => 'topic_actions'),  		'm_merge'	=> array('lang' => 'ACL_M_MERGE', 'cat' => 'topic_actions'), -		'm_info'	=> array('lang' => 'ACL_M_INFO', 'cat' => 'misc'),  		'm_warn'	=> array('lang' => 'ACL_M_WARN', 'cat' => 'misc'),  		'm_ban'		=> array('lang' => 'ACL_M_BAN', 'cat' => 'misc'), diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php index 3c686a552f..ca78167ec0 100644 --- a/phpBB/phpbb/plupload/plupload.php +++ b/phpBB/phpbb/plupload/plupload.php @@ -267,8 +267,8 @@ class plupload  		{  			$resize = sprintf(  				'resize: {width: %d, height: %d, quality: 100},', -				(int) $this->config['img_max_height'], -				(int) $this->config['img_max_width'] +				(int) $this->config['img_max_width'], +				(int) $this->config['img_max_height']  			);  		} @@ -326,7 +326,7 @@ class plupload  		$tmp_file = $this->temporary_filepath($upload['tmp_name']); -		if (!move_uploaded_file($upload['tmp_name'], $tmp_file)) +		if (!phpbb_is_writable($this->temporary_directory) || !move_uploaded_file($upload['tmp_name'], $tmp_file))  		{  			$this->emit_error(103, 'PLUPLOAD_ERR_MOVE_UPLOADED');  		} diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index 1a0aba096f..bad2003000 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -43,6 +43,12 @@ class fulltext_mysql extends \phpbb\search\base  	protected $db;  	/** +	 * phpBB event dispatcher object +	 * @var \phpbb\event\dispatcher_interface +	 */ +	protected $phpbb_dispatcher; + +	/**  	 * User object  	 * @var \phpbb\user  	 */ @@ -79,11 +85,13 @@ class fulltext_mysql extends \phpbb\search\base  	 * @param \phpbb\config\config $config Config object  	 * @param \phpbb\db\driver\driver_interface Database object  	 * @param \phpbb\user $user User object +	 * @param \phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	 */ -	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user) +	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher)  	{  		$this->config = $config;  		$this->db = $db; +		$this->phpbb_dispatcher = $phpbb_dispatcher;  		$this->user = $user;  		$this->word_length = array('min' => $this->config['fulltext_mysql_min_word_len'], 'max' => $this->config['fulltext_mysql_max_word_len']); @@ -447,6 +455,55 @@ class fulltext_mysql extends \phpbb\search\base  			break;  		} +		$search_query = $this->search_query; + +		/** +		* Allow changing the query used to search for posts using fulltext_mysql +		* +		* @event core.search_mysql_keywords_main_query_before +		* @var	string	search_query		The parsed keywords used for this search +		* @var	int		result_count		The previous result count for the format of the query. +		*									Set to 0 to force a re-count +		* @var	bool	join_topic			Weather or not TOPICS_TABLE should be CROSS JOIN'ED +		* @var	array	author_ary			Array of user_id containing the users to filter the results to +		* @var	string	author_name			An extra username to search on (!empty(author_ary) must be true, to be relevant) +		* @var	array	ex_fid_ary			Which forums not to search on +		* @var	int		topic_id			Limit the search to this topic_id only +		* @var	string	sql_sort_table		Extra tables to include in the SQL query. +		*									Used in conjunction with sql_sort_join +		* @var	string	sql_sort_join		SQL conditions to join all the tables used together. +		*									Used in conjunction with sql_sort_table +		* @var	int		sort_days			Time, in days, of the oldest possible post to list +		* @var	string	sql_match			Which columns to do the search on. +		* @var	string	sql_match_where		Extra conditions to use to properly filter the matching process +		* @var	string	sort_by_sql			The possible predefined sort types +		* @var	string	sort_key			The sort type used from the possible sort types +		* @var	string	sort_dir			"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort			The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	int		start				How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'search_query', +			'result_count', +			'join_topic', +			'author_ary', +			'author_name', +			'ex_fid_ary', +			'topic_id', +			'sql_sort_table', +			'sql_sort_join', +			'sort_days', +			'sql_match', +			'sql_match_where', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_keywords_main_query_before', compact($vars))); +  		$sql_select			= (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : '';  		$sql_select			= ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';  		$sql_from			= ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; @@ -620,6 +677,59 @@ class fulltext_mysql extends \phpbb\search\base  		$m_approve_fid_sql = ' AND ' . $post_visibility; +		/** +		* Allow changing the query used to search for posts by author in fulltext_mysql +		* +		* @event core.search_mysql_author_query_before +		* @var	int		result_count		The previous result count for the format of the query. +		*									Set to 0 to force a re-count +		* @var	string	sql_sort_table		CROSS JOIN'ed table to allow doing the sort chosen +		* @var	string	sql_sort_join		Condition to define how to join the CROSS JOIN'ed table specifyed in sql_sort_table +		* @var	string	type				Either "posts" or "topics" specifying the type of search being made +		* @var	array	author_ary			Array of user_id containing the users to filter the results to +		* @var	string	author_name			An extra username to search on +		* @var	string	sql_author			SQL WHERE condition for the post author ids +		* @var	int		topic_id			Limit the search to this topic_id only +		* @var	string	sql_topic_id		SQL of topic_id +		* @var	string	sort_by_sql			The possible predefined sort types +		* @var	string	sort_key			The sort type used from the possible sort types +		* @var	string	sort_dir			"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort			The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	string	sort_days			Time, in days, that the oldest post showing can have +		* @var	string	sql_time			The SQL to search on the time specifyed by sort_days +		* @var	bool	firstpost_only		Wether or not to search only on the first post of the topics +		* @var	string	sql_firstpost		The SQL with the conditions to join the tables when using firstpost_only +		* @var	array	ex_fid_ary			Forum ids that must not be searched on +		* @var	array	sql_fora			SQL query for ex_fid_ary +		* @var	string	m_approve_fid_sql	WHERE clause condition on post_visibility restrictions +		* @var	int		start				How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'result_count', +			'sql_sort_table', +			'sql_sort_join', +			'type', +			'author_ary', +			'author_name', +			'sql_author', +			'topic_id', +			'sql_topic_id', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'sort_days', +			'sql_time', +			'firstpost_only', +			'sql_firstpost', +			'ex_fid_ary', +			'sql_fora', +			'm_approve_fid_sql', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_author_query_before', compact($vars))); +  		// If the cache was completely empty count the results  		$calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS '; diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 93ea46ca60..7c825029fb 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -87,6 +87,12 @@ class fulltext_native extends \phpbb\search\base  	protected $db;  	/** +	 * phpBB event dispatcher object +	 * @var \phpbb\event\dispatcher_interface +	 */ +	protected $phpbb_dispatcher; + +	/**  	 * User object  	 * @var \phpbb\user  	 */ @@ -96,13 +102,15 @@ class fulltext_native extends \phpbb\search\base  	* Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded  	*  	* @param	boolean|string	&$error	is passed by reference and should either be set to false on success or an error message on failure +	* @param	\phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	*/ -	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user) +	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher)  	{  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $phpEx;  		$this->config = $config;  		$this->db = $db; +		$this->phpbb_dispatcher = $phpbb_dispatcher;  		$this->user = $user;  		$this->word_length = array('min' => $this->config['fulltext_native_min_chars'], 'max' => $this->config['fulltext_native_max_chars']); @@ -712,6 +720,70 @@ class fulltext_native extends \phpbb\search\base  		$sql_where[] = $post_visibility; +		$search_query = $this->search_query; +		$must_exclude_one_ids = $this->must_exclude_one_ids; +		$must_not_contain_ids = $this->must_not_contain_ids; +		$must_contain_ids = $this->must_contain_ids; + +		/** +		* Allow changing the query used for counting for posts using fulltext_native +		* +		* @event core.search_native_keywords_count_query_before +		* @var	string	search_query			The parsed keywords used for this search +		* @var	array	must_not_contain_ids	Ids that cannot be taken into account for the results +		* @var	array	must_exclude_one_ids	Ids that cannot be on the results +		* @var	array	must_contain_ids		Ids that must be on the results +		* @var	int		total_results			The previous result count for the format of the query +		*										Set to 0 to force a re-count +		* @var	array	sql_array				The data on how to search in the DB at this point +		* @var	bool	left_join_topics		Whether or not TOPICS_TABLE should be CROSS JOIN'ED +		* @var	array	author_ary				Array of user_id containing the users to filter the results to +		* @var	string	author_name				An extra username to search on (!empty(author_ary) must be true, to be relevant) +		* @var	array	ex_fid_ary				Which forums not to search on +		* @var	int		topic_id				Limit the search to this topic_id only +		* @var	string	sql_sort_table			Extra tables to include in the SQL query. +		*										Used in conjunction with sql_sort_join +		* @var	string	sql_sort_join			SQL conditions to join all the tables used together. +		*										Used in conjunction with sql_sort_table +		* @var	int		sort_days				Time, in days, of the oldest possible post to list +		* @var	string	sql_where				An array of the current WHERE clause conditions +		* @var	string	sql_match				Which columns to do the search on +		* @var	string	sql_match_where			Extra conditions to use to properly filter the matching process +		* @var	bool	group_by				Whether or not the SQL query requires a GROUP BY for the elements in the SELECT clause +		* @var	string	sort_by_sql				The possible predefined sort types +		* @var	string	sort_key				The sort type used from the possible sort types +		* @var	string	sort_dir				"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort				The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	int		start					How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'search_query', +			'must_not_contain_ids', +			'must_exclude_one_ids', +			'must_contain_ids', +			'total_results', +			'sql_array', +			'left_join_topics', +			'author_ary', +			'author_name', +			'ex_fid_ary', +			'topic_id', +			'sql_sort_table', +			'sql_sort_join', +			'sort_days', +			'sql_where', +			'sql_match', +			'sql_match_where', +			'group_by', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_native_keywords_count_query_before', compact($vars))); +  		if ($topic_id)  		{  			$sql_where[] = 'p.topic_id = ' . $topic_id; @@ -823,6 +895,13 @@ class fulltext_native extends \phpbb\search\base  			);  		} +		// if using mysql and the total result count is not calculated yet, get it from the db +		if (!$total_results && $is_mysql) +		{ +			// Also count rows for the query as if there was not LIMIT. Add SQL_CALC_FOUND_ROWS to SQL +			$sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT']; +		} +  		$sql_array['WHERE'] = implode(' AND ', $sql_where);  		$sql_array['GROUP_BY'] = ($group_by) ? (($type == 'posts') ? 'p.post_id' : 'p.topic_id') . ', ' . $sort_by_sql[$sort_key] : '';  		$sql_array['ORDER_BY'] = $sql_sort; @@ -838,19 +917,9 @@ class fulltext_native extends \phpbb\search\base  		}  		$this->db->sql_freeresult($result); -		// if we use mysql and the total result count is not cached yet, retrieve it from the db  		if (!$total_results && $is_mysql)  		{ -			// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it -			$sql_array_copy = $sql_array; -			$sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id '; - -			$sql_calc = $this->db->sql_build_query('SELECT', $sql_array_copy); -			unset($sql_array_copy); - -			$this->db->sql_query($sql_calc); -			$this->db->sql_freeresult($result); - +			// Get the number of results as calculated by MySQL  			$sql_count = 'SELECT FOUND_ROWS() as total_results';  			$result = $this->db->sql_query($sql_count);  			$total_results = (int) $this->db->sql_fetchfield('total_results'); @@ -975,6 +1044,49 @@ class fulltext_native extends \phpbb\search\base  		$select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';  		$is_mysql = false; +		/** +		* Allow changing the query used to search for posts by author in fulltext_native +		* +		* @event core.search_native_author_count_query_before +		* @var	int		total_results		The previous result count for the format of the query. +		*									Set to 0 to force a re-count +		* @var	string	select				SQL SELECT clause for what to get +		* @var	string	sql_sort_table		CROSS JOIN'ed table to allow doing the sort chosen +		* @var	string	sql_sort_join		Condition to define how to join the CROSS JOIN'ed table specifyed in sql_sort_table +		* @var	array	sql_author			SQL WHERE condition for the post author ids +		* @var	int		topic_id			Limit the search to this topic_id only +		* @var	string	sort_by_sql			The possible predefined sort types +		* @var	string	sort_key			The sort type used from the possible sort types +		* @var	string	sort_dir			"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort			The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	string	sort_days			Time, in days, that the oldest post showing can have +		* @var	string	sql_time			The SQL to search on the time specifyed by sort_days +		* @var	bool	firstpost_only		Wether or not to search only on the first post of the topics +		* @var	array	ex_fid_ary			Forum ids that must not be searched on +		* @var	array	sql_fora			SQL query for ex_fid_ary +		* @var	int		start				How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'total_results', +			'select', +			'sql_sort_table', +			'sql_sort_join', +			'sql_author', +			'topic_id', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'sort_days', +			'sql_time', +			'firstpost_only', +			'ex_fid_ary', +			'sql_fora', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_native_author_count_query_before', compact($vars))); +  		// If the cache was completely empty count the results  		if (!$total_results)  		{ @@ -1078,7 +1190,7 @@ class fulltext_native extends \phpbb\search\base  			// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.  			$sql_calc = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql); -			$this->db->sql_query($sql_calc); +			$result = $this->db->sql_query($sql_calc);  			$this->db->sql_freeresult($result);  			$sql_count = 'SELECT FOUND_ROWS() as total_results'; diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php index b6af371d13..d17b26be8f 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/fulltext_postgres.php @@ -56,6 +56,12 @@ class fulltext_postgres extends \phpbb\search\base  	protected $db;  	/** +	 * phpBB event dispatcher object +	 * @var \phpbb\event\dispatcher_interface +	 */ +	protected $phpbb_dispatcher; + +	/**  	 * User object  	 * @var \phpbb\user  	 */ @@ -92,11 +98,13 @@ class fulltext_postgres extends \phpbb\search\base  	 * @param \phpbb\config\config $config Config object  	 * @param \phpbb\db\driver\driver_interface Database object  	 * @param \phpbb\user $user User object +	 * @param \phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	 */ -	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user) +	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher)  	{  		$this->config = $config;  		$this->db = $db; +		$this->phpbb_dispatcher = $phpbb_dispatcher;  		$this->user = $user;  		$this->word_length = array('min' => $this->config['fulltext_postgres_min_word_len'], 'max' => $this->config['fulltext_postgres_max_word_len']); @@ -409,6 +417,55 @@ class fulltext_postgres extends \phpbb\search\base  			break;  		} +		$tsearch_query = $this->tsearch_query; + +		/** +		* Allow changing the query used to search for posts using fulltext_postgres +		* +		* @event core.search_postgres_keywords_main_query_before +		* @var	string	tsearch_query		The parsed keywords used for this search +		* @var	int		result_count		The previous result count for the format of the query. +		*									Set to 0 to force a re-count +		* @var	bool	join_topic			Weather or not TOPICS_TABLE should be CROSS JOIN'ED +		* @var	array	author_ary			Array of user_id containing the users to filter the results to +		* @var	string	author_name			An extra username to search on (!empty(author_ary) must be true, to be relevant) +		* @var	array	ex_fid_ary			Which forums not to search on +		* @var	int		topic_id			Limit the search to this topic_id only +		* @var	string	sql_sort_table		Extra tables to include in the SQL query. +		*									Used in conjunction with sql_sort_join +		* @var	string	sql_sort_join		SQL conditions to join all the tables used together. +		*									Used in conjunction with sql_sort_table +		* @var	int		sort_days			Time, in days, of the oldest possible post to list +		* @var	string	sql_match			Which columns to do the search on. +		* @var	string	sql_match_where		Extra conditions to use to properly filter the matching process +		* @var	string	sort_by_sql			The possible predefined sort types +		* @var	string	sort_key			The sort type used from the possible sort types +		* @var	string	sort_dir			"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort			The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	int		start				How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'tsearch_query', +			'result_count', +			'join_topic', +			'author_ary', +			'author_name', +			'ex_fid_ary', +			'topic_id', +			'sql_sort_table', +			'sql_sort_join', +			'sort_days', +			'sql_match', +			'sql_match_where', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_keywords_main_query_before', compact($vars))); +  		$sql_select			= ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';  		$sql_from			= ($join_topic) ? TOPICS_TABLE . ' t, ' : '';  		$field				= ($type == 'posts') ? 'post_id' : 'topic_id'; @@ -595,6 +652,55 @@ class fulltext_postgres extends \phpbb\search\base  		$m_approve_fid_sql = ' AND ' . $post_visibility; +		/** +		* Allow changing the query used to search for posts by author in fulltext_postgres +		* +		* @event core.search_postgres_author_count_query_before +		* @var	int		result_count		The previous result count for the format of the query. +		*									Set to 0 to force a re-count +		* @var	string	sql_sort_table		CROSS JOIN'ed table to allow doing the sort chosen +		* @var	string	sql_sort_join		Condition to define how to join the CROSS JOIN'ed table specifyed in sql_sort_table +		* @var	array	author_ary			Array of user_id containing the users to filter the results to +		* @var	string	author_name			An extra username to search on +		* @var	string	sql_author			SQL WHERE condition for the post author ids +		* @var	int		topic_id			Limit the search to this topic_id only +		* @var	string	sql_topic_id		SQL of topic_id +		* @var	string	sort_by_sql			The possible predefined sort types +		* @var	string	sort_key			The sort type used from the possible sort types +		* @var	string	sort_dir			"a" for ASC or "d" dor DESC for the sort order used +		* @var	string	sql_sort			The result SQL when processing sort_by_sql + sort_key + sort_dir +		* @var	string	sort_days			Time, in days, that the oldest post showing can have +		* @var	string	sql_time			The SQL to search on the time specifyed by sort_days +		* @var	bool	firstpost_only		Wether or not to search only on the first post of the topics +		* @var	array	ex_fid_ary			Forum ids that must not be searched on +		* @var	array	sql_fora			SQL query for ex_fid_ary +		* @var	string	m_approve_fid_sql	WHERE clause condition on post_visibility restrictions +		* @var	int		start				How many posts to skip in the search results (used for pagination) +		* @since 3.1.5-RC1 +		*/ +		$vars = array( +			'result_count', +			'sql_sort_table', +			'sql_sort_join', +			'author_ary', +			'author_name', +			'sql_author', +			'topic_id', +			'sql_topic_id', +			'sort_by_sql', +			'sort_key', +			'sort_dir', +			'sql_sort', +			'sort_days', +			'sql_time', +			'firstpost_only', +			'ex_fid_ary', +			'sql_fora', +			'm_approve_fid_sql', +			'start', +		); +		extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_author_count_query_before', compact($vars))); +  		// Build the query for really selecting the post_ids  		if ($type == 'posts')  		{ diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index eb53ca6d40..cd7add72f0 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -96,6 +96,12 @@ class fulltext_sphinx  	protected $dbtype;  	/** +	 * phpBB event dispatcher object +	 * @var \phpbb\event\dispatcher_interface +	 */ +	protected $phpbb_dispatcher; + +	/**  	 * User object  	 * @var \phpbb\user  	 */ @@ -125,12 +131,14 @@ class fulltext_sphinx  	 * @param \phpbb\config\config $config Config object  	 * @param \phpbb\db\driver\driver_interface Database object  	 * @param \phpbb\user $user User object +	 * @param \phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	 */ -	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user) +	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher)  	{  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $phpEx;  		$this->config = $config; +		$this->phpbb_dispatcher = $phpbb_dispatcher;  		$this->user = $user;  		$this->db = $db;  		$this->auth = $auth; @@ -138,7 +146,7 @@ class fulltext_sphinx  		// Initialize \phpbb\db\tools object  		$this->db_tools = new \phpbb\db\tools($this->db); -		if(!$this->config['fulltext_sphinx_id']) +		if (!$this->config['fulltext_sphinx_id'])  		{  			set_config('fulltext_sphinx_id', unique_id());  		} diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 0a6a18ffbe..a5c8f264e0 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -130,6 +130,10 @@ class session  		$script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';  		$root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/'; +		$forum_id = $request->variable('f', 0); +		// maximum forum id value is maximum value of mediumint unsigned column +		$forum_id = ($forum_id > 0 && $forum_id < 16777215) ? $forum_id : 0; +  		$page_array += array(  			'page_name'			=> $page_name,  			'page_dir'			=> $page_dir, @@ -139,7 +143,7 @@ class session  			'root_script_path'	=> str_replace(' ', '%20', htmlspecialchars($root_script_path)),  			'page'				=> $page, -			'forum'				=> request_var('f', 0), +			'forum'				=> $forum_id,  		);  		return $page_array; @@ -515,7 +519,7 @@ class session  	*/  	function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)  	{ -		global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx, $phpbb_container; +		global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;  		$this->data = array(); @@ -889,6 +893,19 @@ class session  			$_SID = '';  		} +		$session_data = $sql_ary; +		/** +		* Event to send new session data to extension +		* Read-only event +		* +		* @event core.session_create_after +		* @var	array		session_data				Associative array of session keys to be updated +		* @since 3.1.6-RC1 +		*/ +		$vars = array('session_data'); +		extract($phpbb_dispatcher->trigger_event('core.session_create_after', compact($vars))); +		unset($session_data); +  		return true;  	} @@ -902,13 +919,30 @@ class session  	*/  	function session_kill($new_session = true)  	{ -		global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx, $phpbb_container; +		global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;  		$sql = 'DELETE FROM ' . SESSIONS_TABLE . "  			WHERE session_id = '" . $db->sql_escape($this->session_id) . "'  				AND session_user_id = " . (int) $this->data['user_id'];  		$db->sql_query($sql); +		$user_id = (int) $this->data['user_id']; +		$session_id = $this->session_id; +		/** +		* Event to send session kill information to extension +		* Read-only event +		* +		* @event core.session_kill_after +		* @var	int		user_id				user_id of the session user. +		* @var	string		session_id				current user's session_id +		* @var	bool	new_session 	should we create new session for user +		* @since 3.1.6-RC1 +		*/ +		$vars = array('user_id', 'session_id', 'new_session'); +		extract($phpbb_dispatcher->trigger_event('core.session_kill_after', compact($vars))); +		unset($user_id); +		unset($session_id); +  		// Allow connecting logout with external auth method logout  		$provider_collection = $phpbb_container->get('auth.provider_collection');  		$provider = $provider_collection->get_provider(); @@ -976,7 +1010,7 @@ class session  	*/  	function session_gc()  	{ -		global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container; +		global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;  		$batch_size = 10; @@ -1044,6 +1078,14 @@ class session  			$db->sql_query($sql);  		} +		/** +		* Event to trigger extension on session_gc +		* +		* @event core.session_gc_after +		* @since 3.1.6-RC1 +		*/ +		$phpbb_dispatcher->dispatch('core.session_gc_after'); +  		return;  	} @@ -1537,12 +1579,24 @@ class session  	*/  	public function update_session($session_data, $session_id = null)  	{ -		global $db; +		global $db, $phpbb_dispatcher;  		$session_id = ($session_id) ? $session_id : $this->session_id;  		$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $session_data) . "  			WHERE session_id = '" . $db->sql_escape($session_id) . "'";  		$db->sql_query($sql); + +		/** +		* Event to send update session information to extension +		* Read-only event +		* +		* @event core.update_session_after +		* @var	array		session_data				Associative array of session keys to be updated +		* @var	string		session_id				current user's session_id +		* @since 3.1.6-RC1 +		*/ +		$vars = array('session_data', 'session_id'); +		extract($phpbb_dispatcher->trigger_event('core.update_session_after', compact($vars)));  	}  } diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php index 2f8ffaa776..139a413b70 100644 --- a/phpBB/phpbb/template/twig/loader.php +++ b/phpBB/phpbb/template/twig/loader.php @@ -97,7 +97,8 @@ class loader extends \Twig_Loader_Filesystem  		// If this is in the cache we can skip the entire process below  		//	as it should have already been validated -		if (isset($this->cache[$name])) { +		if (isset($this->cache[$name])) +		{  			return $this->cache[$name];  		} diff --git a/phpBB/phpbb/template/twig/node/definenode.php b/phpBB/phpbb/template/twig/node/definenode.php index 695ec4281f..ddbd151d20 100644 --- a/phpBB/phpbb/template/twig/node/definenode.php +++ b/phpBB/phpbb/template/twig/node/definenode.php @@ -14,7 +14,6 @@  namespace phpbb\template\twig\node; -  class definenode extends \Twig_Node  {  	public function __construct($capture, \Twig_NodeInterface $name, \Twig_NodeInterface $value, $lineno, $tag = null) @@ -31,7 +30,8 @@ class definenode extends \Twig_Node  	{  		$compiler->addDebugInfo($this); -		if ($this->getAttribute('capture')) { +		if ($this->getAttribute('capture')) +		{  			$compiler  				->write("ob_start();\n")  				->subcompile($this->getNode('value')) diff --git a/phpBB/phpbb/template/twig/node/event.php b/phpBB/phpbb/template/twig/node/event.php index 8fc4ba4775..b765bde98d 100644 --- a/phpBB/phpbb/template/twig/node/event.php +++ b/phpBB/phpbb/template/twig/node/event.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\node; -  class event extends \Twig_Node  {  	/** diff --git a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php index 8c7f7b378d..2cd15d59da 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\node\expression\binary; -  class equalequal extends \Twig_Node_Expression_Binary  {  	public function operator(\Twig_Compiler $compiler) diff --git a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php index 2e95c68090..5f2908fb9b 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\node\expression\binary; -  class notequalequal extends \Twig_Node_Expression_Binary  {  	public function operator(\Twig_Compiler $compiler) diff --git a/phpBB/phpbb/template/twig/node/includecss.php b/phpBB/phpbb/template/twig/node/includecss.php index 2ce63402aa..2dac154036 100644 --- a/phpBB/phpbb/template/twig/node/includecss.php +++ b/phpBB/phpbb/template/twig/node/includecss.php @@ -31,7 +31,7 @@ class includecss extends \phpbb\template\twig\node\includeasset  		$compiler  			->raw("<link href=\"' . ")  			->raw("\$asset_file . '\"") -			->raw(' rel="stylesheet" type="text/css" media="screen, projection" />') +			->raw(' rel="stylesheet" type="text/css" media="screen" />')  		;  	}  } diff --git a/phpBB/phpbb/template/twig/node/includenode.php b/phpBB/phpbb/template/twig/node/includenode.php index 42428b6106..c36ac3c324 100644 --- a/phpBB/phpbb/template/twig/node/includenode.php +++ b/phpBB/phpbb/template/twig/node/includenode.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\node; -  class includenode extends \Twig_Node_Include  {  	/** diff --git a/phpBB/phpbb/template/twig/node/includephp.php b/phpBB/phpbb/template/twig/node/includephp.php index 826617e8e8..76182c2f84 100644 --- a/phpBB/phpbb/template/twig/node/includephp.php +++ b/phpBB/phpbb/template/twig/node/includephp.php @@ -14,7 +14,6 @@  namespace phpbb\template\twig\node; -  class includephp extends \Twig_Node  {  	/** @var \Twig_Environment */ @@ -47,7 +46,8 @@ class includephp extends \Twig_Node  			return;  		} -		if ($this->getAttribute('ignore_missing')) { +		if ($this->getAttribute('ignore_missing')) +		{  			$compiler  				->write("try {\n")  				->indent() @@ -76,7 +76,8 @@ class includephp extends \Twig_Node  			->write("}\n")  		; -		if ($this->getAttribute('ignore_missing')) { +		if ($this->getAttribute('ignore_missing')) +		{  			$compiler  				->outdent()  				->write("} catch (\Twig_Error_Loader \$e) {\n") diff --git a/phpBB/phpbb/template/twig/node/php.php b/phpBB/phpbb/template/twig/node/php.php index 3a24513dca..4ee415e446 100644 --- a/phpBB/phpbb/template/twig/node/php.php +++ b/phpBB/phpbb/template/twig/node/php.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\node; -  class php extends \Twig_Node  {  	/** @var \Twig_Environment */ diff --git a/phpBB/phpbb/template/twig/tokenparser/defineparser.php b/phpBB/phpbb/template/twig/tokenparser/defineparser.php index cfee84a363..b755836ccd 100644 --- a/phpBB/phpbb/template/twig/tokenparser/defineparser.php +++ b/phpBB/phpbb/template/twig/tokenparser/defineparser.php @@ -14,7 +14,6 @@  namespace phpbb\template\twig\tokenparser; -  class defineparser extends \Twig_TokenParser  {  	/** @@ -33,7 +32,8 @@ class defineparser extends \Twig_TokenParser  		$name = $this->parser->getExpressionParser()->parseExpression();  		$capture = false; -		if ($stream->test(\Twig_Token::OPERATOR_TYPE, '=')) { +		if ($stream->test(\Twig_Token::OPERATOR_TYPE, '=')) +		{  			$stream->next();  			$value = $this->parser->getExpressionParser()->parseExpression(); @@ -45,7 +45,9 @@ class defineparser extends \Twig_TokenParser  			}  			$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		} else { +		} +		else +		{  			$capture = true;  			$stream->expect(\Twig_Token::BLOCK_END_TYPE); diff --git a/phpBB/phpbb/template/twig/tokenparser/event.php b/phpBB/phpbb/template/twig/tokenparser/event.php index 4c7c8e07d9..f73ef4ae25 100644 --- a/phpBB/phpbb/template/twig/tokenparser/event.php +++ b/phpBB/phpbb/template/twig/tokenparser/event.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\tokenparser; -  class event extends \Twig_TokenParser  {  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includejs.php b/phpBB/phpbb/template/twig/tokenparser/includejs.php index 4156048e42..4b67d2c468 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includejs.php +++ b/phpBB/phpbb/template/twig/tokenparser/includejs.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\tokenparser; -  class includejs extends \Twig_TokenParser  {  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includeparser.php b/phpBB/phpbb/template/twig/tokenparser/includeparser.php index 6ee78e5562..aa7236aaa6 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includeparser.php +++ b/phpBB/phpbb/template/twig/tokenparser/includeparser.php @@ -14,7 +14,6 @@  namespace phpbb\template\twig\tokenparser; -  class includeparser extends \Twig_TokenParser_Include  {  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includephp.php b/phpBB/phpbb/template/twig/tokenparser/includephp.php index 38196c5290..3992636f8c 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includephp.php +++ b/phpBB/phpbb/template/twig/tokenparser/includephp.php @@ -14,7 +14,6 @@  namespace phpbb\template\twig\tokenparser; -  class includephp extends \Twig_TokenParser  {  	/** @@ -31,7 +30,8 @@ class includephp extends \Twig_TokenParser  		$stream = $this->parser->getStream();  		$ignoreMissing = false; -		if ($stream->test(\Twig_Token::NAME_TYPE, 'ignore')) { +		if ($stream->test(\Twig_Token::NAME_TYPE, 'ignore')) +		{  			$stream->next();  			$stream->expect(\Twig_Token::NAME_TYPE, 'missing'); diff --git a/phpBB/phpbb/template/twig/tokenparser/php.php b/phpBB/phpbb/template/twig/tokenparser/php.php index 557a70cca1..f11ce35896 100644 --- a/phpBB/phpbb/template/twig/tokenparser/php.php +++ b/phpBB/phpbb/template/twig/tokenparser/php.php @@ -13,7 +13,6 @@  namespace phpbb\template\twig\tokenparser; -  class php extends \Twig_TokenParser  {  	/** diff --git a/phpBB/phpbb/tree/nestedset.php b/phpBB/phpbb/tree/nestedset.php index 57d109652e..8490c7c299 100644 --- a/phpBB/phpbb/tree/nestedset.php +++ b/phpBB/phpbb/tree/nestedset.php @@ -837,7 +837,10 @@ abstract class nestedset implements \phpbb\tree\tree_interface  				' . $this->get_sql_where('AND') . '  			ORDER BY ' . $this->column_left_id . ', ' . $this->column_item_id . ' ASC';  		$result = $this->db->sql_query($sql); -		while ($row = $this->db->sql_fetchrow($result)) +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); + +		foreach ($rows as $row)  		{  			// First we update the left_id for this module  			if ($row[$this->column_left_id] != $new_id) @@ -862,7 +865,6 @@ abstract class nestedset implements \phpbb\tree\tree_interface  			}  			$new_id++;  		} -		$this->db->sql_freeresult($result);  		if ($acquired_new_lock)  		{ diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index 882e9cef26..3bc1af2899 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -637,7 +637,7 @@ class user extends \phpbb\session  				$lang_path = $this->lang_path;  			} -			if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0) +			if (strpos($phpbb_root_path . $filename, $lang_path) === 0)  			{  				$language_filename = $phpbb_root_path . $filename;  			} diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php index 24e663b150..5ce8ca2d4d 100644 --- a/phpBB/phpbb/user_loader.php +++ b/phpBB/phpbb/user_loader.php @@ -179,9 +179,10 @@ class user_loader  	* @param bool $query Should we query the database if this user has not yet been loaded?  	* 						Typically this should be left as false and you should make sure  	* 						you load users ahead of time with load_users() +	* @param bool @lazy If true, will be lazy loaded (requires JS)  	* @return string  	*/ -	public function get_avatar($user_id, $query = false) +	public function get_avatar($user_id, $query = false, $lazy = false)  	{  		if (!($user = $this->get_user($user_id, $query)))  		{ @@ -193,7 +194,7 @@ class user_loader  			include($this->phpbb_root_path . 'includes/functions_display.' . $this->php_ext);  		} -		return get_user_avatar($user['user_avatar'], $user['user_avatar_type'], $user['user_avatar_width'], $user['user_avatar_height']); +		return get_user_avatar($user['user_avatar'], $user['user_avatar_type'], $user['user_avatar_width'], $user['user_avatar_height'], 'USER_AVATAR', false, $lazy);  	}  	/** | 
