diff options
Diffstat (limited to 'phpBB/phpbb')
363 files changed, 17877 insertions, 3713 deletions
diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php index 279959974d..81676e75fc 100644 --- a/phpBB/phpbb/auth/auth.php +++ b/phpBB/phpbb/auth/auth.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\auth; /** * Permission/Auth class * @package phpBB3 */ -class phpbb_auth +class auth { var $acl = array(); var $cache = array(); @@ -970,6 +964,18 @@ class phpbb_auth ); } + // If the auth provider wants us to link an empty account do so and redirect + if ($login['status'] == LOGIN_SUCCESS_LINK_PROFILE) + { + // If this status exists a fourth field is in the $login array called 'redirect_data' + // This data is passed along as GET data to the next page allow the account to be linked + + $params = array('mode' => 'login_link'); + $url = append_sid($phpbb_root_path . 'ucp.' . $phpEx, array_merge($params, $login['redirect_data'])); + + redirect($url); + } + // If login succeeded, we will log the user in... else we pass the login array through... if ($login['status'] == LOGIN_SUCCESS) { diff --git a/phpBB/phpbb/auth/provider/apache.php b/phpBB/phpbb/auth/provider/apache.php index 2e80436f78..6374f29d67 100644 --- a/phpBB/phpbb/auth/provider/apache.php +++ b/phpBB/phpbb/auth/provider/apache.php @@ -7,35 +7,38 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\auth\provider; /** * Apache authentication provider for phpBB3 * * @package auth */ -class phpbb_auth_provider_apache extends phpbb_auth_provider_base +class apache extends \phpbb\auth\provider\base { /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; + + /** * Apache Authentication Constructor * - * @param phpbb_db_driver $db - * @param phpbb_config $config - * @param phpbb_request $request - * @param phpbb_user $user + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\request\request $request + * @param \phpbb\user $user * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_request $request, phpbb_user $user, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->request = $request; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; @@ -47,7 +50,7 @@ class phpbb_auth_provider_apache extends phpbb_auth_provider_base */ public function init() { - if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'))) + if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'))) { return $this->user->lang['APACHE_SETUP_BEFORE_USE']; } @@ -78,7 +81,7 @@ class phpbb_auth_provider_apache extends phpbb_auth_provider_base ); } - if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) + if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) { return array( 'status' => LOGIN_ERROR_EXTERNAL_AUTH, @@ -149,7 +152,7 @@ class phpbb_auth_provider_apache extends phpbb_auth_provider_base */ public function autologin() { - if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) + if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) { return array(); } @@ -226,7 +229,7 @@ class phpbb_auth_provider_apache extends phpbb_auth_provider_base // generate user account data return array( 'username' => $username, - 'user_password' => phpbb_hash($password), + 'user_password' => $this->passwords_manager->hash($password), 'user_email' => '', 'group_id' => (int) $row['group_id'], 'user_type' => USER_NORMAL, @@ -241,7 +244,7 @@ class phpbb_auth_provider_apache extends phpbb_auth_provider_base public function validate_session($user) { // Check if PHP_AUTH_USER is set and handle this case - if ($this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) + if ($this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) { $php_auth_user = $this->request->server('PHP_AUTH_USER'); diff --git a/phpBB/phpbb/auth/provider/base.php b/phpBB/phpbb/auth/provider/base.php index 7eaf8bb2d3..78a3289356 100644 --- a/phpBB/phpbb/auth/provider/base.php +++ b/phpBB/phpbb/auth/provider/base.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\auth\provider; /** * Base authentication provider class that all other providers should implement * * @package auth */ -abstract class phpbb_auth_provider_base implements phpbb_auth_provider_interface +abstract class base implements \phpbb\auth\provider\provider_interface { /** * {@inheritdoc} @@ -57,6 +51,22 @@ abstract class phpbb_auth_provider_base implements phpbb_auth_provider_interface /** * {@inheritdoc} */ + public function get_login_data() + { + return; + } + + /** + * {@inheritdoc} + */ + public function get_auth_link_data() + { + return; + } + + /** + * {@inheritdoc} + */ public function logout($data, $new_session) { return; @@ -69,4 +79,28 @@ abstract class phpbb_auth_provider_base implements phpbb_auth_provider_interface { return; } + + /** + * {@inheritdoc} + */ + public function login_link_has_necessary_data($login_link_data) + { + return; + } + + /** + * {@inheritdoc} + */ + public function link_account(array $link_data) + { + return; + } + + /** + * {@inheritdoc} + */ + public function unlink_account(array $link_data) + { + return; + } } diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index 0934c56d9b..5adbf84d9f 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\auth\provider; /** * Database authentication provider for phpBB3 @@ -22,23 +16,31 @@ if (!defined('IN_PHPBB')) * * @package auth */ -class phpbb_auth_provider_db extends phpbb_auth_provider_base +class db extends \phpbb\auth\provider\base { + /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; /** * Database Authentication Constructor * - * @param phpbb_db_driver $db - * @param phpbb_config $config - * @param phpbb_request $request - * @param phpbb_user $user - * @param string $phpbb_root_path - * @param string $php_ext + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\request\request $request + * @param \phpbb\user $user + * @param string $phpbb_root_path + * @param string $php_ext */ - public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_request $request, phpbb_user $user, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->request = $request; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; @@ -149,7 +151,7 @@ class phpbb_auth_provider_db extends phpbb_auth_provider_base include ($this->phpbb_root_path . 'includes/captcha/captcha_factory.' . $this->php_ext); } - $captcha = phpbb_captcha_factory::get_instance($this->config['captcha_plugin']); + $captcha = \phpbb_captcha_factory::get_instance($this->config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); $vc_response = $captcha->validate($row); if ($vc_response) @@ -197,10 +199,10 @@ class phpbb_auth_provider_db extends phpbb_auth_provider_base // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding // plain md5 support left in for conversions from other systems. - if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) + if ((strlen($row['user_password']) == 34 && ($this->passwords_manager->check(md5($password_old_format), $row['user_password']) || $this->passwords_manager->check(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password']))) { - $hash = phpbb_hash($password_new_format); + $hash = $this->passwords_manager->hash($password_new_format); // Update the password in the users table to the new format and remove user_pass_convert flag $sql = 'UPDATE ' . USERS_TABLE . ' @@ -232,12 +234,12 @@ class phpbb_auth_provider_db extends phpbb_auth_provider_base } // Check password ... - if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password'])) + if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password'])) { // Check for old password hash... - if (strlen($row['user_password']) == 32) + if ($this->passwords_manager->convert_flag || strlen($row['user_password']) == 32) { - $hash = phpbb_hash($password); + $hash = $this->passwords_manager->hash($password); // Update the password in the users table to the new format $sql = 'UPDATE ' . USERS_TABLE . " diff --git a/phpBB/phpbb/auth/provider/interface.php b/phpBB/phpbb/auth/provider/interface.php deleted file mode 100644 index 47043bc107..0000000000 --- a/phpBB/phpbb/auth/provider/interface.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** -* -* @package auth -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * The interface authentication provider classes have to implement. - * - * @package auth - */ -interface phpbb_auth_provider_interface -{ - /** - * Checks whether the user is currently identified to the authentication - * provider. - * Called in acp_board while setting authentication plugins. - * Changing to an authentication provider will not be permitted in acp_board - * if there is an error. - * - * @return boolean|string False if the user is identified, otherwise an - * error message, or null if not implemented. - */ - public function init(); - - /** - * Performs login. - * - * @param string $username The name of the user being authenticated. - * @param string $password The password of the user. - * @return array An associative array of the format: - * array( - * 'status' => status constant - * 'error_msg' => string - * 'user_row' => array - * ) - */ - public function login($username, $password); - - /** - * Autologin function - * - * @return array|null containing the user row, empty if no auto login - * should take place, or null if not impletmented. - */ - public function autologin(); - - /** - * This function is used to output any required fields in the authentication - * admin panel. It also defines any required configuration table fields. - * - * @return array|null Returns null if not implemented or an array of the - * configuration fields of the provider. - */ - public function acp(); - - /** - * This function updates the template with variables related to the acp - * options with whatever configuraton values are passed to it as an array. - * It then returns the name of the acp file related to this authentication - * provider. - * @param array $new_config Contains the new configuration values that - * have been set in acp_board. - * @return array|null Returns null if not implemented or an array with - * the template file name and an array of the vars - * that the template needs that must conform to the - * following example: - * array( - * 'TEMPLATE_FILE' => string, - * 'TEMPLATE_VARS' => array(...), - * ) - */ - public function get_acp_template($new_config); - - /** - * Performs additional actions during logout. - * - * @param array $data An array corresponding to - * phpbb_session::data - * @param boolean $new_session True for a new session, false for no new - * session. - */ - public function logout($data, $new_session); - - /** - * The session validation function checks whether the user is still logged - * into phpBB. - * - * @param array $user - * @return boolean true if the given user is authenticated, false if the - * session should be closed, or null if not implemented. - */ - public function validate_session($user); -} diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index 0196529408..3d3f1990eb 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\auth\provider; /** * Database authentication provider for phpBB3 @@ -22,19 +16,28 @@ if (!defined('IN_PHPBB')) * * @package auth */ -class phpbb_auth_provider_ldap extends phpbb_auth_provider_base +class ldap extends \phpbb\auth\provider\base { /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; + + /** * LDAP Authentication Constructor * - * @param phpbb_db_driver $db - * @param phpbb_config $config - * @param phpbb_user $user + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\user $user */ - public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_user $user) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\user $user) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->user = $user; } @@ -95,7 +98,6 @@ class phpbb_auth_provider_ldap extends phpbb_auth_provider_base @ldap_close($ldap); - if (!is_array($result) || sizeof($result) < 2) { return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']); @@ -242,7 +244,7 @@ class phpbb_auth_provider_ldap extends phpbb_auth_provider_base // generate user account data $ldap_user_row = array( 'username' => $username, - 'user_password' => phpbb_hash($password), + 'user_password' => $this->passwords_manager->hash($password), 'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '', 'group_id' => (int) $row['group_id'], 'user_type' => USER_NORMAL, diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php new file mode 100644 index 0000000000..10d5cda5e3 --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -0,0 +1,621 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth; + +use OAuth\Common\Consumer\Credentials; +use OAuth\Common\Http\Uri\Uri; + +/** +* OAuth authentication provider for phpBB3 +* +* @package auth +*/ +class oauth extends \phpbb\auth\provider\base +{ + /** + * Database driver + * + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * phpBB config + * + * @var \phpbb\config\config + */ + protected $config; + + /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; + + /** + * phpBB request object + * + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * phpBB user + * + * @var \phpbb\user + */ + protected $user; + + /** + * OAuth token table + * + * @var string + */ + protected $auth_provider_oauth_token_storage_table; + + /** + * OAuth account association table + * + * @var string + */ + protected $auth_provider_oauth_token_account_assoc; + + /** + * All OAuth service providers + * + * @var \phpbb\di\service_collection Contains \phpbb\auth\provider\oauth\service_interface + */ + protected $service_providers; + + /** + * Users table + * + * @var string + */ + protected $users_table; + + /** + * Cached current uri object + * + * @var \OAuth\Common\Http\Uri\UriInterface|null + */ + protected $current_uri; + + /** + * phpBB root path + * + * @var string + */ + protected $phpbb_root_path; + + /** + * PHP extenstion + * + * @var string + */ + protected $php_ext; + + /** + * OAuth Authentication Constructor + * + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\request\request_interface $request + * @param \phpbb\user $user + * @param string $auth_provider_oauth_token_storage_table + * @param string $auth_provider_oauth_token_account_assoc + * @param \phpbb\di\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface + * @param string $users_table + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, $phpbb_root_path, $php_ext) + { + $this->db = $db; + $this->config = $config; + $this->passwords_manager = $passwords_manager; + $this->request = $request; + $this->user = $user; + $this->auth_provider_oauth_token_storage_table = $auth_provider_oauth_token_storage_table; + $this->auth_provider_oauth_token_account_assoc = $auth_provider_oauth_token_account_assoc; + $this->service_providers = $service_providers; + $this->users_table = $users_table; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * {@inheritdoc} + */ + public function init() + { + // This does not test whether or not the key and secret provided are valid. + foreach ($this->service_providers as $service_provider) + { + $credentials = $service_provider->get_service_credentials(); + + if (($credentials['key'] && !$credentials['secret']) || (!$credentials['key'] && $credentials['secret'])) + { + return $this->user->lang['AUTH_PROVIDER_OAUTH_ERROR_ELEMENT_MISSING']; + } + } + return false; + } + + /** + * {@inheritdoc} + */ + public function login($username, $password) + { + // Temporary workaround for only having one authentication provider available + if (!$this->request->is_set('oauth_service')) + { + $provider = new \phpbb\auth\provider\db($this->db, $this->config, $this->passwords_manager, $this->request, $this->user, $this->phpbb_root_path, $this->php_ext); + return $provider->login($username, $password); + } + + // Requst the name of the OAuth service + $service_name_original = $this->request->variable('oauth_service', '', false); + $service_name = 'auth.provider.oauth.service.' . strtolower($service_name_original); + if ($service_name_original === '' || !array_key_exists($service_name, $this->service_providers)) + { + return array( + 'status' => LOGIN_ERROR_EXTERNAL_AUTH, + 'error_msg' => 'LOGIN_ERROR_OAUTH_SERVICE_DOES_NOT_EXIST', + 'user_row' => array('user_id' => ANONYMOUS), + ); + } + + // Get the service credentials for the given service + $service_credentials = $this->service_providers[$service_name]->get_service_credentials(); + + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $query = 'mode=login&login=external&oauth_service=' . $service_name_original; + $service = $this->get_service($service_name_original, $storage, $service_credentials, $query, $this->service_providers[$service_name]->get_auth_scope()); + + if ($this->request->is_set('code', \phpbb\request\request_interface::GET)) + { + $this->service_providers[$service_name]->set_external_service_provider($service); + $unique_id = $this->service_providers[$service_name]->perform_auth_login(); + + // Check to see if this provider is already assosciated with an account + $data = array( + 'provider' => $service_name_original, + 'oauth_provider_id' => $unique_id + ); + $sql = 'SELECT user_id FROM ' . $this->auth_provider_oauth_token_account_assoc . ' + WHERE ' . $this->db->sql_build_array('SELECT', $data); + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row) + { + // The user does not yet exist, ask to link or create profile + return array( + 'status' => LOGIN_SUCCESS_LINK_PROFILE, + 'error_msg' => 'LOGIN_OAUTH_ACCOUNT_NOT_LINKED', + 'user_row' => array(), + 'redirect_data' => array( + 'auth_provider' => 'oauth', + 'login_link_oauth_service' => $service_name_original, + ), + ); + } + + // Retrieve the user's account + $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts + FROM ' . $this->users_table . ' + WHERE user_id = ' . (int) $row['user_id']; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row) + { + throw new Exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_ENTRY'); + } + + // Update token storage to store the user_id + $storage->set_user_id($row['user_id']); + + // The user is now authenticated and can be logged in + return array( + 'status' => LOGIN_SUCCESS, + 'error_msg' => false, + 'user_row' => $row, + ); + } + else + { + $url = $service->getAuthorizationUri(); + header('Location: ' . $url); + } + } + + /** + * Returns the cached current_uri object or creates and caches it if it is + * not already created. In each case the query string is updated based on + * the $query parameter. + * + * @param string $service_name The name of the service + * @param string $query The query string of the current_uri + * used in redirects + * @return \OAuth\Common\Http\Uri\UriInterface + */ + protected function get_current_uri($service_name, $query) + { + if ($this->current_uri) + { + $this->current_uri->setQuery($query); + return $this->current_uri; + } + + $uri_factory = new \OAuth\Common\Http\Uri\UriFactory(); + $current_uri = $uri_factory->createFromSuperGlobalArray($this->request->get_super_global(\phpbb\request\request_interface::SERVER)); + $current_uri->setQuery($query); + + $this->current_uri = $current_uri; + return $current_uri; + } + + /** + * Returns a new service object + * + * @param string $service_name The name of the service + * @param \phpbb\auth\provider\oauth\token_storage $storage + * @param array $service_credentials {@see \phpbb\auth\provider\oauth\oauth::get_service_credentials} + * @param string $query The query string of the + * current_uri used in redirection + * @param array $scope The scope of the request against + * the api. + * @return \OAuth\Common\Service\ServiceInterface + */ + protected function get_service($service_name, \phpbb\auth\provider\oauth\token_storage $storage, array $service_credentials, $query, array $scopes = array()) + { + $current_uri = $this->get_current_uri($service_name, $query); + + // Setup the credentials for the requests + $credentials = new Credentials( + $service_credentials['key'], + $service_credentials['secret'], + $current_uri->getAbsoluteUri() + ); + + $service_factory = new \OAuth\ServiceFactory(); + $service = $service_factory->createService($service_name, $credentials, $storage, $scopes); + + if (!$service) + { + throw new Exception('AUTH_PROVIDER_OAUTH_ERROR_SERVICE_NOT_CREATED'); + } + + return $service; + } + + /** + * {@inheritdoc} + */ + public function get_login_data() + { + $login_data = array( + 'TEMPLATE_FILE' => 'login_body_oauth.html', + 'BLOCK_VAR_NAME' => 'oauth', + 'BLOCK_VARS' => array(), + ); + + foreach ($this->service_providers as $service_name => $service_provider) + { + // Only include data if the credentials are set + $credentials = $service_provider->get_service_credentials(); + if ($credentials['key'] && $credentials['secret']) + { + $actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); + $redirect_url = build_url(false) . '&login=external&oauth_service=' . $actual_name; + $login_data['BLOCK_VARS'][$service_name] = array( + 'REDIRECT_URL' => redirect($redirect_url, true), + 'SERVICE_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], + ); + } + } + + return $login_data; + } + + /** + * {@inheritdoc} + */ + public function acp() + { + $ret = array(); + + foreach ($this->service_providers as $service_name => $service_provider) + { + $actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); + $ret[] = 'auth_oauth_' . $actual_name . '_key'; + $ret[] = 'auth_oauth_' . $actual_name . '_secret'; + } + + return $ret; + } + + /** + * {@inheritdoc} + */ + public function get_acp_template($new_config) + { + $ret = array( + 'BLOCK_VAR_NAME' => 'oauth_services', + 'BLOCK_VARS' => array(), + 'TEMPLATE_FILE' => 'auth_provider_oauth.html', + 'TEMPLATE_VARS' => array(), + ); + + foreach ($this->service_providers as $service_name => $service_provider) + { + $actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); + $ret['BLOCK_VARS'][$actual_name] = array( + 'ACTUAL_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], + 'KEY' => $new_config['auth_oauth_' . $actual_name . '_key'], + 'NAME' => $actual_name, + 'SECRET' => $new_config['auth_oauth_' . $actual_name . '_secret'], + ); + } + + return $ret; + } + + /** + * {@inheritdoc} + */ + public function login_link_has_necessary_data($login_link_data) + { + if (empty($login_link_data)) + { + return 'LOGIN_LINK_NO_DATA_PROVIDED'; + } + + if (!array_key_exists('oauth_service', $login_link_data) || !$login_link_data['oauth_service'] || + !array_key_exists('link_method', $login_link_data) || !$login_link_data['link_method']) + { + return 'LOGIN_LINK_MISSING_DATA'; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function link_account(array $link_data) + { + // Check for a valid link method (auth_link or login_link) + if (!array_key_exists('link_method', $link_data) || + !in_array($link_data['link_method'], array( + 'auth_link', + 'login_link', + ))) + { + return 'LOGIN_LINK_MISSING_DATA'; + } + + // We must have an oauth_service listed, check for it two ways + if (!array_key_exists('oauth_service', $link_data) || !$link_data['oauth_service']) + { + $link_data['oauth_service'] = $this->request->variable('oauth_service', ''); + + if (!$link_data['oauth_service']) + { + return 'LOGIN_LINK_MISSING_DATA'; + } + } + + $service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); + if (!array_key_exists($service_name, $this->service_providers)) + { + return 'LOGIN_ERROR_OAUTH_SERVICE_DOES_NOT_EXIST'; + } + + switch ($link_data['link_method']) + { + case 'auth_link': + return $this->link_account_auth_link($link_data, $service_name); + case 'login_link': + return $this->link_account_login_link($link_data, $service_name); + } + } + + /** + * Performs the account linking for login_link + * + * @param array $link_data The same variable given to {@see \phpbb\auth\provider\provider_interface::link_account} + * @param string $service_name The name of the service being used in + * linking. + * @return string|null Returns a language constant (string) if an error is + * encountered, or null on success. + */ + protected function link_account_login_link(array $link_data, $service_name) + { + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + + // Check for an access token, they should have one + if (!$storage->has_access_token_by_session($service_name)) + { + return 'LOGIN_LINK_ERROR_OAUTH_NO_ACCESS_TOKEN'; + } + + // Prepare the query string + $query = 'mode=login_link&login_link_oauth_service=' . strtolower($link_data['oauth_service']); + + // Prepare for an authentication request + $service_credentials = $this->service_providers[$service_name]->get_service_credentials(); + $scopes = $this->service_providers[$service_name]->get_auth_scope(); + $service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes); + $this->service_providers[$service_name]->set_external_service_provider($service); + + // The user has already authenticated successfully, request to authenticate again + $unique_id = $this->service_providers[$service_name]->perform_token_auth(); + + // Insert into table, they will be able to log in after this + $data = array( + 'user_id' => $link_data['user_id'], + 'provider' => strtolower($link_data['oauth_service']), + 'oauth_provider_id' => $unique_id, + ); + + $this->link_account_perform_link($data); + // Update token storage to store the user_id + $storage->set_user_id($link_data['user_id']); + } + + /** + * Performs the account linking for auth_link + * + * @param array $link_data The same variable given to {@see \phpbb\auth\provider\provider_interface::link_account} + * @param string $service_name The name of the service being used in + * linking. + * @return string|null Returns a language constant (string) if an error is + * encountered, or null on success. + */ + protected function link_account_auth_link(array $link_data, $service_name) + { + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $query = 'i=ucp_auth_link&mode=auth_link&link=1&oauth_service=' . strtolower($link_data['oauth_service']); + $service_credentials = $this->service_providers[$service_name]->get_service_credentials(); + $scopes = $this->service_providers[$service_name]->get_auth_scope(); + $service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes); + + if ($this->request->is_set('code', \phpbb\request\request_interface::GET)) + { + $this->service_providers[$service_name]->set_external_service_provider($service); + $unique_id = $this->service_providers[$service_name]->perform_auth_login(); + + // Insert into table, they will be able to log in after this + $data = array( + 'user_id' => $this->user->data['user_id'], + 'provider' => strtolower($link_data['oauth_service']), + 'oauth_provider_id' => $unique_id, + ); + + $this->link_account_perform_link($data); + } + else + { + $url = $service->getAuthorizationUri(); + header('Location: ' . $url); + } + } + + /** + * Performs the query that inserts an account link + * + * @param array $data This array is passed to db->sql_build_array + */ + protected function link_account_perform_link(array $data) + { + $sql = 'INSERT INTO ' . $this->auth_provider_oauth_token_account_assoc . ' + ' . $this->db->sql_build_array('INSERT', $data); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function logout($data, $new_session) + { + // Clear all tokens belonging to the user + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage->clearAllTokens(); + + return; + } + + /** + * {@inheritdoc} + */ + public function get_auth_link_data() + { + $block_vars = array(); + + // Get all external accounts tied to the current user + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + ); + $sql = 'SELECT oauth_provider_id, provider FROM ' . $this->auth_provider_oauth_token_account_assoc . ' + WHERE ' . $this->db->sql_build_array('SELECT', $data); + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $oauth_user_ids = array(); + + if ($rows !== false && sizeof($rows)) + { + foreach ($rows as $row) + { + $oauth_user_ids[$row['provider']] = $row['oauth_provider_id']; + } + } + unset($rows); + + foreach ($this->service_providers as $service_name => $service_provider) + { + // Only include data if the credentials are set + $credentials = $service_provider->get_service_credentials(); + if ($credentials['key'] && $credentials['secret']) + { + $actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); + + $block_vars[$service_name] = array( + 'HIDDEN_FIELDS' => array( + 'link' => (!isset($oauth_user_ids[$actual_name])), + 'oauth_service' => $actual_name, + ), + + 'SERVICE_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], + 'UNIQUE_ID' => (isset($oauth_user_ids[$actual_name])) ? $oauth_user_ids[$actual_name] : null, + ); + } + } + + return array( + 'BLOCK_VAR_NAME' => 'oauth', + 'BLOCK_VARS' => $block_vars, + + 'TEMPLATE_FILE' => 'ucp_auth_link_oauth.html', + ); + } + + /** + * {@inheritdoc} + */ + public function unlink_account(array $link_data) + { + if (!array_key_exists('oauth_service', $link_data) || !$link_data['oauth_service']) + { + return 'LOGIN_LINK_MISSING_DATA'; + } + + // 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']; + $this->db->sql_query($sql); + + // Clear all tokens belonging to the user on this servce + $service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage->clearToken($service_name); + + return; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/base.php b/phpBB/phpbb/auth/provider/oauth/service/base.php new file mode 100644 index 0000000000..7a144d2f51 --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/base.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* Base OAuth abstract class that all OAuth services should implement +* +* @package auth +*/ +abstract class base implements \phpbb\auth\provider\oauth\service\service_interface +{ + /** + * External OAuth service provider + * + * @var \OAuth\Common\Service\ServiceInterface + */ + protected $service_provider; + + /** + * {@inheritdoc} + */ + public function get_external_service_provider() + { + return $this->service_provider; + } + + /** + * {@inheritdoc} + */ + public function get_auth_scope() + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function set_external_service_provider(\OAuth\Common\Service\ServiceInterface $service_provider) + { + $this->service_provider = $service_provider; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/bitly.php b/phpBB/phpbb/auth/provider/oauth/service/bitly.php new file mode 100644 index 0000000000..b4050033a6 --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/bitly.php @@ -0,0 +1,92 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* Bitly OAuth service +* +* @package auth +*/ +class bitly extends \phpbb\auth\provider\oauth\service\base +{ + /** + * phpBB config + * + * @var \phpbb\config\config + */ + protected $config; + + /** + * phpBB request + * + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * Constructor + * + * @param \phpbb\config\config $config + * @param \phpbb\request\request_interface $request + */ + public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request) + { + $this->config = $config; + $this->request = $request; + } + + /** + * {@inheritdoc} + */ + public function get_service_credentials() + { + return array( + 'key' => $this->config['auth_oauth_bitly_key'], + 'secret' => $this->config['auth_oauth_bitly_secret'], + ); + } + + /** + * {@inheritdoc} + */ + public function perform_auth_login() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Bitly)) + { + throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // This was a callback request from bitly, get the token + $this->service_provider->requestAccessToken($this->request->variable('code', '')); + + // Send a request with it + $result = json_decode($this->service_provider->request('user/info'), true); + + // Return the unique identifier returned from bitly + return $result['data']['login']; + } + + /** + * {@inheritdoc} + */ + public function perform_token_auth() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Bitly)) + { + throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // Send a request with it + $result = json_decode($this->service_provider->request('user/info'), true); + + // Return the unique identifier returned from bitly + return $result['data']['login']; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/exception.php b/phpBB/phpbb/auth/provider/oauth/service/exception.php new file mode 100644 index 0000000000..3bc93be01e --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/exception.php @@ -0,0 +1,19 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* OAuth service exception class +* +* @package auth +*/ +class exception extends \RuntimeException +{ +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/facebook.php b/phpBB/phpbb/auth/provider/oauth/service/facebook.php new file mode 100644 index 0000000000..2698be8b18 --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/facebook.php @@ -0,0 +1,92 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* Facebook OAuth service +* +* @package auth +*/ +class facebook extends base +{ + /** + * phpBB config + * + * @var phpbb\config\config + */ + protected $config; + + /** + * phpBB request + * + * @var phpbb\request\request_interface + */ + protected $request; + + /** + * Constructor + * + * @param phpbb\config\config $config + * @param phpbb\request\request_interface $request + */ + public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request) + { + $this->config = $config; + $this->request = $request; + } + + /** + * {@inheritdoc} + */ + public function get_service_credentials() + { + return array( + 'key' => $this->config['auth_oauth_facebook_key'], + 'secret' => $this->config['auth_oauth_facebook_secret'], + ); + } + + /** + * {@inheritdoc} + */ + public function perform_auth_login() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Facebook)) + { + throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // This was a callback request, get the token + $this->service_provider->requestAccessToken($this->request->variable('code', '')); + + // Send a request with it + $result = json_decode($this->service_provider->request('/me'), true); + + // Return the unique identifier + return $result['id']; + } + + /** + * {@inheritdoc} + */ + public function perform_token_auth() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Facebook)) + { + throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // Send a request with it + $result = json_decode($this->service_provider->request('/me'), true); + + // Return the unique identifier + return $result['id']; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/google.php b/phpBB/phpbb/auth/provider/oauth/service/google.php new file mode 100644 index 0000000000..08cb025c2d --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/google.php @@ -0,0 +1,103 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* Google OAuth service +* +* @package auth +*/ +class google extends base +{ + /** + * phpBB config + * + * @var phpbb\config\config + */ + protected $config; + + /** + * phpBB request + * + * @var phpbb\request\request_interface + */ + protected $request; + + /** + * Constructor + * + * @param phpbb\config\config $config + * @param phpbb\request\request_interface $request + */ + public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request) + { + $this->config = $config; + $this->request = $request; + } + + /** + * {@inheritdoc} + */ + public function get_auth_scope() + { + return array( + 'userinfo_email', + 'userinfo_profile', + ); + } + + /** + * {@inheritdoc} + */ + public function get_service_credentials() + { + return array( + 'key' => $this->config['auth_oauth_google_key'], + 'secret' => $this->config['auth_oauth_google_secret'], + ); + } + + /** + * {@inheritdoc} + */ + public function perform_auth_login() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Google)) + { + throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // This was a callback request, get the token + $this->service_provider->requestAccessToken($this->request->variable('code', '')); + + // Send a request with it + $result = json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); + + // Return the unique identifier + return $result['id']; + } + + /** + * {@inheritdoc} + */ + public function perform_token_auth() + { + if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Google)) + { + throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // Send a request with it + $result = json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); + + // Return the unique identifier + return $result['id']; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/service/service_interface.php b/phpBB/phpbb/auth/provider/oauth/service/service_interface.php new file mode 100644 index 0000000000..eee3a51cac --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/service_interface.php @@ -0,0 +1,71 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* OAuth service interface +* +* @package auth +*/ +interface service_interface +{ + /** + * Returns an array of the scopes necessary for auth + * + * @return array An array of the required scopes + */ + public function get_auth_scope(); + + /** + * Returns the external library service provider once it has been set + * + * @param \OAuth\Common\Service\ServiceInterface|null + */ + public function get_external_service_provider(); + + /** + * Returns an array containing the service credentials belonging to requested + * service. + * + * @return array An array containing the 'key' and the 'secret' of the + * service in the form: + * array( + * 'key' => string + * 'secret' => string + * ) + */ + public function get_service_credentials(); + + /** + * Returns the results of the authentication in json format + * + * @throws \phpbb\auth\provider\oauth\service\exception + * @return string The unique identifier returned by the service provider + * that is used to authenticate the user with phpBB. + */ + public function perform_auth_login(); + + /** + * Returns the results of the authentication in json format + * Use this function when the user already has an access token + * + * @throws \phpbb\auth\provider\oauth\service\exception + * @return string The unique identifier returned by the service provider + * that is used to authenticate the user with phpBB. + */ + public function perform_token_auth(); + + /** + * Sets the external library service provider + * + * @param \OAuth\Common\Service\ServiceInterface $service + */ + public function set_external_service_provider(\OAuth\Common\Service\ServiceInterface $service_provider); +} diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php new file mode 100644 index 0000000000..d32a03be0a --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php @@ -0,0 +1,360 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider\oauth; + + +use OAuth\OAuth1\Token\StdOAuth1Token; +use OAuth\Common\Token\TokenInterface; +use OAuth\Common\Storage\TokenStorageInterface; +use OAuth\Common\Storage\Exception\StorageException; +use OAuth\Common\Storage\Exception\TokenNotFoundException; + +/** +* OAuth storage wrapper for phpbb's cache +* +* @package auth +*/ +class token_storage implements TokenStorageInterface +{ + /** + * Cache driver. + * + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * phpBB user + * + * @var \phpbb\user + */ + protected $user; + + /** + * OAuth token table + * + * @var string + */ + protected $auth_provider_oauth_table; + + /** + * @var object|TokenInterface + */ + protected $cachedToken; + + /** + * Creates token storage for phpBB. + * + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\user $user + * @param string $auth_provider_oauth_table + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $auth_provider_oauth_table) + { + $this->db = $db; + $this->user = $user; + $this->auth_provider_oauth_table = $auth_provider_oauth_table; + } + + /** + * {@inheritdoc} + */ + public function retrieveAccessToken($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedToken instanceof TokenInterface) + { + return $this->cachedToken; + } + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + ); + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $data['session_id'] = $this->user->data['session_id']; + } + + return $this->_retrieve_access_token($data); + } + + /** + * {@inheritdoc} + */ + public function storeAccessToken($service, TokenInterface $token) + { + $service = $this->get_service_name_for_db($service); + + $this->cachedToken = $token; + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + 'oauth_token' => $this->json_encode_token($token), + 'session_id' => $this->user->data['session_id'], + ); + + $sql = 'INSERT INTO ' . $this->auth_provider_oauth_table . ' + ' . $this->db->sql_build_array('INSERT', $data); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function hasAccessToken($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedToken) { + return true; + } + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + ); + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $data['session_id'] = $this->user->data['session_id']; + } + + return $this->_has_acess_token($data); + } + + /** + * {@inheritdoc} + */ + public function clearToken($service) + { + $service = $this->get_service_name_for_db($service); + + $this->cachedToken = null; + + $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . ' + WHERE user_id = ' . (int) $this->user->data['user_id'] . " + AND provider = '" . $this->db->sql_escape($service) . "'"; + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; + } + + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function clearAllTokens() + { + $this->cachedToken = null; + + $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . ' + WHERE user_id = ' . (int) $this->user->data['user_id']; + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; + } + + $this->db->sql_query($sql); + } + + /** + * Updates the user_id field in the database assosciated with the token + * + * @param int $user_id + */ + public function set_user_id($user_id) + { + if (!$this->cachedToken) + { + return; + } + + $sql = 'UPDATE ' . $this->auth_provider_oauth_table . ' + SET ' . $this->db->sql_build_array('UPDATE', array( + 'user_id' => (int) $user_id + )) . ' + WHERE user_id = ' . (int) $this->user->data['user_id'] . " + AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; + $this->db->sql_query($sql); + } + + /** + * Checks to see if an access token exists solely by the session_id of the user + * + * @return bool true if they have token, false if they don't + */ + public function has_access_token_by_session($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedToken) + { + return true; + } + + $data = array( + 'session_id' => $this->user->data['session_id'], + 'provider' => $service, + ); + + return $this->_has_acess_token($data); + } + + /** + * A helper function that performs the query for has access token functions + * + * @param array $data + * @return bool + */ + protected function _has_acess_token($data) + { + return (bool) $this->get_access_token_row($data); + } + + public function retrieve_access_token_by_session($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedToken instanceof TokenInterface) { + return $this->cachedToken; + } + + $data = array( + 'session_id' => $this->user->data['session_id'], + 'provider' => $service, + ); + + return $this->_retrieve_access_token($data); + } + + /** + * A helper function that performs the query for retrieve access token functions + * Also checks if the token is a valid token + * + * @param array $data + * @return mixed + */ + protected function _retrieve_access_token($data) + { + $row = $this->get_access_token_row($data); + + if (!$row) + { + throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_NOT_STORED'); + } + + $token = $this->json_decode_token($row['oauth_token']); + + // Ensure that the token was serialized/unserialized correctly + if (!($token instanceof TokenInterface)) + { + $this->clearToken(); + throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED'); + } + + $this->cachedToken = $token; + return $token; + } + + /** + * A helper function that performs the query for retrieving an access token + * + * @param array $data + * @return mixed + */ + protected function get_access_token_row($data) + { + $sql = 'SELECT oauth_token FROM ' . $this->auth_provider_oauth_table . ' + WHERE ' . $this->db->sql_build_array('SELECT', $data); + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + return $row; + } + + public function json_encode_token(TokenInterface $token) + { + $members = array( + 'accessToken' => $token->getAccessToken(), + 'endOfLife' => $token->getEndOfLife(), + 'extraParams' => $token->getExtraParams(), + 'refreshToken' => $token->getRefreshToken(), + + 'token_class' => get_class($token), + ); + + // Handle additional data needed for OAuth1 tokens + if ($token instanceof StdOAuth1Token) + { + $members['requestToken'] = $token->getRequestToken(); + $members['requestTokenSecret'] = $token->getRequestTokenSecret(); + $members['accessTokenSecret'] = $token->getAccessTokenSecret(); + } + + return json_encode($members); + } + + public function json_decode_token($json) + { + $token_data = json_decode($json, true); + + if ($token_data === null) + { + throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED'); + } + + $token_class = $token_data['token_class']; + $access_token = $token_data['accessToken']; + $refresh_token = $token_data['refreshToken']; + $endOfLife = $token_data['endOfLife']; + $extra_params = $token_data['extraParams']; + + // Create the token + $token = new $token_class($access_token, $refresh_token, TokenInterface::EOL_NEVER_EXPIRES, $extra_params); + $token->setEndOfLife($endOfLife); + + // Handle OAuth 1.0 specific elements + if ($token instanceof StdOAuth1Token) + { + $token->setRequestToken($token_data['requestToken']); + $token->setRequestTokenSecret($token_data['requestTokenSecret']); + $token->setAccessTokenSecret($token_data['accessTokenSecret']); + } + + return $token; + } + + /** + * Returns the name of the service as it must be stored in the database. + * + * @param string $service The name of the OAuth service + * @return string The name of the OAuth service as it needs to be stored + * in the database. + */ + protected function get_service_name_for_db($service) + { + // Enforce the naming convention for oauth services + if (strpos($service, 'auth.provider.oauth.service.') !== 0) + { + $service = 'auth.provider.oauth.service.' . strtolower($service); + } + + return $service; + } +} diff --git a/phpBB/phpbb/auth/provider/provider_interface.php b/phpBB/phpbb/auth/provider/provider_interface.php new file mode 100644 index 0000000000..946731f52d --- /dev/null +++ b/phpBB/phpbb/auth/provider/provider_interface.php @@ -0,0 +1,191 @@ +<?php +/** +* +* @package auth +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\auth\provider; + +/** + * The interface authentication provider classes have to implement. + * + * @package auth + */ +interface provider_interface +{ + /** + * Checks whether the user is currently identified to the authentication + * provider. + * Called in acp_board while setting authentication plugins. + * Changing to an authentication provider will not be permitted in acp_board + * if there is an error. + * + * @return boolean|string False if the user is identified, otherwise an + * error message, or null if not implemented. + */ + public function init(); + + /** + * Performs login. + * + * @param string $username The name of the user being authenticated. + * @param string $password The password of the user. + * @return array An associative array of the format: + * array( + * 'status' => status constant + * 'error_msg' => string + * 'user_row' => array + * ) + * A fourth key of the array may be present: + * 'redirect_data' This key is only used when 'status' is + * equal to LOGIN_SUCCESS_LINK_PROFILE and its value is an + * associative array that is turned into GET variables on + * the redirect url. + */ + public function login($username, $password); + + /** + * Autologin function + * + * @return array|null containing the user row, empty if no auto login + * should take place, or null if not impletmented. + */ + public function autologin(); + + /** + * This function is used to output any required fields in the authentication + * admin panel. It also defines any required configuration table fields. + * + * @return array|null Returns null if not implemented or an array of the + * configuration fields of the provider. + */ + public function acp(); + + /** + * This function updates the template with variables related to the acp + * options with whatever configuraton values are passed to it as an array. + * It then returns the name of the acp file related to this authentication + * provider. + * @param array $new_config Contains the new configuration values that + * have been set in acp_board. + * @return array|null Returns null if not implemented or an array with + * the template file name and an array of the vars + * that the template needs that must conform to the + * following example: + * array( + * 'TEMPLATE_FILE' => string, + * 'TEMPLATE_VARS' => array(...), + * ) + * An optional third element may be added to this + * array: 'BLOCK_VAR_NAME'. If this is present, + * then its value should be a string that is used + * to designate the name of the loop used in the + * ACP template file. When this is present, an + * additional key named 'BLOCK_VARS' is required. + * This must be an array containing at least one + * array of variables that will be assigned during + * the loop in the template. An example of this is + * presented below: + * array( + * 'BLOCK_VAR_NAME' => string, + * 'BLOCK_VARS' => array( + * 'KEY IS UNIMPORTANT' => array(...), + * ), + * 'TEMPLATE_FILE' => string, + * 'TEMPLATE_VARS' => array(...), + * ) + */ + public function get_acp_template($new_config); + + /** + * Returns an array of data necessary to build custom elements on the login + * form. + * + * @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 + * which only 'TEMPLATE_FILE'. If 'BLOCK_VAR_NAME' is + * present then 'BLOCK_VARS' must also be present in + * the array. The fourth element 'VARS' is also + * optional. The array, with all four elements present + * looks like the following: + * array( + * 'TEMPLATE_FILE' => string, + * 'BLOCK_VAR_NAME' => string, + * 'BLOCK_VARS' => array(...), + * 'VARS' => array(...), + * ) + */ + public function get_login_data(); + + /** + * Performs additional actions during logout. + * + * @param array $data An array corresponding to + * \phpbb\session::data + * @param boolean $new_session True for a new session, false for no new + * session. + */ + public function logout($data, $new_session); + + /** + * The session validation function checks whether the user is still logged + * into phpBB. + * + * @param array $user + * @return boolean true if the given user is authenticated, false if the + * session should be closed, or null if not implemented. + */ + public function validate_session($user); + + /** + * Checks to see if $login_link_data contains all information except for the + * user_id of an account needed to successfully link an external account to + * a forum account. + * + * @param array $link_data Any data needed to link a phpBB account to + * an external account. + * @return string|null Returns a string with a language constant if there + * is data missing or null if there is no error. + */ + public function login_link_has_necessary_data($login_link_data); + + /** + * Links an external account to a phpBB account. + * + * @param array $link_data Any data needed to link a phpBB account to + * an external account. + */ + public function link_account(array $link_data); + + /** + * Returns an array of data necessary to build the ucp_auth_link page + * + * @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 + * which only 'TEMPLATE_FILE'. If 'BLOCK_VAR_NAME' is + * present then 'BLOCK_VARS' must also be present in + * the array. The fourth element 'VARS' is also + * optional. The array, with all four elements present + * looks like the following: + * array( + * 'TEMPLATE_FILE' => string, + * 'BLOCK_VAR_NAME' => string, + * 'BLOCK_VARS' => array(...), + * 'VARS' => array(...), + * ) + */ + public function get_auth_link_data(); + + /** + * Unlinks an external account from a phpBB account. + * + * @param array $link_data Any data needed to unlink a phpBB account + * from a phpbb account. + */ + public function unlink_account(array $link_data); +} diff --git a/phpBB/phpbb/avatar/driver/driver.php b/phpBB/phpbb/avatar/driver/driver.php index 29c58d4e62..dd55f09119 100644 --- a/phpBB/phpbb/avatar/driver/driver.php +++ b/phpBB/phpbb/avatar/driver/driver.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Base class for avatar drivers * @package phpBB3 */ -abstract class phpbb_avatar_driver implements phpbb_avatar_driver_interface +abstract class driver implements \phpbb\avatar\driver\driver_interface { /** * Avatar driver name @@ -29,7 +23,7 @@ abstract class phpbb_avatar_driver implements phpbb_avatar_driver_interface /** * Current board configuration - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; @@ -46,8 +40,14 @@ abstract class phpbb_avatar_driver implements phpbb_avatar_driver_interface protected $php_ext; /** + * Path Helper + * @var \phpbb\path_helper + */ + protected $path_helper; + + /** * Cache driver - * @var phpbb_cache_driver_interface + * @var \phpbb\cache\driver\driver_interface */ protected $cache; @@ -69,17 +69,19 @@ abstract class phpbb_avatar_driver implements phpbb_avatar_driver_interface /** * Construct a driver object * - * @param phpbb_config $config phpBB configuration - * @param phpbb_request $request Request object + * @param \phpbb\config\config $config phpBB configuration + * @param \phpbb\request\request $request Request object * @param string $phpbb_root_path Path to the phpBB root * @param string $php_ext PHP file extension - * @param phpbb_cache_driver_interface $cache Cache driver + * @param \phpbb_path_helper $path_helper phpBB path helper + * @param \phpbb\cache\driver\driver_interface $cache Cache driver */ - public function __construct(phpbb_config $config, $phpbb_root_path, $php_ext, phpbb_cache_driver_interface $cache = null) + public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \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->cache = $cache; } @@ -110,17 +112,6 @@ abstract class phpbb_avatar_driver implements phpbb_avatar_driver_interface /** * @inheritdoc */ - public function get_template_name() - { - $driver = preg_replace('#^phpbb_avatar_driver_#', '', get_class($this)); - $template = "ucp_avatar_options_$driver.html"; - - return $template; - } - - /** - * @inheritdoc - */ public function get_name() { return $this->name; diff --git a/phpBB/phpbb/avatar/driver/interface.php b/phpBB/phpbb/avatar/driver/driver_interface.php index 3d62969aef..7f049469a2 100644 --- a/phpBB/phpbb/avatar/driver/interface.php +++ b/phpBB/phpbb/avatar/driver/driver_interface.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Interface for avatar drivers * @package phpBB3 */ -interface phpbb_avatar_driver_interface +interface driver_interface { /** * Returns the name of the driver. @@ -32,7 +26,7 @@ interface phpbb_avatar_driver_interface * Get the avatar url and dimensions * * @param array $row User data or group data that has been cleaned with - * phpbb_avatar_manager::clean_row + * \phpbb\avatar\manager::clean_row * @return array Avatar data, must have keys src, width and height, e.g. * ['src' => '', 'width' => 0, 'height' => 0] */ @@ -41,9 +35,9 @@ interface phpbb_avatar_driver_interface /** * Returns custom html if it is needed for displaying this avatar * - * @param phpbb_user $user phpBB user object + * @param \phpbb\user $user phpBB user object * @param array $row User data or group data that has been cleaned with - * phpbb_avatar_manager::clean_row + * \phpbb\avatar\manager::clean_row * @param string $alt Alternate text for avatar image * * @return string HTML @@ -53,11 +47,11 @@ interface phpbb_avatar_driver_interface /** * Prepare form for changing the settings of this avatar * - * @param phpbb_request $request Request object - * @param phpbb_template $template Template object - * @param phpbb_user $user User object + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object * @param array $row User data or group data that has been cleaned with - * phpbb_avatar_manager::clean_row + * \phpbb\avatar\manager::clean_row * @param array &$error Reference to an error array that is filled by this * function. Key values can either be a string with a language key or * an array that will be passed to vsprintf() with the language key in @@ -70,7 +64,7 @@ interface phpbb_avatar_driver_interface /** * Prepare form for changing the acp settings of this avatar * - * @param phpbb_user $user phpBB user object + * @param \phpbb\user $user phpBB user object * * @return array Array of configuration options as consumed by acp_board. * The setting for enabling/disabling the avatar will be handled by @@ -81,11 +75,11 @@ interface phpbb_avatar_driver_interface /** * Process form data * - * @param phpbb_request $request Request object - * @param phpbb_template $template Template object - * @param phpbb_user $user User object + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object * @param array $row User data or group data that has been cleaned with - * phpbb_avatar_manager::clean_row + * \phpbb\avatar\manager::clean_row * @param array &$error Reference to an error array that is filled by this * function. Key values can either be a string with a language key or * an array that will be passed to vsprintf() with the language key in @@ -100,7 +94,7 @@ interface phpbb_avatar_driver_interface * Delete avatar * * @param array $row User data or group data that has been cleaned with - * phpbb_avatar_manager::clean_row + * \phpbb\avatar\manager::clean_row * * @return bool True if avatar has been deleted or there is no need to delete, * i.e. when the avatar is not hosted locally. diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php index d559da1c0d..9f14b7f468 100644 --- a/phpBB/phpbb/avatar/driver/gravatar.php +++ b/phpBB/phpbb/avatar/driver/gravatar.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Handles avatars hosted at gravatar.com * @package phpBB3 */ -class phpbb_avatar_driver_gravatar extends phpbb_avatar_driver +class gravatar extends \phpbb\avatar\driver\driver { /** * The URL for the gravatar service @@ -153,6 +147,14 @@ class phpbb_avatar_driver_gravatar extends phpbb_avatar_driver } /** + * @inheritdoc + */ + public function get_template_name() + { + return 'ucp_avatar_options_gravatar.html'; + } + + /** * Build gravatar URL for output on page * * @return string Gravatar URL diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php index f4bcd4ce74..611a44cb3d 100644 --- a/phpBB/phpbb/avatar/driver/local.php +++ b/phpBB/phpbb/avatar/driver/local.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Handles avatars selected from the board gallery * @package phpBB3 */ -class phpbb_avatar_driver_local extends phpbb_avatar_driver +class local extends \phpbb\avatar\driver\driver { /** * @inheritdoc @@ -27,7 +21,7 @@ class phpbb_avatar_driver_local extends phpbb_avatar_driver public function get_data($row) { return array( - 'src' => $this->phpbb_root_path . $this->config['avatar_gallery_path'] . '/' . $row['avatar'], + 'src' => $this->path_helper->get_web_root_path() . $this->config['avatar_gallery_path'] . '/' . $row['avatar'], 'width' => $row['avatar_width'], 'height' => $row['avatar_height'], ); @@ -141,10 +135,18 @@ class phpbb_avatar_driver_local extends phpbb_avatar_driver } /** + * @inheritdoc + */ + public function get_template_name() + { + return 'ucp_avatar_options_local.html'; + } + + /** * Get a list of avatars that are locally available * Results get cached for 24 hours (86400 seconds) * - * @param phpbb_user $user User object + * @param \phpbb\user $user User object * * @return array Array containing the locally available avatars */ @@ -157,7 +159,7 @@ class phpbb_avatar_driver_local extends phpbb_avatar_driver $avatar_list = array(); $path = $this->phpbb_root_path . $this->config['avatar_gallery_path']; - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS), RecursiveIteratorIterator::SELF_FIRST); + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS), \RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file_info) { $file_path = $file_info->getPath(); diff --git a/phpBB/phpbb/avatar/driver/remote.php b/phpBB/phpbb/avatar/driver/remote.php index d629a490fd..36623942df 100644 --- a/phpBB/phpbb/avatar/driver/remote.php +++ b/phpBB/phpbb/avatar/driver/remote.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Handles avatars hosted remotely * @package phpBB3 */ -class phpbb_avatar_driver_remote extends phpbb_avatar_driver +class remote extends \phpbb\avatar\driver\driver { /** * @inheritdoc @@ -120,8 +114,39 @@ class phpbb_avatar_driver_remote extends phpbb_avatar_driver include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext); } - $types = fileupload::image_types(); - $extension = strtolower(filespec::get_extension($url)); + $types = \fileupload::image_types(); + $extension = strtolower(\filespec::get_extension($url)); + + // Check if this is actually an image + if ($file_stream = @fopen($url, 'r')) + { + // Timeout after 1 second + stream_set_timeout($file_stream, 1); + $meta = stream_get_meta_data($file_stream); + foreach ($meta['wrapper_data'] as $header) + { + $header = preg_split('/ /', $header, 2); + if (strtr(strtolower(trim($header[0], ':')), '_', '-') === 'content-type') + { + if (strpos($header[1], 'image/') !== 0) + { + $error[] = 'AVATAR_URL_INVALID'; + fclose($file_stream); + return false; + } + else + { + fclose($file_stream); + break; + } + } + } + } + else + { + $error[] = 'AVATAR_URL_INVALID'; + return false; + } if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]]))) { @@ -161,4 +186,12 @@ class phpbb_avatar_driver_remote extends phpbb_avatar_driver 'avatar_height' => $height, ); } + + /** + * @inheritdoc + */ + public function get_template_name() + { + return 'ucp_avatar_options_remote.html'; + } } diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 685ac4f349..f77ef1332b 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar\driver; /** * Handles avatars uploaded to the board * @package phpBB3 */ -class phpbb_avatar_driver_upload extends phpbb_avatar_driver +class upload extends \phpbb\avatar\driver\driver { /** * @inheritdoc @@ -27,7 +21,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver public function get_data($row, $ignore_config = false) { return array( - 'src' => $this->phpbb_root_path . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'], + 'src' => $this->path_helper->get_web_root_path() . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'], 'width' => $row['avatar_width'], 'height' => $row['avatar_height'], ); @@ -66,7 +60,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext); } - $upload = new fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); + $upload = new \fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); $url = $request->variable('avatar_upload_url', ''); $upload_file = $request->file('avatar_upload_file'); @@ -153,7 +147,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver return array( 'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'number:0', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), - 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true), + 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), ); } @@ -174,6 +168,14 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver } /** + * @inheritdoc + */ + public function get_template_name() + { + return 'ucp_avatar_options_upload.html'; + } + + /** * Check if user is able to upload an avatar * * @return bool True if user can upload, false if not diff --git a/phpBB/phpbb/avatar/manager.php b/phpBB/phpbb/avatar/manager.php index 58d994c3c0..6ce924d2eb 100644 --- a/phpBB/phpbb/avatar/manager.php +++ b/phpBB/phpbb/avatar/manager.php @@ -7,22 +7,16 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\avatar; /** * @package avatar */ -class phpbb_avatar_manager +class manager { /** * phpBB configuration - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; @@ -40,12 +34,6 @@ class phpbb_avatar_manager protected $avatar_drivers; /** - * Service container object - * @var object - */ - protected $container; - - /** * Default avatar data row * @var array */ @@ -59,15 +47,29 @@ class phpbb_avatar_manager /** * Construct an avatar manager object * - * @param phpbb_config $config phpBB configuration + * @param \phpbb\config\config $config phpBB configuration * @param array $avatar_drivers Avatar drivers passed via the service container - * @param object $container Container object */ - public function __construct(phpbb_config $config, $avatar_drivers, $container) + public function __construct(\phpbb\config\config $config, $avatar_drivers) { $this->config = $config; - $this->avatar_drivers = $avatar_drivers; - $this->container = $container; + $this->register_avatar_drivers($avatar_drivers); + } + + /** + * Register avatar drivers + * + * @param array $avatar_drivers Service collection of avatar drivers + */ + protected function register_avatar_drivers($avatar_drivers) + { + if (!empty($avatar_drivers)) + { + foreach ($avatar_drivers as $driver) + { + $this->avatar_drivers[$driver->get_name()] = $driver; + } + } } /** @@ -110,7 +112,7 @@ class phpbb_avatar_manager * There is no need to handle invalid avatar types as the following code * will cause a ServiceNotFoundException if the type does not exist */ - $driver = $this->container->get($avatar_type); + $driver = $this->avatar_drivers[$avatar_type]; return $driver; } @@ -176,14 +178,16 @@ class phpbb_avatar_manager } /** - * Strip out user_ and group_ prefixes from keys + * Strip out user_, group_, or other prefixes from array keys * - * @param array $row User data or group data + * @param array $row User data or group data + * @param string $prefix Prefix of data keys (e.g. user), should not include the trailing underscore * - * @return array User data or group data with keys that have been - * stripped from the preceding "user_" or "group_" + * @return array User or group data with keys that have been + * stripped from the preceding "user_" or "group_" + * Also the group id is prefixed with g, when the prefix group is removed. */ - static public function clean_row($row) + static public function clean_row($row, $prefix = '') { // Upon creation of a user/group $row might be empty if (empty($row)) @@ -191,23 +195,19 @@ class phpbb_avatar_manager return self::$default_row; } - $keys = array_keys($row); - $values = array_values($row); - - $keys = array_map(array('phpbb_avatar_manager', 'strip_prefix'), $keys); + $output = array(); + foreach ($row as $key => $value) + { + $key = preg_replace("#^(?:{$prefix}_)#", '', $key); + $output[$key] = $value; + } - return array_combine($keys, $values); - } + if ($prefix === 'group' && isset($output['id'])) + { + $output['id'] = 'g' . $output['id']; + } - /** - * Strip prepending user_ or group_ prefix from key - * - * @param string Array key - * @return string Key that has been stripped from its prefix - */ - static protected function strip_prefix($key) - { - return preg_replace('#^(?:user_|group_)#', '', $key); + return $output; } /** @@ -220,7 +220,7 @@ class phpbb_avatar_manager */ static public function clean_driver_name($name) { - return str_replace('_', '.', $name); + return str_replace(array('\\', '_'), '.', $name); } /** @@ -262,7 +262,7 @@ class phpbb_avatar_manager $config_name = $this->get_driver_config_name($driver); return array( - 'allow_avatar_' . $config_name => array('lang' => 'ALLOW_' . strtoupper($config_name), 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_avatar_' . $config_name => array('lang' => 'ALLOW_' . strtoupper(str_replace('\\', '_', $config_name)), 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), ); } @@ -275,13 +275,13 @@ class phpbb_avatar_manager */ public function get_driver_config_name($driver) { - return preg_replace('#^phpbb_avatar_driver_#', '', get_class($driver)); + return preg_replace('#^phpbb\\\\avatar\\\\driver\\\\#', '', get_class($driver)); } /** * Replace "error" strings with their real, localized form * - * @param phpbb_user phpBB User object + * @param \phpbb\user phpBB User object * @param array $error Array containing error strings * Key values can either be a string with a language key or an array * that will be passed to vsprintf() with the language key in the @@ -289,7 +289,7 @@ class phpbb_avatar_manager * * @return array Array containing the localized error strings */ - public function localize_errors(phpbb_user $user, $error) + public function localize_errors(\phpbb\user $user, $error) { foreach ($error as $key => $lang) { diff --git a/phpBB/phpbb/cache/driver/apc.php b/phpBB/phpbb/cache/driver/apc.php index 0516b669c8..77b7b11181 100644 --- a/phpBB/phpbb/cache/driver/apc.php +++ b/phpBB/phpbb/cache/driver/apc.php @@ -7,26 +7,18 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM for APC * @package acm */ -class phpbb_cache_driver_apc extends phpbb_cache_driver_memory +class apc extends \phpbb\cache\driver\memory { var $extension = 'apc'; /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php index 32e04f813a..feaca25a5b 100644 --- a/phpBB/phpbb/cache/driver/base.php +++ b/phpBB/phpbb/cache/driver/base.php @@ -7,17 +7,11 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * @package acm */ -abstract class phpbb_cache_driver_base implements phpbb_cache_driver_interface +abstract class base implements \phpbb\cache\driver\driver_interface { } diff --git a/phpBB/phpbb/cache/driver/interface.php b/phpBB/phpbb/cache/driver/driver_interface.php index 53f684d1c8..8929647411 100644 --- a/phpBB/phpbb/cache/driver/interface.php +++ b/phpBB/phpbb/cache/driver/driver_interface.php @@ -7,63 +7,84 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * An interface that all cache drivers must implement * * @package acm */ -interface phpbb_cache_driver_interface +interface driver_interface { /** * Load global cache + * + * @return mixed False if an error was encountered, otherwise the data type of the cached data */ public function load(); /** * Unload cache object + * + * @return null */ public function unload(); /** * Save modified objects + * + * @return null */ public function save(); /** * Tidy cache + * + * @return null */ public function tidy(); /** * Get saved cache object + * + * @param string $var_name Cache key + * @return mixed False if an error was encountered, otherwise the saved cached object */ public function get($var_name); /** * Put data into cache + * + * @param string $var_name Cache key + * @param mixed $var Cached data to store + * @param int $ttl Time-to-live of cached data + * @return null */ public function put($var_name, $var, $ttl = 0); /** * Purge cache data + * + * @return null */ public function purge(); /** * Destroy cache data + * + * @param string $var_name Cache key + * @param string $table Table name + * @return null */ public function destroy($var_name, $table = ''); /** * Check if a given cache entry exists + * + * @param string $var_name Cache key + * + * @return bool True if cache file exists and has not expired. + * False otherwise. */ public function _exists($var_name); @@ -85,10 +106,10 @@ interface phpbb_cache_driver_interface * result to persistent storage. In other words, there is no need * to call save() afterwards. * - * @param phpbb_db_driver $db Database connection + * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $query SQL query, should be used for generating storage key - * @param mixed $query_result The result from dbal::sql_query, to be passed to - * dbal::sql_fetchrow to get all rows and store them + * @param mixed $query_result The result from \dbal::sql_query, to be passed to + * \dbal::sql_fetchrow to get all rows and store them * in cache. * @param int $ttl Time to live, after this timeout the query should * expire from the cache. @@ -96,7 +117,7 @@ interface phpbb_cache_driver_interface * representing the query should be returned. Otherwise * the original $query_result should be returned. */ - public function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl); + public function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl); /** * Check if result for a given SQL query exists in cache. diff --git a/phpBB/phpbb/cache/driver/eaccelerator.php b/phpBB/phpbb/cache/driver/eaccelerator.php index 257b90c76e..d1ad69ef6d 100644 --- a/phpBB/phpbb/cache/driver/eaccelerator.php +++ b/phpBB/phpbb/cache/driver/eaccelerator.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM for eAccelerator * @package acm * @todo Missing locks from destroy() talk with David */ -class phpbb_cache_driver_eaccelerator extends phpbb_cache_driver_memory +class eaccelerator extends \phpbb\cache\driver\memory { var $extension = 'eaccelerator'; var $function = 'eaccelerator_get'; @@ -28,9 +22,7 @@ class phpbb_cache_driver_eaccelerator extends phpbb_cache_driver_memory var $serialize_header = '#phpbb-serialized#'; /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { @@ -45,10 +37,8 @@ class phpbb_cache_driver_eaccelerator extends phpbb_cache_driver_memory } /** - * Perform cache garbage collection - * - * @return null - */ + * {@inheritDoc} + */ function tidy() { eaccelerator_gc(); diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index 944dfd6541..286ba328c3 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM File Based Caching * @package acm */ -class phpbb_cache_driver_file extends phpbb_cache_driver_base +class file extends \phpbb\cache\driver\base { var $vars = array(); var $var_expires = array(); @@ -39,7 +33,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Load global cache + * {@inheritDoc} */ function load() { @@ -47,7 +41,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Unload cache object + * {@inheritDoc} */ function unload() { @@ -64,7 +58,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Save modified objects + * {@inheritDoc} */ function save() { @@ -99,7 +93,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Tidy cache + * {@inheritDoc} */ function tidy() { @@ -161,7 +155,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Get saved cache object + * {@inheritDoc} */ function get($var_name) { @@ -183,7 +177,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Put data into cache + * {@inheritDoc} */ function put($var_name, $var, $ttl = 31536000) { @@ -200,14 +194,14 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Purge cache data + * {@inheritDoc} */ function purge() { // Purge all phpbb cache files - try + try { - $iterator = new DirectoryIterator($this->cache_dir); + $iterator = new \DirectoryIterator($this->cache_dir); } catch (Exception $e) { @@ -256,9 +250,9 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base */ protected function remove_dir($dir) { - try + try { - $iterator = new DirectoryIterator($dir); + $iterator = new \DirectoryIterator($dir); } catch (Exception $e) { @@ -286,7 +280,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Destroy cache data + * {@inheritDoc} */ function destroy($var_name, $table = '') { @@ -365,7 +359,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Check if a given cache entry exist + * {@inheritDoc} */ function _exists($var_name) { @@ -391,7 +385,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Load cached sql query + * {@inheritDoc} */ function sql_load($query) { @@ -413,7 +407,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base /** * {@inheritDoc} */ - function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) + function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl) { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); @@ -437,7 +431,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Ceck if a given sql query exist in cache + * {@inheritDoc} */ function sql_exists($query_id) { @@ -445,7 +439,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Fetch row from cache (database) + * {@inheritDoc} */ function sql_fetchrow($query_id) { @@ -458,7 +452,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Fetch a field from the current row of a cached database result (database) + * {@inheritDoc} */ function sql_fetchfield($query_id, $field) { @@ -471,7 +465,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Seek a specific row in an a cached database result (database) + * {@inheritDoc} */ function sql_rowseek($rownum, $query_id) { @@ -485,7 +479,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Free memory used for a cached database result (database) + * {@inheritDoc} */ function sql_freeresult($query_id) { @@ -695,7 +689,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base $file = "{$this->cache_dir}$filename.$phpEx"; - $lock = new phpbb_lock_flock($file); + $lock = new \phpbb\lock\flock($file); $lock->acquire(); if ($handle = @fopen($file, 'wb')) @@ -764,6 +758,10 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base /** * Removes/unlinks file + * + * @param string $filename Filename to remove + * @param bool $check Check file permissions + * @return bool True if the file was successfully removed, otherwise false */ function remove_file($filename, $check = false) { diff --git a/phpBB/phpbb/cache/driver/memcache.php b/phpBB/phpbb/cache/driver/memcache.php index 3fd16b23b0..eb3fced973 100644 --- a/phpBB/phpbb/cache/driver/memcache.php +++ b/phpBB/phpbb/cache/driver/memcache.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; if (!defined('PHPBB_ACM_MEMCACHE_PORT')) { @@ -40,7 +34,7 @@ if (!defined('PHPBB_ACM_MEMCACHE')) * ACM for Memcached * @package acm */ -class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory +class memcache extends \phpbb\cache\driver\memory { var $extension = 'memcache'; @@ -52,7 +46,7 @@ class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory // Call the parent constructor parent::__construct(); - $this->memcache = new Memcache; + $this->memcache = new \Memcache; foreach(explode(',', PHPBB_ACM_MEMCACHE) as $u) { $parts = explode('/', $u); @@ -62,9 +56,7 @@ class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory } /** - * Unload the cache resources - * - * @return null + * {@inheritDoc} */ function unload() { @@ -74,9 +66,7 @@ class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory } /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php index f77a1df316..d5404455d1 100644 --- a/phpBB/phpbb/cache/driver/memory.php +++ b/phpBB/phpbb/cache/driver/memory.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM Abstract Memory Class * @package acm */ -abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base +abstract class memory extends \phpbb\cache\driver\base { var $key_prefix; @@ -56,7 +50,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Load global cache + * {@inheritDoc} */ function load() { @@ -72,7 +66,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Unload cache object + * {@inheritDoc} */ function unload() { @@ -87,7 +81,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Save modified objects + * {@inheritDoc} */ function save() { @@ -102,7 +96,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Tidy cache + * {@inheritDoc} */ function tidy() { @@ -112,7 +106,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Get saved cache object + * {@inheritDoc} */ function get($var_name) { @@ -132,7 +126,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Put data into cache + * {@inheritDoc} */ function put($var_name, $var, $ttl = 2592000) { @@ -148,7 +142,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Purge cache data + * {@inheritDoc} */ function purge() { @@ -189,7 +183,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base /** - * Destroy cache data + * {@inheritDoc} */ function destroy($var_name, $table = '') { @@ -243,7 +237,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Check if a given cache entry exist + * {@inheritDoc} */ function _exists($var_name) { @@ -263,7 +257,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Load cached sql query + * {@inheritDoc} */ function sql_load($query) { @@ -285,7 +279,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base /** * {@inheritDoc} */ - function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) + function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl) { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); @@ -341,7 +335,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Ceck if a given sql query exist in cache + * {@inheritDoc} */ function sql_exists($query_id) { @@ -349,7 +343,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Fetch row from cache (database) + * {@inheritDoc} */ function sql_fetchrow($query_id) { @@ -362,7 +356,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Fetch a field from the current row of a cached database result (database) + * {@inheritDoc} */ function sql_fetchfield($query_id, $field) { @@ -375,7 +369,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Seek a specific row in an a cached database result (database) + * {@inheritDoc} */ function sql_rowseek($rownum, $query_id) { @@ -389,7 +383,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Free memory used for a cached database result (database) + * {@inheritDoc} */ function sql_freeresult($query_id) { @@ -406,6 +400,10 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base /** * Removes/unlinks file + * + * @param string $filename Filename to remove + * @param bool $check Check file permissions + * @return bool True if the file was successfully removed, otherwise false */ function remove_file($filename, $check = false) { diff --git a/phpBB/phpbb/cache/driver/null.php b/phpBB/phpbb/cache/driver/null.php index 2fadc27ba3..99cfe454e0 100644 --- a/phpBB/phpbb/cache/driver/null.php +++ b/phpBB/phpbb/cache/driver/null.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM Null Caching * @package acm */ -class phpbb_cache_driver_null extends phpbb_cache_driver_base +class null extends \phpbb\cache\driver\base { /** * Set cache path @@ -29,7 +23,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Load global cache + * {@inheritDoc} */ function load() { @@ -37,21 +31,21 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Unload cache object + * {@inheritDoc} */ function unload() { } /** - * Save modified objects + * {@inheritDoc} */ function save() { } /** - * Tidy cache + * {@inheritDoc} */ function tidy() { @@ -60,7 +54,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Get saved cache object + * {@inheritDoc} */ function get($var_name) { @@ -68,28 +62,28 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Put data into cache + * {@inheritDoc} */ function put($var_name, $var, $ttl = 0) { } /** - * Purge cache data + * {@inheritDoc} */ function purge() { } /** - * Destroy cache data + * {@inheritDoc} */ function destroy($var_name, $table = '') { } /** - * Check if a given cache entry exist + * {@inheritDoc} */ function _exists($var_name) { @@ -97,7 +91,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Load cached sql query + * {@inheritDoc} */ function sql_load($query) { @@ -107,13 +101,13 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base /** * {@inheritDoc} */ - function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) + function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl) { return $query_result; } /** - * Ceck if a given sql query exist in cache + * {@inheritDoc} */ function sql_exists($query_id) { @@ -121,7 +115,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Fetch row from cache (database) + * {@inheritDoc} */ function sql_fetchrow($query_id) { @@ -129,7 +123,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Fetch a field from the current row of a cached database result (database) + * {@inheritDoc} */ function sql_fetchfield($query_id, $field) { @@ -137,7 +131,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Seek a specific row in an a cached database result (database) + * {@inheritDoc} */ function sql_rowseek($rownum, $query_id) { @@ -145,7 +139,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Free memory used for a cached database result (database) + * {@inheritDoc} */ function sql_freeresult($query_id) { diff --git a/phpBB/phpbb/cache/driver/redis.php b/phpBB/phpbb/cache/driver/redis.php index 960735b673..2f2a32a12d 100644 --- a/phpBB/phpbb/cache/driver/redis.php +++ b/phpBB/phpbb/cache/driver/redis.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; if (!defined('PHPBB_ACM_REDIS_PORT')) { @@ -33,7 +27,7 @@ if (!defined('PHPBB_ACM_REDIS_HOST')) * * @package acm */ -class phpbb_cache_driver_redis extends phpbb_cache_driver_memory +class redis extends \phpbb\cache\driver\memory { var $extension = 'redis'; @@ -56,7 +50,7 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory // Call the parent constructor parent::__construct(); - $this->redis = new Redis(); + $this->redis = new \Redis(); $args = func_get_args(); if (!empty($args)) @@ -83,8 +77,8 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory } } - $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); - $this->redis->setOption(Redis::OPT_PREFIX, $this->key_prefix); + $this->redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP); + $this->redis->setOption(\Redis::OPT_PREFIX, $this->key_prefix); if (defined('PHPBB_ACM_REDIS_DB')) { @@ -98,9 +92,7 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory } /** - * Unload the cache resources - * - * @return null + * {@inheritDoc} */ function unload() { @@ -110,9 +102,7 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory } /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { @@ -163,4 +153,3 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory return false; } } - diff --git a/phpBB/phpbb/cache/driver/wincache.php b/phpBB/phpbb/cache/driver/wincache.php index 58f3b4a581..d0f636d9cb 100644 --- a/phpBB/phpbb/cache/driver/wincache.php +++ b/phpBB/phpbb/cache/driver/wincache.php @@ -7,26 +7,18 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM for WinCache * @package acm */ -class phpbb_cache_driver_wincache extends phpbb_cache_driver_memory +class wincache extends \phpbb\cache\driver\memory { var $extension = 'wincache'; /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { diff --git a/phpBB/phpbb/cache/driver/xcache.php b/phpBB/phpbb/cache/driver/xcache.php index 06c5fafd97..6c9323ec83 100644 --- a/phpBB/phpbb/cache/driver/xcache.php +++ b/phpBB/phpbb/cache/driver/xcache.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache\driver; /** * ACM for XCache @@ -24,7 +18,7 @@ if (!defined('IN_PHPBB')) * - xcache.admin.enable_auth = off (or xcache.admin.user and xcache.admin.password set) * */ -class phpbb_cache_driver_xcache extends phpbb_cache_driver_memory +class xcache extends \phpbb\cache\driver\memory { var $extension = 'XCache'; @@ -39,9 +33,7 @@ class phpbb_cache_driver_xcache extends phpbb_cache_driver_memory } /** - * Purge cache data - * - * @return null + * {@inheritDoc} */ function purge() { diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php index 69c5e0fdd0..f9b6324b05 100644 --- a/phpBB/phpbb/cache/service.php +++ b/phpBB/phpbb/cache/service.php @@ -7,38 +7,32 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cache; /** * Class for grabbing/handling cached entries * @package acm */ -class phpbb_cache_service +class service { /** * Cache driver. * - * @var phpbb_cache_driver_interface + * @var \phpbb\cache\driver\driver_interface */ protected $driver; /** * The config. * - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * Database connection. * - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -59,13 +53,13 @@ class phpbb_cache_service /** * Creates a cache service around a cache driver * - * @param phpbb_cache_driver_interface $driver The cache driver - * @param phpbb_config $config The config - * @param phpbb_db_driver $db Database connection + * @param \phpbb\cache\driver\driver_interface $driver The cache driver + * @param \phpbb\config\config $config The config + * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $phpbb_root_path Root path * @param string $php_ext PHP extension */ - public function __construct(phpbb_cache_driver_interface $driver, phpbb_config $config, phpbb_db_driver $db, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\cache\driver\driver_interface $driver, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext) { $this->set_driver($driver); $this->config = $config; @@ -77,7 +71,7 @@ class phpbb_cache_service /** * Returns the cache driver used by this cache service. * - * @return phpbb_cache_driver_interface The cache driver + * @return \phpbb\cache\driver\driver_interface The cache driver */ public function get_driver() { @@ -87,9 +81,9 @@ class phpbb_cache_service /** * Replaces the cache driver used by this cache service. * - * @param phpbb_cache_driver_interface $driver The cache driver + * @param \phpbb\cache\driver\driver_interface $driver The cache driver */ - public function set_driver(phpbb_cache_driver_interface $driver) + public function set_driver(\phpbb\cache\driver\driver_interface $driver) { $this->driver = $driver; } diff --git a/phpBB/phpbb/class_loader.php b/phpBB/phpbb/class_loader.php index 02a2d584dc..ee9767148b 100644 --- a/phpBB/phpbb/class_loader.php +++ b/phpBB/phpbb/class_loader.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * The class loader resolves class names to file system paths and loads them if @@ -28,9 +22,9 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_class_loader +class class_loader { - private $prefix; + private $namespace; private $path; private $php_ext; private $cache; @@ -44,17 +38,22 @@ class phpbb_class_loader private $cached_paths = array(); /** - * Creates a new phpbb_class_loader, which loads files with the given + * Creates a new \phpbb\class_loader, which loads files with the given * file extension from the given path. * - * @param string $prefix Required class name prefix for files to be loaded + * @param string $namespace Required namespace for files to be loaded * @param string $path Directory to load files from * @param string $php_ext The file extension for PHP files - * @param phpbb_cache_driver_interface $cache An implementation of the phpBB cache interface. + * @param \phpbb\cache\driver\driver_interface $cache An implementation of the phpBB cache interface. */ - public function __construct($prefix, $path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null) + public function __construct($namespace, $path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null) { - $this->prefix = $prefix; + if ($namespace[0] !== '\\') + { + $namespace = '\\' . $namespace; + } + + $this->namespace = $namespace; $this->path = $path; $this->php_ext = $php_ext; @@ -66,13 +65,13 @@ class phpbb_class_loader * the class loader will resolve paths by checking for the existance of every * directory in the class name every time. * - * @param phpbb_cache_driver_interface $cache An implementation of the phpBB cache interface. + * @param \phpbb\cache\driver\driver_interface $cache An implementation of the phpBB cache interface. */ - public function set_cache(phpbb_cache_driver_interface $cache = null) + public function set_cache(\phpbb\cache\driver\driver_interface $cache = null) { if ($cache) { - $this->cached_paths = $cache->get('class_loader_' . $this->prefix); + $this->cached_paths = $cache->get('class_loader_' . str_replace('\\', '__', $this->namespace)); if ($this->cached_paths === false) { @@ -102,8 +101,9 @@ class phpbb_class_loader /** * Resolves a phpBB class name to a relative path which can be included. * - * @param string $class The class name to resolve, must have a phpbb_ - * prefix + * @param string $class The class name to resolve, must be in the + * namespace the loader was constructed with. + * Has to begin with \ * @return string|bool A relative path to the file containing the * class or false if looking it up failed. */ @@ -114,27 +114,12 @@ class phpbb_class_loader return $this->path . $this->cached_paths[$class] . '.' . $this->php_ext; } - if (!preg_match('/^' . $this->prefix . '[a-zA-Z0-9_]+$/', $class)) + if (!preg_match('/^' . preg_quote($this->namespace, '/') . '[a-zA-Z0-9_\\\\]+$/', $class)) { return false; } - $parts = explode('_', substr($class, strlen($this->prefix))); - - $dirs = ''; - - for ($i = 0, $n = sizeof($parts); $i < $n && is_dir($this->path . $dirs . $parts[$i]); $i++) - { - $dirs .= $parts[$i] . '/'; - } - - // no file name left => use last dir name as file name - if ($i == sizeof($parts)) - { - $parts[] = $parts[$i - 1]; - } - - $relative_path = $dirs . implode(array_slice($parts, $i, sizeof($parts) - $i), '_'); + $relative_path = str_replace('\\', '/', substr($class, strlen($this->namespace))); if (!file_exists($this->path . $relative_path . '.' . $this->php_ext)) { @@ -144,7 +129,7 @@ class phpbb_class_loader if ($this->cache) { $this->cached_paths[$class] = $relative_path; - $this->cache->put('class_loader_' . $this->prefix, $this->cached_paths); + $this->cache->put('class_loader_' . str_replace('\\', '__', $this->namespace), $this->cached_paths); } return $this->path . $relative_path . '.' . $this->php_ext; @@ -157,7 +142,14 @@ class phpbb_class_loader */ public function load_class($class) { - if (substr($class, 0, strlen($this->prefix)) === $this->prefix) + // In general $class is not supposed to contain a leading backslash, + // but sometimes it does. See tickets PHP-50731 and HHVM-1840. + if ($class[0] !== '\\') + { + $class = '\\' . $class; + } + + if (substr($class, 0, strlen($this->namespace)) === $this->namespace) { $path = $this->resolve_path($class); diff --git a/phpBB/phpbb/config/config.php b/phpBB/phpbb/config/config.php index 4b533dd55c..d37922acf1 100644 --- a/phpBB/phpbb/config/config.php +++ b/phpBB/phpbb/config/config.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\config; /** * Configuration container class * @package phpBB3 */ -class phpbb_config implements ArrayAccess, IteratorAggregate, Countable +class config implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The configuration data @@ -44,7 +38,7 @@ class phpbb_config implements ArrayAccess, IteratorAggregate, Countable */ public function getIterator() { - return new ArrayIterator($this->config); + return new \ArrayIterator($this->config); } /** @@ -90,7 +84,7 @@ class phpbb_config implements ArrayAccess, IteratorAggregate, Countable */ public function offsetUnset($key) { - trigger_error('Config values have to be deleted explicitly with the phpbb_config::delete($key) method.', E_USER_ERROR); + trigger_error('Config values have to be deleted explicitly with the \phpbb\config\config::delete($key) method.', E_USER_ERROR); } /** diff --git a/phpBB/phpbb/config/db.php b/phpBB/phpbb/config/db.php index b18369a479..ea84a9f873 100644 --- a/phpBB/phpbb/config/db.php +++ b/phpBB/phpbb/config/db.php @@ -7,29 +7,23 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\config; /** * Configuration container class * @package phpBB3 */ -class phpbb_config_db extends phpbb_config +class db extends \phpbb\config\config { /** * Cache instance - * @var phpbb_cache_driver_interface + * @var \phpbb\cache\driver\driver_interface */ protected $cache; /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -42,11 +36,11 @@ class phpbb_config_db extends phpbb_config /** * Creates a configuration container with a default set of values * - * @param phpbb_db_driver $db Database connection - * @param phpbb_cache_driver_interface $cache Cache instance + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\cache\driver\driver_interface $cache Cache instance * @param string $table Configuration table name */ - public function __construct(phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $table) { $this->db = $db; $this->cache = $cache; diff --git a/phpBB/phpbb/config/db_text.php b/phpBB/phpbb/config/db_text.php index b365cb5c77..250a2ec7de 100644 --- a/phpBB/phpbb/config/db_text.php +++ b/phpBB/phpbb/config/db_text.php @@ -7,26 +7,20 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\config; /** * Manages configuration options with an arbitrary length value stored in a TEXT -* column. In constrast to class phpbb_config_db, values are never cached and +* column. In constrast to class \phpbb\config\db, values are never cached and * prefetched, but every get operation sends a query to the database. * * @package phpBB3 */ -class phpbb_config_db_text +class db_text { /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -37,10 +31,10 @@ class phpbb_config_db_text protected $table; /** - * @param phpbb_db_driver $db Database connection + * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $table Table name */ - public function __construct(phpbb_db_driver $db, $table) + public function __construct(\phpbb\db\driver\driver_interface $db, $table) { $this->db = $db; $this->table = $this->db->sql_escape($table); diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php new file mode 100644 index 0000000000..fdcd9d42f6 --- /dev/null +++ b/phpBB/phpbb/console/application.php @@ -0,0 +1,23 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\console; + +use Symfony\Component\DependencyInjection\TaggedContainerInterface; + +class application extends \Symfony\Component\Console\Application +{ + function register_container_commands(TaggedContainerInterface $container, $tag = 'console.command') + { + foreach($container->findTaggedServiceIds($tag) as $id => $void) + { + $this->add($container->get($id)); + } + } +} diff --git a/phpBB/phpbb/console/command/command.php b/phpBB/phpbb/console/command/command.php new file mode 100644 index 0000000000..6abbdd203c --- /dev/null +++ b/phpBB/phpbb/console/command/command.php @@ -0,0 +1,14 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\console\command; + +abstract class command extends \Symfony\Component\Console\Command\Command +{ +} diff --git a/phpBB/phpbb/console/command/config/command.php b/phpBB/phpbb/console/command/config/command.php new file mode 100644 index 0000000000..b105bc826d --- /dev/null +++ b/phpBB/phpbb/console/command/config/command.php @@ -0,0 +1,22 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +abstract class command extends \phpbb\console\command\command +{ + /** @var \phpbb\config\config */ + protected $config; + + function __construct(\phpbb\config\config $config) + { + $this->config = $config; + + parent::__construct(); + } +} diff --git a/phpBB/phpbb/console/command/config/delete.php b/phpBB/phpbb/console/command/config/delete.php new file mode 100644 index 0000000000..9a2d00561d --- /dev/null +++ b/phpBB/phpbb/console/command/config/delete.php @@ -0,0 +1,46 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class delete extends command +{ + protected function configure() + { + $this + ->setName('config:delete') + ->setDescription('Deletes a configuration option') + ->addArgument( + 'key', + InputArgument::REQUIRED, + "The configuration option's name" + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $key = $input->getArgument('key'); + + if (isset($this->config[$key])) + { + $this->config->delete($key); + + $output->writeln("<info>Successfully deleted config $key</info>"); + } + else + { + $output->writeln("<error>Config $key does not exist</error>"); + } + } +} diff --git a/phpBB/phpbb/console/command/config/get.php b/phpBB/phpbb/console/command/config/get.php new file mode 100644 index 0000000000..275c82b53f --- /dev/null +++ b/phpBB/phpbb/console/command/config/get.php @@ -0,0 +1,54 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class get extends command +{ + protected function configure() + { + $this + ->setName('config:get') + ->setDescription("Gets a configuration option's value") + ->addArgument( + 'key', + InputArgument::REQUIRED, + "The configuration option's name" + ) + ->addOption( + 'no-newline', + null, + InputOption::VALUE_NONE, + 'Set this option if the value should be printed without a new line at the end.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $key = $input->getArgument('key'); + + if (isset($this->config[$key]) && $input->getOption('no-newline')) + { + $output->write($this->config[$key]); + } + elseif (isset($this->config[$key])) + { + $output->writeln($this->config[$key]); + } + else + { + $output->writeln("<error>Could not get config $key</error>"); + } + } +} diff --git a/phpBB/phpbb/console/command/config/increment.php b/phpBB/phpbb/console/command/config/increment.php new file mode 100644 index 0000000000..bc6b63c6ff --- /dev/null +++ b/phpBB/phpbb/console/command/config/increment.php @@ -0,0 +1,52 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class increment extends command +{ + protected function configure() + { + $this + ->setName('config:increment') + ->setDescription("Increments a configuration option's value") + ->addArgument( + 'key', + InputArgument::REQUIRED, + "The configuration option's name" + ) + ->addArgument( + 'increment', + InputArgument::REQUIRED, + 'Amount to increment by' + ) + ->addOption( + 'dynamic', + 'd', + InputOption::VALUE_NONE, + 'Set this option if the configuration option changes too frequently to be efficiently cached.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $key = $input->getArgument('key'); + $increment = $input->getArgument('increment'); + $use_cache = !$input->getOption('dynamic'); + + $this->config->increment($key, $increment, $use_cache); + + $output->writeln("<info>Successfully incremented config $key</info>"); + } +} diff --git a/phpBB/phpbb/console/command/config/set.php b/phpBB/phpbb/console/command/config/set.php new file mode 100644 index 0000000000..9d471a96ad --- /dev/null +++ b/phpBB/phpbb/console/command/config/set.php @@ -0,0 +1,52 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class set extends command +{ + protected function configure() + { + $this + ->setName('config:set') + ->setDescription("Sets a configuration option's value") + ->addArgument( + 'key', + InputArgument::REQUIRED, + "The configuration option's name" + ) + ->addArgument( + 'value', + InputArgument::REQUIRED, + 'New configuration value, use 0 and 1 to specify boolean values' + ) + ->addOption( + 'dynamic', + 'd', + InputOption::VALUE_NONE, + 'Set this option if the configuration option changes too frequently to be efficiently cached.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $key = $input->getArgument('key'); + $value = $input->getArgument('value'); + $use_cache = !$input->getOption('dynamic'); + + $this->config->set($key, $value, $use_cache); + + $output->writeln("<info>Successfully set config $key</info>"); + } +} diff --git a/phpBB/phpbb/console/command/config/set_atomic.php b/phpBB/phpbb/console/command/config/set_atomic.php new file mode 100644 index 0000000000..03e7a60210 --- /dev/null +++ b/phpBB/phpbb/console/command/config/set_atomic.php @@ -0,0 +1,65 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\config; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class set_atomic extends command +{ + protected function configure() + { + $this + ->setName('config:set-atomic') + ->setDescription("Sets a configuration option's value only if the old matches the current value.") + ->addArgument( + 'key', + InputArgument::REQUIRED, + "The configuration option's name" + ) + ->addArgument( + 'old', + InputArgument::REQUIRED, + 'Current configuration value, use 0 and 1 to specify boolean values' + ) + ->addArgument( + 'new', + InputArgument::REQUIRED, + 'New configuration value, use 0 and 1 to specify boolean values' + ) + ->addOption( + 'dynamic', + 'd', + InputOption::VALUE_NONE, + 'Set this option if the configuration option changes too frequently to be efficiently cached.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $key = $input->getArgument('key'); + $old_value = $input->getArgument('old'); + $new_value = $input->getArgument('new'); + $use_cache = !$input->getOption('dynamic'); + + if ($this->config->set_atomic($key, $old_value, $new_value, $use_cache)) + { + $output->writeln("<info>Successfully set config $key</info>"); + return 0; + } + else + { + $output->writeln("<error>Could not set config $key</error>"); + return 1; + } + } +} diff --git a/phpBB/phpbb/console/command/extension/command.php b/phpBB/phpbb/console/command/extension/command.php new file mode 100644 index 0000000000..edde7ce2e2 --- /dev/null +++ b/phpBB/phpbb/console/command/extension/command.php @@ -0,0 +1,22 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\extension; + +abstract class command extends \phpbb\console\command\command +{ + /** @var \phpbb\extension\manager */ + protected $manager; + + function __construct(\phpbb\extension\manager $manager) + { + $this->manager = $manager; + + parent::__construct(); + } +} diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php new file mode 100644 index 0000000000..e4de70ca34 --- /dev/null +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\extension; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class disable extends command +{ + protected function configure() + { + $this + ->setName('extension:disable') + ->setDescription('Disables the specified extension.') + ->addArgument( + 'extension-name', + InputArgument::REQUIRED, + 'Name of the extension' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument('extension-name'); + $this->manager->disable($name); + $this->manager->load_extensions(); + + if ($this->manager->enabled($name)) + { + $output->writeln("<error>Could not disable extension $name</error>"); + return 1; + } + else + { + $output->writeln("<info>Successfully disabled extension $name</info>"); + return 0; + } + } +} diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php new file mode 100644 index 0000000000..ee7dae76aa --- /dev/null +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\extension; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class enable extends command +{ + protected function configure() + { + $this + ->setName('extension:enable') + ->setDescription('Enables the specified extension.') + ->addArgument( + 'extension-name', + InputArgument::REQUIRED, + 'Name of the extension' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument('extension-name'); + $this->manager->enable($name); + $this->manager->load_extensions(); + + if ($this->manager->enabled($name)) + { + $output->writeln("<info>Successfully enabled extension $name</info>"); + return 0; + } + else + { + $output->writeln("<error>Could not enable extension $name</error>"); + return 1; + } + } +} diff --git a/phpBB/phpbb/console/command/extension/purge.php b/phpBB/phpbb/console/command/extension/purge.php new file mode 100644 index 0000000000..c2e1d2928c --- /dev/null +++ b/phpBB/phpbb/console/command/extension/purge.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\extension; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class purge extends command +{ + protected function configure() + { + $this + ->setName('extension:purge') + ->setDescription('Purges the specified extension.') + ->addArgument( + 'extension-name', + InputArgument::REQUIRED, + 'Name of the extension' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument('extension-name'); + $this->manager->purge($name); + $this->manager->load_extensions(); + + if ($this->manager->enabled($name)) + { + $output->writeln("<error>Could not purge extension $name</error>"); + return 1; + } + else + { + $output->writeln("<info>Successfully purge extension $name</info>"); + return 0; + } + } +} diff --git a/phpBB/phpbb/console/command/extension/show.php b/phpBB/phpbb/console/command/extension/show.php new file mode 100644 index 0000000000..0f48ac2379 --- /dev/null +++ b/phpBB/phpbb/console/command/extension/show.php @@ -0,0 +1,58 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\extension; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class show extends command +{ + protected function configure() + { + $this + ->setName('extension:show') + ->setDescription('Lists all extensions in the database and on the filesystem.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->manager->load_extensions(); + $all = array_keys($this->manager->all_available()); + + if (empty($all)) + { + $output->writeln('<comment>No extensions were found.</comment>'); + return 3; + } + + $enabled = array_keys($this->manager->all_enabled()); + $this->print_extension_list($output, 'Enabled', $enabled); + + $output->writeln(''); + + $disabled = array_keys($this->manager->all_disabled()); + $this->print_extension_list($output, 'Disabled', $disabled); + + $output->writeln(''); + + $purged = array_diff($all, $enabled, $disabled); + $this->print_extension_list($output, 'Available', $purged); + } + + protected function print_extension_list(OutputInterface $output, $type, array $extensions) + { + $output->writeln("<info>$type:</info>"); + + foreach ($extensions as $extension) + { + $output->writeln(" - $extension"); + } + } +} diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php new file mode 100644 index 0000000000..8c520673d9 --- /dev/null +++ b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php @@ -0,0 +1,71 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ +namespace phpbb\console\command\fixup; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class recalculate_email_hash extends \phpbb\console\command\command +{ + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + function __construct(\phpbb\db\driver\driver_interface $db) + { + $this->db = $db; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setName('fixup:recalculate-email-hash') + ->setDescription('Recalculates the user_email_hash column of the users table.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $sql = 'SELECT user_id, user_email, user_email_hash + FROM ' . USERS_TABLE . ' + WHERE user_type <> ' . USER_IGNORE . " + AND user_email <> ''"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $user_email_hash = phpbb_email_hash($row['user_email']); + if ($user_email_hash !== $row['user_email_hash']) + { + $sql_ary = array( + 'user_email_hash' => $user_email_hash, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . (int) $row['user_id']; + $this->db->sql_query($sql); + + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) + { + $output->writeln(sprintf( + 'user_id %d, email %s => %s', + $row['user_id'], + $row['user_email'], + $user_email_hash + )); + } + } + } + $this->db->sql_freeresult($result); + + $output->writeln('<info>Successfully recalculated all email hashes.</info>'); + } +} diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index fb8ece0e8c..881a8f2c54 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -7,36 +7,30 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * phpbb_visibility * Handle fetching and setting the visibility for topics and posts * @package phpbb */ -class phpbb_content_visibility +class content_visibility { /** * Database object - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Auth object - * @var phpbb_auth + * @var \phpbb\auth\auth */ protected $auth; @@ -55,14 +49,14 @@ class phpbb_content_visibility /** * Constructor * - * @param phpbb_auth $auth Auth object - * @param phpbb_db_driver $db Database object - * @param phpbb_user $user User object + * @param \phpbb\auth\auth $auth Auth object + * @param \phpbb\db\driver\driver_interface $db Database object + * @param \phpbb\user $user User object * @param string $phpbb_root_path Root path * @param string $php_ext PHP Extension * @return null */ - public function __construct(phpbb_auth $auth, phpbb_db_driver $db, phpbb_user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table) + public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table) { $this->auth = $auth; $this->db = $db; @@ -221,23 +215,23 @@ class phpbb_content_visibility /** * Change visibility status of one post or all posts of a topic * - * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED} + * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @param $post_id mixed Post ID or array of post IDs to act on, * if it is empty, all posts of topic_id will be modified * @param $topic_id int Topic where $post_id is found * @param $forum_id int Forum where $topic_id is found * @param $user_id int User performing the action * @param $time int Timestamp when the action is performed - * @param $reason string Reason why the visibilty was changed. + * @param $reason string Reason why the visibility was changed. * @param $is_starter bool Is this the first post of the topic changed? * @param $is_latest bool Is this the last post of the topic changed? * @param $limit_visibility mixed Limit updating per topic_id to a certain visibility * @param $limit_delete_time mixed Limit updating per topic_id to a certain deletion time - * @return array Changed post data, empty array if an error occured. + * @return array Changed post data, empty array if an error occurred. */ public function set_post_visibility($visibility, $post_id, $topic_id, $forum_id, $user_id, $time, $reason, $is_starter, $is_latest, $limit_visibility = false, $limit_delete_time = false) { - if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED))) + if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE))) { return array(); } @@ -332,7 +326,7 @@ class phpbb_content_visibility // Update users postcounts foreach ($postcounts as $num_posts => $poster_ids) { - if ($visibility == ITEM_DELETED) + if (in_array($visibility, array(ITEM_REAPPROVE, ITEM_DELETED))) { $sql = 'UPDATE ' . $this->users_table . ' SET user_posts = 0 @@ -393,54 +387,36 @@ class phpbb_content_visibility // Update the topic's reply count and the forum's post count if ($update_topic_postcount) { - $cur_posts = $cur_unapproved_posts = $cur_softdeleted_posts = 0; + $field_alias = array( + ITEM_APPROVED => 'posts_approved', + ITEM_UNAPPROVED => 'posts_unapproved', + ITEM_DELETED => 'posts_softdeleted', + ITEM_REAPPROVE => 'posts_unapproved', + ); + $cur_posts = array_fill_keys($field_alias, 0); + foreach ($postcount_visibility as $post_visibility => $visibility_posts) { - // We need to substract the posts from the counters ... - if ($post_visibility == ITEM_APPROVED) - { - $cur_posts += $visibility_posts; - } - else if ($post_visibility == ITEM_UNAPPROVED) - { - $cur_unapproved_posts += $visibility_posts; - } - else if ($post_visibility == ITEM_DELETED) - { - $cur_softdeleted_posts += $visibility_posts; - } + $cur_posts[$field_alias[(int) $post_visibility]] += $visibility_posts; } $sql_ary = array(); - if ($visibility == ITEM_DELETED) + $recipient_field = $field_alias[$visibility]; + + foreach ($cur_posts as $field => $count) { - if ($cur_posts) + // Decrease the count for the old statuses. + if ($count && $field != $recipient_field) { - $sql_ary['posts_approved'] = ' - ' . $cur_posts; - } - if ($cur_unapproved_posts) - { - $sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts; - } - if ($cur_posts + $cur_unapproved_posts) - { - $sql_ary['posts_softdeleted'] = ' + ' . ($cur_posts + $cur_unapproved_posts); + $sql_ary[$field] = " - $count"; } } - else + // Add up the count from all statuses excluding the recipient status. + $count_increase = array_sum(array_diff($cur_posts, array($recipient_field))); + + if ($count_increase) { - if ($cur_unapproved_posts) - { - $sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts; - } - if ($cur_softdeleted_posts) - { - $sql_ary['posts_softdeleted'] = ' - ' . $cur_softdeleted_posts; - } - if ($cur_softdeleted_posts + $cur_unapproved_posts) - { - $sql_ary['posts_approved'] = ' + ' . ($cur_softdeleted_posts + $cur_unapproved_posts); - } + $sql_ary[$recipient_field] = " + $count_increase"; } if (sizeof($sql_ary)) @@ -481,7 +457,7 @@ class phpbb_content_visibility * as soft deleted. * If you want to update all posts, use the force option. * - * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED} + * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @param $topic_id mixed Topic ID to act on * @param $forum_id int Forum where $topic_id is found * @param $user_id int User performing the action @@ -492,7 +468,7 @@ class phpbb_content_visibility */ public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false) { - if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED))) + if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE))) { return array(); } @@ -534,16 +510,16 @@ class phpbb_content_visibility if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED) { // If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion. - self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']); + $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']); } else if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED) { - // If we're soft deleting a topic we only approved posts are soft deleted. - self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']); + // If we're soft deleting a topic we only mark approved posts as soft deleted. + $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']); } else { - self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true); + $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true); } return $data; @@ -554,7 +530,7 @@ class phpbb_content_visibility * * @param $data array Contains information from the topics table about given topic * @param $sql_data array Populated with the SQL changes, may be empty at call time - * @return void + * @return null */ public function add_post_to_statistic($data, &$sql_data) { @@ -575,7 +551,7 @@ class phpbb_content_visibility * * @param $data array Contains information from the topics table about given topic * @param $sql_data array Populated with the SQL changes, may be empty at call time - * @return void + * @return null */ public function remove_post_from_statistic($data, &$sql_data) { @@ -597,7 +573,7 @@ class phpbb_content_visibility * @param $forum_id int Forum where the topic is found * @param $topic_row array Contains information from the topic, may be empty at call time * @param $sql_data array Populated with the SQL changes, may be empty at call time - * @return void + * @return null */ public function remove_topic_from_statistic($topic_id, $forum_id, &$topic_row, &$sql_data) { diff --git a/phpBB/phpbb/controller/exception.php b/phpBB/phpbb/controller/exception.php index faa8b6b584..06ece8d1d5 100644 --- a/phpBB/phpbb/controller/exception.php +++ b/phpBB/phpbb/controller/exception.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\controller; /** * Controller exception class * @package phpBB3 */ -class phpbb_controller_exception extends RuntimeException +class exception extends \RuntimeException { } diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 4d240f9380..54c30c93fc 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -7,39 +7,35 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\controller; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\RequestContext; /** * Controller helper class, contains methods that do things for controllers * @package phpBB3 */ -class phpbb_controller_helper +class helper { /** * Template object - * @var phpbb_template + * @var \phpbb\template\template */ protected $template; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** - * Request object - * @var phpbb_request + * config object + * @var \phpbb\config\config */ - protected $request; + protected $config; /** * phpBB root path @@ -56,18 +52,21 @@ class phpbb_controller_helper /** * Constructor * - * @param phpbb_template $template Template object - * @param phpbb_user $user User object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param \phpbb\config\config $config Config object + * @param \phpbb\controller\provider $provider Path provider * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP extension */ - public function __construct(phpbb_template $template, phpbb_user $user, phpbb_request_interface $request, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; - $this->request = $request; + $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->route_collection = $provider->get_routes(); } /** @@ -78,9 +77,9 @@ class phpbb_controller_helper * @param int $status_code The status code to be sent to the page header * @return Response object containing rendered page */ - public function render($template_file, $page_title = '', $status_code = 200) + public function render($template_file, $page_title = '', $status_code = 200, $display_online_list = false) { - page_header($page_title); + page_header($page_title, $display_online_list); $this->template->set_filenames(array( 'body' => $template_file, @@ -92,33 +91,43 @@ class phpbb_controller_helper } /** - * Generate a URL + * Generate a URL to a route * - * @param string $route The route to travel - * @param mixed $params String or array of additional url parameters + * @param string $route Name of the route to travel + * @param array $params String or array of additional url parameters * @param bool $is_amp Is url using & (true) or & (false) * @param string $session_id Possibility to use a custom session id instead of the global one * @return string The URL already passed through append_sid() */ - public function url($route, $params = false, $is_amp = true, $session_id = false) + public function route($route, array $params = array(), $is_amp = true, $session_id = false) { - $route_params = ''; - if (($route_delim = strpos($route, '?')) !== false) + $anchor = ''; + if (isset($params['#'])) { - $route_params = substr($route, $route_delim); - $route = substr($route, 0, $route_delim); + $anchor = '#' . $params['#']; + unset($params['#']); } + $url_generator = new UrlGenerator($this->route_collection, new RequestContext()); + $route_url = $url_generator->generate($route, $params); - $request_uri = $this->request->variable('REQUEST_URI', '', false, phpbb_request::SERVER); - $script_name = $this->request->variable('SCRIPT_NAME', '', false, phpbb_request::SERVER); + if (strpos($route_url, '/') === 0) + { + $route_url = substr($route_url, 1); + } - // If the app.php file is being used (no rewrite) keep it in the URL. - // Otherwise, don't include it. + if ($is_amp) + { + $route_url = str_replace(array('&', '&'), array('&', '&'), $route_url); + } + + // If enable_mod_rewrite is false, we need to include app.php $route_prefix = $this->phpbb_root_path; - $parts = explode('/', $script_name); - $route_prefix .= strpos($request_uri, $script_name) === 0 ? array_pop($parts) . '/' : ''; + if (empty($this->config['enable_mod_rewrite'])) + { + $route_prefix .= 'app.' . $this->php_ext . '/'; + } - return append_sid($route_prefix . "$route" . $route_params, $params, $is_amp, $session_id); + return append_sid($route_prefix . $route_url . $anchor, false, $is_amp, $session_id); } /** diff --git a/phpBB/phpbb/controller/provider.php b/phpBB/phpbb/controller/provider.php index b2a5b9f6b2..9df8130210 100644 --- a/phpBB/phpbb/controller/provider.php +++ b/phpBB/phpbb/controller/provider.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\controller; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Loader\YamlFileLoader; @@ -23,60 +17,67 @@ use Symfony\Component\Config\FileLocator; * Controller interface * @package phpBB3 */ -class phpbb_controller_provider +class provider { /** * YAML file(s) containing route information * @var array */ - protected $routing_paths; + protected $routing_files; + + /** + * Collection of the routes in phpBB and all found extensions + * @var RouteCollection + */ + protected $routes; /** * Construct method * - * @param array() $routing_paths Array of strings containing paths + * @param array() $routing_files Array of strings containing paths * to YAML files holding route information */ - public function __construct($routing_paths = array()) + public function __construct(\phpbb\extension\finder $finder = null, $routing_files = array()) { - $this->routing_paths = $routing_paths; + $this->routing_files = $routing_files; + + if ($finder) + { + // We hardcode the path to the core config directory + // because the finder cannot find it + $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder + ->directory('config') + ->suffix('routing.yml') + ->find() + )); + } } /** - * Locate paths containing routing files - * This sets an internal property but does not return the paths. + * Find a list of controllers and return it * - * @return The current instance of this object for method chaining + * @param string $base_path Base path to prepend to file paths + * @return null */ - public function import_paths_from_finder(phpbb_extension_finder $finder) + public function find($base_path = '') { - // We hardcode the path to the core config directory - // because the finder cannot find it - $this->routing_paths = array_merge(array('config'), array_map('dirname', array_keys($finder - ->directory('config') - ->prefix('routing') - ->suffix('yml') - ->find() - ))); + $this->routes = new RouteCollection; + foreach ($this->routing_files as $file_path) + { + $loader = new YamlFileLoader(new FileLocator($base_path)); + $this->routes->addCollection($loader->load($file_path)); + } return $this; } /** - * Get a list of controllers and return it + * Get the list of routes * - * @param string $base_path Base path to prepend to file paths - * @return array Array of controllers and their route information + * @return RouteCollection Get the route collection */ - public function find($base_path = '') + public function get_routes() { - $routes = new RouteCollection; - foreach ($this->routing_paths as $path) - { - $loader = new YamlFileLoader(new FileLocator($base_path . $path)); - $routes->addCollection($loader->load('routing.yml')); - } - - return $routes; + return $this->routes; } } diff --git a/phpBB/phpbb/controller/resolver.php b/phpBB/phpbb/controller/resolver.php index d772507261..233179e343 100644 --- a/phpBB/phpbb/controller/resolver.php +++ b/phpBB/phpbb/controller/resolver.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\controller; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -23,11 +17,11 @@ use Symfony\Component\HttpFoundation\Request; * Controller manager class * @package phpBB3 */ -class phpbb_controller_resolver implements ControllerResolverInterface +class resolver implements ControllerResolverInterface { /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; @@ -38,19 +32,19 @@ class phpbb_controller_resolver implements ControllerResolverInterface protected $container; /** - * phpbb_template object - * @var phpbb_template + * phpbb\template\template object + * @var phpbb\template\template */ protected $template; /** * Construct method * - * @param phpbb_user $user User Object + * @param \phpbb\user $user User Object * @param ContainerInterface $container ContainerInterface object - * @param phpbb_template $template + * @param \phpbb\template\template $template */ - public function __construct(phpbb_user $user, ContainerInterface $container, phpbb_template $template = null) + public function __construct(\phpbb\user $user, ContainerInterface $container, \phpbb\template\template $template = null) { $this->user = $user; $this->container = $container; @@ -62,7 +56,7 @@ class phpbb_controller_resolver implements ControllerResolverInterface * * @param Symfony\Component\HttpFoundation\Request $request Symfony Request object * @return bool|Callable Callable or false - * @throws phpbb_controller_exception + * @throws \phpbb\controller\exception */ public function getController(Request $request) { @@ -70,20 +64,20 @@ class phpbb_controller_resolver implements ControllerResolverInterface if (!$controller) { - throw new phpbb_controller_exception($this->user->lang['CONTROLLER_NOT_SPECIFIED']); + throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_NOT_SPECIFIED']); } // Require a method name along with the service name if (stripos($controller, ':') === false) { - throw new phpbb_controller_exception($this->user->lang['CONTROLLER_METHOD_NOT_SPECIFIED']); + throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_METHOD_NOT_SPECIFIED']); } list($service, $method) = explode(':', $controller); if (!$this->container->has($service)) { - throw new phpbb_controller_exception($this->user->lang('CONTROLLER_SERVICE_UNDEFINED', $service)); + throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_SERVICE_UNDEFINED', $service)); } $controller_object = $this->container->get($service); @@ -93,12 +87,12 @@ class phpbb_controller_resolver implements ControllerResolverInterface * the style paths for the extension (the ext author can change them * if necessary). */ - $controller_dir = explode('_', get_class($controller_object)); + $controller_dir = explode('\\', get_class($controller_object)); - // 0 phpbb, 1 ext, 2 vendor, 3 extension name, ... - if (!is_null($this->template) && isset($controller_dir[3]) && $controller_dir[1] === 'ext') + // 0 vendor, 1 extension name, ... + if (!is_null($this->template) && isset($controller_dir[1])) { - $controller_style_dir = 'ext/' . $controller_dir[2] . '/' . $controller_dir[3] . '/styles'; + $controller_style_dir = 'ext/' . $controller_dir[0] . '/' . $controller_dir[1] . '/styles'; if (is_dir($controller_style_dir)) { @@ -118,13 +112,13 @@ class phpbb_controller_resolver implements ControllerResolverInterface * @param Symfony\Component\HttpFoundation\Request $request Symfony Request object * @param mixed $controller A callable (controller class, method) * @return bool False - * @throws phpbb_controller_exception + * @throws \phpbb\controller\exception */ public function getArguments(Request $request, $controller) { // At this point, $controller contains the object and method name list($object, $method) = $controller; - $mirror = new ReflectionMethod($object, $method); + $mirror = new \ReflectionMethod($object, $method); $arguments = array(); $parameters = $mirror->getParameters(); @@ -145,7 +139,7 @@ class phpbb_controller_resolver implements ControllerResolverInterface } else { - throw new phpbb_controller_exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); + throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); } } diff --git a/phpBB/phpbb/cron/manager.php b/phpBB/phpbb/cron/manager.php index 84c9650830..b6af07aff7 100644 --- a/phpBB/phpbb/cron/manager.php +++ b/phpBB/phpbb/cron/manager.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron; /** * Cron manager class. @@ -22,10 +16,10 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_manager +class manager { /** - * Set of phpbb_cron_task_wrapper objects. + * Set of \phpbb\cron\task\wrapper objects. * Array holding all tasks that have been found. * * @var array @@ -52,7 +46,7 @@ class phpbb_cron_manager * Loads tasks given by name, wraps them * and puts them into $this->tasks. * - * @param array|Traversable $tasks Array of instances of phpbb_cron_task + * @param array|Traversable $tasks Array of instances of \phpbb\cron\task\task * * @return null */ @@ -71,7 +65,7 @@ class phpbb_cron_manager * * If no tasks are ready, null is returned. * - * @return phpbb_cron_task_wrapper|null + * @return \phpbb\cron\task\wrapper|null */ public function find_one_ready_task() { @@ -88,7 +82,7 @@ class phpbb_cron_manager /** * Finds all tasks that are ready to run. * - * @return array List of tasks which are ready to run (wrapped in phpbb_cron_task_wrapper). + * @return array List of tasks which are ready to run (wrapped in \phpbb\cron\task\wrapper). */ public function find_all_ready_tasks() { @@ -111,7 +105,7 @@ class phpbb_cron_manager * Web runner uses this method to resolve names to tasks. * * @param string $name Name of the task to look up. - * @return phpbb_cron_task A task corresponding to the given name, or null. + * @return \phpbb\cron\task\task A task corresponding to the given name, or null. */ public function find_task($name) { @@ -126,13 +120,13 @@ class phpbb_cron_manager } /** - * Wraps a task inside an instance of phpbb_cron_task_wrapper. + * Wraps a task inside an instance of \phpbb\cron\task\wrapper. * - * @param phpbb_cron_task $task The task. - * @return phpbb_cron_task_wrapper The wrapped task. + * @param \phpbb\cron\task\task $task The task. + * @return \phpbb\cron\task\wrapper The wrapped task. */ - public function wrap_task(phpbb_cron_task $task) + public function wrap_task(\phpbb\cron\task\task $task) { - return new phpbb_cron_task_wrapper($task, $this->phpbb_root_path, $this->php_ext); + return new \phpbb\cron\task\wrapper($task, $this->phpbb_root_path, $this->php_ext); } } diff --git a/phpBB/phpbb/cron/task/base.php b/phpBB/phpbb/cron/task/base.php index 94a2f267b4..63f0407bcd 100644 --- a/phpBB/phpbb/cron/task/base.php +++ b/phpBB/phpbb/cron/task/base.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task; /** * Cron task base class. Provides sensible defaults for cron tasks @@ -26,7 +20,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -abstract class phpbb_cron_task_base implements phpbb_cron_task +abstract class base implements \phpbb\cron\task\task { private $name; diff --git a/phpBB/phpbb/cron/task/core/prune_all_forums.php b/phpBB/phpbb/cron/task/core/prune_all_forums.php index 2c5d38cec0..36a551394a 100644 --- a/phpBB/phpbb/cron/task/core/prune_all_forums.php +++ b/phpBB/phpbb/cron/task/core/prune_all_forums.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Prune all forums cron task. @@ -24,7 +18,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_task_core_prune_all_forums extends phpbb_cron_task_base +class prune_all_forums extends \phpbb\cron\task\base { protected $phpbb_root_path; protected $php_ext; @@ -36,10 +30,10 @@ class phpbb_cron_task_core_prune_all_forums extends phpbb_cron_task_base * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_config $config The config - * @param phpbb_db_driver $db The db connection + * @param \phpbb\config\config $config The config + * @param \phpbb\db\driver\driver_interface $db The db connection */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; diff --git a/phpBB/phpbb/cron/task/core/prune_forum.php b/phpBB/phpbb/cron/task/core/prune_forum.php index e3c497f072..542d75e5b9 100644 --- a/phpBB/phpbb/cron/task/core/prune_forum.php +++ b/phpBB/phpbb/cron/task/core/prune_forum.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Prune one forum cron task. @@ -24,7 +18,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements phpbb_cron_task_parametrized +class prune_forum extends \phpbb\cron\task\base implements \phpbb\cron\task\parametrized { protected $phpbb_root_path; protected $php_ext; @@ -46,10 +40,10 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_config $config The config - * @param phpbb_db_driver $db The db connection + * @param \phpbb\config\config $config The config + * @param \phpbb\db\driver\driver_interface $db The db connection */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -132,15 +126,15 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p /** * Parses parameters found in $request, which is an instance of - * phpbb_request_interface. + * \phpbb\request\request_interface. * * It is expected to have a key f whose value is id of the forum to be pruned. * - * @param phpbb_request_interface $request Request object. + * @param \phpbb\request\request_interface $request Request object. * * @return null */ - public function parse_parameters(phpbb_request_interface $request) + public function parse_parameters(\phpbb\request\request_interface $request) { $this->forum_data = null; if ($request->is_set('f')) diff --git a/phpBB/phpbb/cron/task/core/prune_notifications.php b/phpBB/phpbb/cron/task/core/prune_notifications.php new file mode 100644 index 0000000000..9f67c54e1c --- /dev/null +++ b/phpBB/phpbb/cron/task/core/prune_notifications.php @@ -0,0 +1,59 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\cron\task\core; + +/** +* Prune notifications cron task. +* +* @package phpBB3 +*/ +class prune_notifications extends \phpbb\cron\task\base +{ + protected $config; + protected $notification_manager; + + /** + * Constructor. + * + * @param \phpbb\config\config $config The config + * @param \phpbb\notification\manager $notification_manager Notification manager + */ + public function __construct(\phpbb\config\config $config, \phpbb\notification\manager $notification_manager) + { + $this->config = $config; + $this->notification_manager = $notification_manager; + } + + /** + * {@inheritdoc} + */ + public function run() + { + // time minus expire days in seconds + $timestamp = time() - ($this->config['read_notification_expire_days'] * 60 * 60 * 24); + $this->notification_manager->prune_notifications($timestamp); + } + + /** + * {@inheritdoc} + */ + public function is_runnable() + { + return (bool) $this->config['read_notification_expire_days']; + } + + /** + * {@inheritdoc} + */ + public function should_run() + { + return $this->config['read_notification_last_gc'] < time() - $this->config['read_notification_gc']; + } +} diff --git a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php new file mode 100644 index 0000000000..b30e665a87 --- /dev/null +++ b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php @@ -0,0 +1,191 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\cron\task\core; + +/** +* Prune one forum of its shadow topics cron task. +* +* It is intended to be used when cron is invoked via web. +* This task can decide whether it should be run using data obtained by viewforum +* code, without making additional database queries. +* +* @package phpBB3 +*/ +class prune_shadow_topics extends \phpbb\cron\task\base implements \phpbb\cron\task\parametrized +{ + protected $phpbb_root_path; + protected $php_ext; + protected $config; + protected $db; + protected $log; + + /** + * If $forum_data is given, it is assumed to contain necessary information + * about a single forum that is to be pruned. + * + * If $forum_data is not given, forum id will be retrieved via request_var + * and a database query will be performed to load the necessary information + * about the forum. + */ + protected $forum_data; + + /** + * Constructor. + * + * @param string $phpbb_root_path The root path + * @param string $php_ext The PHP extension + * @param \phpbb\config\config $config The config + * @param \phpbb\db\driver\driver $db The db connection + * @param \phpbb\log\log $log The phpBB log system + */ + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\log\log $log) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->config = $config; + $this->db = $db; + $this->log = $log; + } + + /** + * Manually set forum data. + * + * @param array $forum_data Information about a forum to be pruned. + */ + public function set_forum_data($forum_data) + { + $this->forum_data = $forum_data; + } + + /** + * Runs this cron task. + * + * @return null + */ + public function run() + { + if (!function_exists('auto_prune')) + { + include($this->phpbb_root_path . 'includes/functions_admin.' . $this->php_ext); + } + + if ($this->forum_data['prune_shadow_days']) + { + $this->auto_prune_shadow_topics($this->forum_data['forum_id'], 'shadow', $this->forum_data['forum_flags'], $this->forum_data['prune_shadow_days'], $this->forum_data['prune_shadow_freq']); + } + } + + /** + * Returns whether this cron task can run, given current board configuration. + * + * This cron task will not run when system cron is utilised, as in + * such cases prune_all_forums task would run instead. + * + * Additionally, this task must be given the forum data, either via + * the constructor or parse_parameters method. + * + * @return bool + */ + public function is_runnable() + { + return !$this->config['use_system_cron'] && $this->forum_data; + } + + /** + * Returns whether this cron task should run now, because enough time + * has passed since it was last run. + * + * Forum pruning interval is specified in the forum data. + * + * @return bool + */ + public function should_run() + { + return $this->forum_data['enable_shadow_prune'] && $this->forum_data['prune_shadow_next'] < time(); + } + + /** + * Returns parameters of this cron task as an array. + * The array has one key, f, whose value is id of the forum to be pruned. + * + * @return array + */ + public function get_parameters() + { + return array('f' => $this->forum_data['forum_id']); + } + + /** + * Parses parameters found in $request, which is an instance of + * \phpbb\request\request_interface. + * + * It is expected to have a key f whose value is id of the forum to be pruned. + * + * @param \phpbb\request\request_interface $request Request object. + * + * @return null + */ + public function parse_parameters(\phpbb\request\request_interface $request) + { + $this->forum_data = null; + if ($request->is_set('f')) + { + $forum_id = $request->variable('f', 0); + + $sql = 'SELECT forum_id, prune_shadow_next, enable_shadow_prune, prune_shadow_days, forum_flags, prune_shadow_freq + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if ($row) + { + $this->forum_data = $row; + } + } + } + + /** + * Automatically prune shadow topics + * Based on fuunction auto_prune() + * @param int $forum_id Forum ID of forum that should be pruned + * @param string $prune_mode Prune mode + * @param int $prune_flags Prune flags + * @param int $prune_freq Prune frequency + * @return null + */ + protected function auto_prune_shadow_topics($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq) + { + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $this->db->sql_query($sql, 3600); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if ($row) + { + $prune_date = time() - ($prune_days * 86400); + $next_prune = time() + ($prune_freq * 86400); + + prune($forum_id, $prune_mode, $prune_date, $prune_flags, true); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET prune_shadow_next = $next_prune + WHERE forum_id = $forum_id"; + $this->db->sql_query($sql); + + $this->log->add('admin', 'LOG_PRUNE_SHADOW', $row['forum_name']); + } + + return; + } +} diff --git a/phpBB/phpbb/cron/task/core/queue.php b/phpBB/phpbb/cron/task/core/queue.php index 732f9c6bea..cd799b8024 100644 --- a/phpBB/phpbb/cron/task/core/queue.php +++ b/phpBB/phpbb/cron/task/core/queue.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Queue cron task. Sends email and jabber messages queued by other scripts. * * @package phpBB3 */ -class phpbb_cron_task_core_queue extends phpbb_cron_task_base +class queue extends \phpbb\cron\task\base { protected $phpbb_root_path; protected $php_ext; @@ -31,9 +25,9 @@ class phpbb_cron_task_core_queue extends phpbb_cron_task_base * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_config $config The config + * @param \phpbb\config\config $config The config */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -51,7 +45,7 @@ class phpbb_cron_task_core_queue extends phpbb_cron_task_base { include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); } - $queue = new queue(); + $queue = new \queue(); $queue->process(); } diff --git a/phpBB/phpbb/cron/task/core/tidy_cache.php b/phpBB/phpbb/cron/task/core/tidy_cache.php index 16a45dae7c..a94a85db53 100644 --- a/phpBB/phpbb/cron/task/core/tidy_cache.php +++ b/phpBB/phpbb/cron/task/core/tidy_cache.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Tidy cache cron task. * * @package phpBB3 */ -class phpbb_cron_task_core_tidy_cache extends phpbb_cron_task_base +class tidy_cache extends \phpbb\cron\task\base { protected $config; protected $cache; @@ -28,10 +22,10 @@ class phpbb_cron_task_core_tidy_cache extends phpbb_cron_task_base /** * Constructor. * - * @param phpbb_config $config The config - * @param phpbb_cache_driver_interface $cache The cache driver + * @param \phpbb\config\config $config The config + * @param \phpbb\cache\driver\driver_interface $cache The cache driver */ - public function __construct(phpbb_config $config, phpbb_cache_driver_interface $cache) + public function __construct(\phpbb\config\config $config, \phpbb\cache\driver\driver_interface $cache) { $this->config = $config; $this->cache = $cache; diff --git a/phpBB/phpbb/cron/task/core/tidy_database.php b/phpBB/phpbb/cron/task/core/tidy_database.php index b882e7b500..f712a5047c 100644 --- a/phpBB/phpbb/cron/task/core/tidy_database.php +++ b/phpBB/phpbb/cron/task/core/tidy_database.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Tidy database cron task. * * @package phpBB3 */ -class phpbb_cron_task_core_tidy_database extends phpbb_cron_task_base +class tidy_database extends \phpbb\cron\task\base { protected $phpbb_root_path; protected $php_ext; @@ -31,9 +25,9 @@ class phpbb_cron_task_core_tidy_database extends phpbb_cron_task_base * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_config $config The config + * @param \phpbb\config\config $config The config */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; diff --git a/phpBB/phpbb/cron/task/core/tidy_plupload.php b/phpBB/phpbb/cron/task/core/tidy_plupload.php new file mode 100644 index 0000000000..5a98e0bd7b --- /dev/null +++ b/phpBB/phpbb/cron/task/core/tidy_plupload.php @@ -0,0 +1,116 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\cron\task\core; + +/** +* Cron task for cleaning plupload's temporary upload directory. +* +* @package phpBB3 +*/ +class tidy_plupload extends \phpbb\cron\task\base +{ + /** + * How old a file must be (in seconds) before it is deleted. + * @var int + */ + protected $max_file_age = 86400; + + /** + * How often we run the cron (in seconds). + * @var int + */ + protected $cron_frequency = 86400; + + /** + * phpBB root path + * @var string + */ + protected $phpbb_root_path; + + /** + * Config object + * @var \phpbb\config\config + */ + protected $config; + + /** + * Directory where plupload stores temporary files. + * @var string + */ + protected $plupload_upload_path; + + /** + * Constructor. + * + * @param string $phpbb_root_path The root path + * @param \phpbb\config\config $config The config + */ + public function __construct($phpbb_root_path, \phpbb\config\config $config) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->config = $config; + + $this->plupload_upload_path = $this->phpbb_root_path . $this->config['upload_path'] . '/plupload'; + } + + /** + * {@inheritDoc} + */ + public function run() + { + // Remove old temporary file (perhaps failed uploads?) + $last_valid_timestamp = time() - $this->max_file_age; + try + { + $iterator = new \DirectoryIterator($this->plupload_upload_path); + foreach ($iterator as $file) + { + if (strpos($file->getBasename(), $this->config['plupload_salt']) !== 0) + { + // Skip over any non-plupload files. + continue; + } + + if ($file->getMTime() < $last_valid_timestamp) + { + @unlink($file->getPathname()); + } + } + } + catch (\UnexpectedValueException $e) + { + add_log( + 'critical', + 'LOG_PLUPLOAD_TIDY_FAILED', + $this->plupload_upload_path, + $e->getMessage(), + $e->getTraceAsString() + ); + } + + $this->config->set('plupload_last_gc', time(), true); + } + + /** + * {@inheritDoc} + */ + public function is_runnable() + { + return !empty($this->config['plupload_salt']) && is_dir($this->plupload_upload_path); + } + + /** + * {@inheritDoc} + */ + public function should_run() + { + return $this->config['plupload_last_gc'] < time() - $this->cron_frequency; + } +} diff --git a/phpBB/phpbb/cron/task/core/tidy_search.php b/phpBB/phpbb/cron/task/core/tidy_search.php index a3d5b7dbd2..eac6aa0a36 100644 --- a/phpBB/phpbb/cron/task/core/tidy_search.php +++ b/phpBB/phpbb/cron/task/core/tidy_search.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Tidy search cron task. @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base +class tidy_search extends \phpbb\cron\task\base { protected $phpbb_root_path; protected $php_ext; @@ -36,12 +30,12 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_auth $auth The auth - * @param phpbb_config $config The config - * @param phpbb_db_driver $db The db connection - * @param phpbb_user $user The user + * @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 */ - public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, phpbb_db_driver $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) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; diff --git a/phpBB/phpbb/cron/task/core/tidy_sessions.php b/phpBB/phpbb/cron/task/core/tidy_sessions.php index 95f55235c9..68094af1f7 100644 --- a/phpBB/phpbb/cron/task/core/tidy_sessions.php +++ b/phpBB/phpbb/cron/task/core/tidy_sessions.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Tidy sessions cron task. * * @package phpBB3 */ -class phpbb_cron_task_core_tidy_sessions extends phpbb_cron_task_base +class tidy_sessions extends \phpbb\cron\task\base { protected $config; protected $user; @@ -28,10 +22,10 @@ class phpbb_cron_task_core_tidy_sessions extends phpbb_cron_task_base /** * Constructor. * - * @param phpbb_config $config The config - * @param phpbb_user $user The user + * @param \phpbb\config\config $config The config + * @param \phpbb\user $user The user */ - public function __construct(phpbb_config $config, phpbb_user $user) + public function __construct(\phpbb\config\config $config, \phpbb\user $user) { $this->config = $config; $this->user = $user; diff --git a/phpBB/phpbb/cron/task/core/tidy_warnings.php b/phpBB/phpbb/cron/task/core/tidy_warnings.php index 2a7798e56e..a0ff23fc57 100644 --- a/phpBB/phpbb/cron/task/core/tidy_warnings.php +++ b/phpBB/phpbb/cron/task/core/tidy_warnings.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task\core; /** * Tidy warnings cron task. @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_task_core_tidy_warnings extends phpbb_cron_task_base +class tidy_warnings extends \phpbb\cron\task\base { protected $phpbb_root_path; protected $php_ext; @@ -33,9 +27,9 @@ class phpbb_cron_task_core_tidy_warnings extends phpbb_cron_task_base * * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension - * @param phpbb_config $config The config + * @param \phpbb\config\config $config The config */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; diff --git a/phpBB/phpbb/cron/task/parametrized.php b/phpBB/phpbb/cron/task/parametrized.php index 5f0e46eafc..1aeead0399 100644 --- a/phpBB/phpbb/cron/task/parametrized.php +++ b/phpBB/phpbb/cron/task/parametrized.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task; /** * Parametrized cron task interface. @@ -26,7 +20,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -interface phpbb_cron_task_parametrized extends phpbb_cron_task +interface parametrized extends \phpbb\cron\task\task { /** * Returns parameters of this cron task as an array. @@ -39,14 +33,14 @@ interface phpbb_cron_task_parametrized extends phpbb_cron_task /** * Parses parameters found in $request, which is an instance of - * phpbb_request_interface. + * \phpbb\request\request_interface. * * $request contains user input and must not be trusted. * Cron task must validate all data before using it. * - * @param phpbb_request_interface $request Request object. + * @param \phpbb\request\request_interface $request Request object. * * @return null */ - public function parse_parameters(phpbb_request_interface $request); + public function parse_parameters(\phpbb\request\request_interface $request); } diff --git a/phpBB/phpbb/cron/task/task.php b/phpBB/phpbb/cron/task/task.php index 2d585df96d..3ce3de9598 100644 --- a/phpBB/phpbb/cron/task/task.php +++ b/phpBB/phpbb/cron/task/task.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task; /** * Cron task interface * @package phpBB3 */ -interface phpbb_cron_task +interface task { /** * Returns the name of the task. diff --git a/phpBB/phpbb/cron/task/wrapper.php b/phpBB/phpbb/cron/task/wrapper.php index 386fb5b383..fc3f897206 100644 --- a/phpBB/phpbb/cron/task/wrapper.php +++ b/phpBB/phpbb/cron/task/wrapper.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\cron\task; /** * Cron task wrapper class. @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_cron_task_wrapper +class wrapper { protected $task; protected $phpbb_root_path; @@ -32,9 +26,9 @@ class phpbb_cron_task_wrapper * * Wraps a task $task, which must implement cron_task interface. * - * @param phpbb_cron_task $task The cron task to wrap. + * @param \phpbb\cron\task\task $task The cron task to wrap. */ - public function __construct(phpbb_cron_task $task, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\cron\task\task $task, $phpbb_root_path, $php_ext) { $this->task = $task; $this->phpbb_root_path = $phpbb_root_path; @@ -51,7 +45,7 @@ class phpbb_cron_task_wrapper */ public function is_parametrized() { - return $this->task instanceof phpbb_cron_task_parametrized; + return $this->task instanceof \phpbb\cron\task\parametrized; } /** diff --git a/phpBB/phpbb/datetime.php b/phpBB/phpbb/datetime.php index 3c6d4971b9..dfa21976e0 100644 --- a/phpBB/phpbb/datetime.php +++ b/phpBB/phpbb/datetime.php @@ -6,11 +6,13 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 */ +namespace phpbb; + /** * phpBB custom extensions to the PHP DateTime class * This handles the relative formats phpBB employs */ -class phpbb_datetime extends DateTime +class datetime extends \DateTime { /** * String used to wrap the date segment which should be replaced by today/tomorrow/yesterday @@ -28,14 +30,14 @@ class phpbb_datetime extends DateTime static protected $format_cache = array(); /** - * Constructs a new instance of phpbb_datetime, expanded to include an argument to inject + * Constructs a new instance of \phpbb\datetime, expanded to include an argument to inject * the user context and modify the timezone to the users selected timezone if one is not set. * * @param string $time String in a format accepted by strtotime(). * @param DateTimeZone $timezone Time zone of the time. * @param user User object for context. */ - public function __construct($user, $time = 'now', DateTimeZone $timezone = null) + public function __construct($user, $time = 'now', \DateTimeZone $timezone = null) { $this->user = $user; $timezone = $timezone ?: $this->user->timezone; @@ -72,8 +74,8 @@ class phpbb_datetime extends DateTime * finally check that relative dates are supported by the language pack */ if ($delta <= 3600 && $delta > -60 && - ($delta >= -5 || (($now_ts / 60) % 60) == (($timestamp / 60) % 60)) - && isset($this->user->lang['datetime']['AGO'])) + ($delta >= -5 || (($now_ts / 60) % 60) == (($timestamp / 60) % 60)) + && isset($this->user->lang['datetime']['AGO'])) { return $this->user->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60))); } diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 08c966c07a..85d160c80e 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Database Abstraction Layer * @package dbal */ -class phpbb_db_driver +abstract class driver implements driver_interface { var $db_connect_id; var $query_result; @@ -82,7 +76,7 @@ class phpbb_db_driver // Fill default sql layer based on the class being called. // This can be changed by the specified layer itself later if needed. - $this->sql_layer = substr(get_class($this), strlen('phpbb_db_driver_')); + $this->sql_layer = substr(get_class($this), strlen('phpbb\db\driver\\')); // Do not change this please! This variable is used to easy the use of it - and is hardcoded. $this->any_char = chr(0) . '%'; @@ -90,7 +84,7 @@ class phpbb_db_driver } /** - * return on error or display error message + * {@inheritDoc} */ function sql_return_on_error($fail = false) { @@ -101,7 +95,7 @@ class phpbb_db_driver } /** - * Return number of sql queries and cached sql queries used + * {@inheritDoc} */ function sql_num_queries($cached = false) { @@ -109,7 +103,7 @@ class phpbb_db_driver } /** - * Add to query count + * {@inheritDoc} */ function sql_add_num_queries($cached = false) { @@ -119,7 +113,7 @@ class phpbb_db_driver } /** - * DBAL garbage collection, close sql connection + * {@inheritDoc} */ function sql_close() { @@ -152,8 +146,7 @@ class phpbb_db_driver } /** - * Build LIMIT query - * Doing some validation here. + * {@inheritDoc} */ function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) { @@ -170,7 +163,7 @@ class phpbb_db_driver } /** - * Fetch all rows + * {@inheritDoc} */ function sql_fetchrowset($query_id = false) { @@ -194,8 +187,7 @@ class phpbb_db_driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -237,8 +229,7 @@ class phpbb_db_driver } /** - * Fetch field - * if rownum is false, the current row is used, else it is pointing to the row (zero-based) + * {@inheritDoc} */ function sql_fetchfield($field, $rownum = false, $query_id = false) { @@ -269,11 +260,7 @@ class phpbb_db_driver } /** - * Correctly adjust LIKE expression for special characters - * Some DBMS are handling them in a different way - * - * @param string $expression The expression to use. Every wildcard is escaped, except $this->any_char and $this->one_char - * @return string LIKE expression including the keyword! + * {@inheritDoc} */ function sql_like_expression($expression) { @@ -284,14 +271,7 @@ class phpbb_db_driver } /** - * Build a case expression - * - * Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database! - * - * @param string $condition The condition which must be true, to use action_true rather then action_else - * @param string $action_true SQL expression that is used, if the condition is true - * @param string $action_else SQL expression that is used, if the condition is false, optional - * @return string CASE expression including the condition and statements + * {@inheritDoc} */ public function sql_case($condition, $action_true, $action_false = false) { @@ -303,11 +283,7 @@ class phpbb_db_driver } /** - * Build a concatenated expression - * - * @param string $expr1 Base SQL expression where we append the second one - * @param string $expr2 SQL expression that is appended to the first expression - * @return string Concatenated string + * {@inheritDoc} */ public function sql_concatenate($expr1, $expr2) { @@ -315,9 +291,7 @@ class phpbb_db_driver } /** - * Returns whether results of a query need to be buffered to run a transaction while iterating over them. - * - * @return bool Whether buffering is required. + * {@inheritDoc} */ function sql_buffer_nested_transactions() { @@ -325,15 +299,14 @@ class phpbb_db_driver } /** - * SQL Transaction - * @access private + * {@inheritDoc} */ function sql_transaction($status = 'begin') { switch ($status) { case 'begin': - // If we are within a transaction we will not open another one, but enclose the current one to not loose data (prevening auto commit) + // If we are within a transaction we will not open another one, but enclose the current one to not loose data (preventing auto commit) if ($this->transaction) { $this->transactions++; @@ -351,14 +324,16 @@ class phpbb_db_driver break; case 'commit': - // If there was a previously opened transaction we do not commit yet... but count back the number of inner transactions + // If there was a previously opened transaction we do not commit yet... + // but count back the number of inner transactions if ($this->transaction && $this->transactions) { $this->transactions--; return true; } - // Check if there is a transaction (no transaction can happen if there was an error, with a combined rollback and error returning enabled) + // Check if there is a transaction (no transaction can happen if + // there was an error, with a combined rollback and error returning enabled) // This implies we have transaction always set for autocommit db's if (!$this->transaction) { @@ -391,11 +366,7 @@ class phpbb_db_driver } /** - * Build sql statement from array for insert/update/select statements - * - * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT - * + * {@inheritDoc} */ function sql_build_array($query, $assoc_ary = false) { @@ -429,7 +400,7 @@ class phpbb_db_driver { trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR); } - else if ($query == 'UPDATE' || $query == 'SELECT') + else if ($query == 'UPDATE' || $query == 'SELECT' || $query == 'DELETE') { $values = array(); foreach ($assoc_ary as $key => $var) @@ -443,14 +414,7 @@ class phpbb_db_driver } /** - * Build IN or NOT IN sql comparison string, uses <> or = on single element - * arrays to improve comparison speed - * - * @access public - * @param string $field name of the sql column that shall be compared - * @param array $array array of values that are allowed (IN) or not allowed (NOT IN) - * @param bool $negate true for NOT IN (), false for IN () (default) - * @param bool $allow_empty_set If true, allow $array to be empty, this function will return 1=1 or 1=0 then. Default to false. + * {@inheritDoc} */ function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) { @@ -495,12 +459,7 @@ class phpbb_db_driver } /** - * Run binary AND operator on DB column. - * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}" - * - * @param string $column_name The column name to use - * @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29 - * @param string $compare Any custom SQL code after the check (for example "= 0") + * {@inheritDoc} */ function sql_bit_and($column_name, $bit, $compare = '') { @@ -513,12 +472,7 @@ class phpbb_db_driver } /** - * Run binary OR operator on DB column. - * Results in sql statement: "{$column_name} | (1 << {$bit}) {$compare}" - * - * @param string $column_name The column name to use - * @param int $bit The value to use for the OR operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29 - * @param string $compare Any custom SQL code after the check (for example "= 0") + * {@inheritDoc} */ function sql_bit_or($column_name, $bit, $compare = '') { @@ -531,10 +485,7 @@ class phpbb_db_driver } /** - * Returns SQL string to cast a string expression to an int. - * - * @param string $expression An expression evaluating to string - * @return string Expression returning an int + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -542,10 +493,7 @@ class phpbb_db_driver } /** - * Returns SQL string to cast an integer expression to a string. - * - * @param string $expression An expression evaluating to int - * @return string Expression returning a string + * {@inheritDoc} */ function cast_expr_to_string($expression) { @@ -553,11 +501,7 @@ class phpbb_db_driver } /** - * Run LOWER() on DB column of type text (i.e. neither varchar nor char). - * - * @param string $column_name The column name to use - * - * @return string A SQL statement like "LOWER($column_name)" + * {@inheritDoc} */ function sql_lower_text($column_name) { @@ -565,13 +509,7 @@ class phpbb_db_driver } /** - * Run more than one insert statement. - * - * @param string $table table name to run the statements on - * @param array $sql_ary multi-dimensional array holding the statement data. - * - * @return bool false if no statements were executed. - * @access public + * {@inheritDoc} */ function sql_multi_insert($table, $sql_ary) { @@ -643,9 +581,7 @@ class phpbb_db_driver } /** - * Build sql statement from array for select and select distinct statements - * - * Possible query values: SELECT, SELECT_DISTINCT + * {@inheritDoc} */ function sql_build_query($query, $array) { @@ -748,7 +684,7 @@ class phpbb_db_driver } /** - * display sql error page + * {@inheritDoc} */ function sql_error($sql = '') { @@ -818,11 +754,11 @@ class phpbb_db_driver } /** - * Explain queries + * {@inheritDoc} */ function sql_report($mode, $query = '') { - global $cache, $starttime, $phpbb_root_path, $phpbb_admin_path, $user; + global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper, $user; global $request; if (is_object($request) && !$request->variable('explain', false)) @@ -852,7 +788,7 @@ class phpbb_db_driver <head> <meta charset="utf-8"> <title>SQL Report</title> - <link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" /> + <link href="' . htmlspecialchars($phpbb_path_helper->update_web_root_path($phpbb_root_path) . $phpbb_path_helper->get_adm_relative_path()) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" /> </head> <body id="errorpage"> <div id="wrap"> @@ -1008,14 +944,7 @@ class phpbb_db_driver } /** - * Gets the estimated number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Number of rows in $table_name. - * Prefixed with ~ if estimated (otherwise exact). - * - * @access public + * {@inheritDoc} */ function get_estimated_row_count($table_name) { @@ -1023,13 +952,7 @@ class phpbb_db_driver } /** - * Gets the exact number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Exact number of rows in $table_name. - * - * @access public + * {@inheritDoc} */ function get_row_count($table_name) { diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php new file mode 100644 index 0000000000..a9051616c9 --- /dev/null +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -0,0 +1,355 @@ +<?php +/** +* +* @package dbal +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\driver; + +interface driver_interface +{ + /** + * Gets the exact number of rows in a specified table. + * + * @param string $table_name Table name + * @return string Exact number of rows in $table_name. + */ + public function get_row_count($table_name); + + /** + * Gets the estimated number of rows in a specified table. + * + * @param string $table_name Table name + * @return string Number of rows in $table_name. + * Prefixed with ~ if estimated (otherwise exact). + */ + public function get_estimated_row_count($table_name); + + /** + * Run LOWER() on DB column of type text (i.e. neither varchar nor char). + * + * @param string $column_name The column name to use + * @return string A SQL statement like "LOWER($column_name)" + */ + public function sql_lower_text($column_name); + + /** + * Display sql error page + * + * @param string $sql The SQL query causing the error + * @return mixed Returns the full error message, if $this->return_on_error + * is set, null otherwise + */ + public function sql_error($sql = ''); + + /** + * Returns whether results of a query need to be buffered to run a + * transaction while iterating over them. + * + * @return bool Whether buffering is required. + */ + public function sql_buffer_nested_transactions(); + + /** + * Run binary OR operator on DB column. + * + * @param string $column_name The column name to use + * @param int $bit The value to use for the OR operator, + * will be converted to (1 << $bit). Is used by options, + * using the number schema... 0, 1, 2...29 + * @param string $compare Any custom SQL code after the check (e.g. "= 0") + * @return string A SQL statement like "$column | (1 << $bit) {$compare}" + */ + public function sql_bit_or($column_name, $bit, $compare = ''); + + /** + * Version information about used database + * + * @param bool $raw Only return the fetched sql_server_version + * @param bool $use_cache Is it safe to retrieve the value from the cache + * @return string sql server version + */ + public function sql_server_info($raw = false, $use_cache = true); + + /** + * Return on error or display error message + * + * @param bool $fail Should we return on errors, or stop + * @return null + */ + public function sql_return_on_error($fail = false); + + /** + * Build sql statement from an array + * + * @param string $query Should be on of the following strings: + * INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE + * @param array $assoc_ary Array with "column => value" pairs + * @return string A SQL statement like "c1 = 'a' AND c2 = 'b'" + */ + public function sql_build_array($query, $assoc_ary = array()); + + /** + * Fetch all rows + * + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed Nested array if the query had rows, false otherwise + */ + public function sql_fetchrowset($query_id = false); + + /** + * SQL Transaction + * + * @param string $status Should be one of the following strings: + * begin, commit, rollback + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_transaction($status = 'begin'); + + /** + * Build a concatenated expression + * + * @param string $expr1 Base SQL expression where we append the second one + * @param string $expr2 SQL expression that is appended to the first expression + * @return string Concatenated string + */ + public function sql_concatenate($expr1, $expr2); + + /** + * Build a case expression + * + * Note: The two statements action_true and action_false must have the same + * data type (int, vchar, ...) in the database! + * + * @param string $condition The condition which must be true, + * to use action_true rather then action_else + * @param string $action_true SQL expression that is used, if the condition is true + * @param mixed $action_false SQL expression that is used, if the condition is false + * @return string CASE expression including the condition and statements + */ + public function sql_case($condition, $action_true, $action_false = false); + + /** + * Build sql statement from array for select and select distinct statements + * + * Possible query values: SELECT, SELECT_DISTINCT + * + * @param string $query Should be one of: SELECT, SELECT_DISTINCT + * @param array $array Array with the query data: + * SELECT A comma imploded list of columns to select + * FROM Array with "table => alias" pairs, + * (alias can also be an array) + * Optional: LEFT_JOIN Array of join entries: + * FROM Table that should be joined + * ON Condition for the join + * Optional: WHERE Where SQL statement + * Optional: GROUP_BY Group by SQL statement + * Optional: ORDER_BY Order by SQL statement + * @return string A SQL statement ready for execution + */ + public function sql_build_query($query, $array); + + /** + * Fetch field + * if rownum is false, the current row is used, else it is pointing to the row (zero-based) + * + * @param string $field Name of the column + * @param mixed $rownum Row number, if false the current row will be used + * and the row curser will point to the next row + * Note: $rownum is 0 based + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed String value of the field in the selected row, + * false, if the row does not exist + */ + public function sql_fetchfield($field, $rownum = false, $query_id = false); + + /** + * Fetch current row + * + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed Array with the current row, + * false, if the row does not exist + */ + public function sql_fetchrow($query_id = false); + + /** + * Returns SQL string to cast a string expression to an int. + * + * @param string $expression An expression evaluating to string + * @return string Expression returning an int + */ + public function cast_expr_to_bigint($expression); + + /** + * Get last inserted id after insert statement + * + * @return string Autoincrement value of the last inserted row + */ + public function sql_nextid(); + + /** + * Add to query count + * + * @param bool $cached Is this query cached? + * @return null + */ + public function sql_add_num_queries($cached = false); + + /** + * Build LIMIT query + * + * @param string $query The SQL query to execute + * @param int $total The number of rows to select + * @param int $offset + * @param int $cache_ttl Either 0 to avoid caching or + * the time in seconds which the result shall be kept in cache + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0); + + /** + * Base query method + * + * @param string $query The SQL query to execute + * @param int $cache_ttl Either 0 to avoid caching or + * the time in seconds which the result shall be kept in cache + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_query($query = '', $cache_ttl = 0); + + /** + * Returns SQL string to cast an integer expression to a string. + * + * @param string $expression An expression evaluating to int + * @return string Expression returning a string + */ + public function cast_expr_to_string($expression); + + /** + * Connect to server + * + * @param string $sqlserver Address of the database server + * @param string $sqluser User name of the SQL user + * @param string $sqlpassword Password of the SQL user + * @param string $database Name of the database + * @param mixed $port Port of the database server + * @param bool $persistency + * @param bool $new_link Should a new connection be established + * @return mixed Connection ID on success, string error message otherwise + */ + public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false); + + /** + * Run binary AND operator on DB column. + * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}" + * + * @param string $column_name The column name to use + * @param int $bit The value to use for the AND operator, + * will be converted to (1 << $bit). Is used by + * options, using the number schema: 0, 1, 2...29 + * @param string $compare Any custom SQL code after the check (for example "= 0") + * @return string A SQL statement like: "{$column} & (1 << {$bit}) {$compare}" + */ + public function sql_bit_and($column_name, $bit, $compare = ''); + + /** + * Free sql result + * + * @param mixed $query_id Already executed query result, + * if false, the last query will be used. + * @return null + */ + public function sql_freeresult($query_id = false); + + /** + * Return number of sql queries and cached sql queries used + * + * @param bool $cached Should we return the number of cached or normal queries? + * @return int Number of queries that have been executed + */ + public function sql_num_queries($cached = false); + + /** + * Run more than one insert statement. + * + * @param string $table Table name to run the statements on + * @param array $sql_ary Multi-dimensional array holding the statement data + * @return bool false if no statements were executed. + */ + public function sql_multi_insert($table, $sql_ary); + + /** + * Return number of affected rows + * + * @return mixed Number of the affected rows by the last query + * false if no query has been run before + */ + public function sql_affectedrows(); + + /** + * DBAL garbage collection, close SQL connection + * + * @return mixed False if no connection was opened before, + * Server response otherwise + */ + public function sql_close(); + + /** + * Seek to given row number + * + * @param mixed $rownum Row number the curser should point to + * Note: $rownum is 0 based + * @param mixed $query_id ID of the query to set the row cursor on + * if false, the last query will be used. + * $query_id will then be set correctly + * @return bool False if something went wrong + */ + public function sql_rowseek($rownum, &$query_id); + + /** + * Escape string used in sql query + * + * @param string $msg String to be escaped + * @return string Escaped version of $msg + */ + public function sql_escape($msg); + + /** + * Correctly adjust LIKE expression for special characters + * Some DBMS are handling them in a different way + * + * @param string $expression The expression to use. Every wildcard is + * escaped, except $this->any_char and $this->one_char + * @return string A SQL statement like: "LIKE 'bertie_%'" + */ + public function sql_like_expression($expression); + + /** + * Explain queries + * + * @param string $mode Available modes: display, start, stop, + * add_select_row, fromcache, record_fromcache + * @param string $query The Query that should be explained + * @return mixed Either a full HTML page, boolean or null + */ + public function sql_report($mode, $query = ''); + + /** + * Build IN or NOT IN sql comparison string, uses <> or = on single element + * arrays to improve comparison speed + * + * @param string $field Name of the sql column that shall be compared + * @param array $array Array of values that are (not) allowed + * @param bool $negate true for NOT IN (), false for IN () + * @param bool $allow_empty_set If true, allow $array to be empty, + * this function will return 1=1 or 1=0 then. + * @return string A SQL statement like: "IN (1, 2, 3, 4)" or "= 1" + */ + public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false); +} diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index 787c28b812..a4967c7ffe 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Firebird/Interbase Database Abstraction Layer * Minimum Requirement is Firebird 2.1 * @package dbal */ -class phpbb_db_driver_firebird extends phpbb_db_driver +class firebird extends \phpbb\db\driver\driver { var $last_query_text = ''; var $service_handle = false; @@ -28,7 +22,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -85,10 +79,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache forced to false for Interbase - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -133,13 +124,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -303,7 +288,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -319,7 +304,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -357,7 +342,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -385,7 +370,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -396,7 +381,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -411,7 +396,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { @@ -447,7 +432,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -456,7 +441,7 @@ class phpbb_db_driver_firebird extends phpbb_db_driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_string($expression) { diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 89c2c2351b..588cd7a7e8 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -7,25 +7,19 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * MSSQL Database Abstraction Layer * Minimum Requirement is MSSQL 2000+ * @package dbal */ -class phpbb_db_driver_mssql extends phpbb_db_driver +class mssql extends \phpbb\db\driver\driver { var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -61,10 +55,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -130,13 +121,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -221,7 +206,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -229,7 +214,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -257,7 +242,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver { foreach ($row as $key => $value) { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; + $row[$key] = ($value === ' ' || $value === null) ? '' : $value; } } @@ -265,8 +250,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -286,7 +270,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -305,7 +289,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -316,14 +300,14 @@ class phpbb_db_driver_mssql extends phpbb_db_driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } - if (isset($this->open_queries[$query_id])) + if (isset($this->open_queries[(int) $query_id])) { - unset($this->open_queries[$query_id]); + unset($this->open_queries[(int) $query_id]); return @mssql_free_result($query_id); } @@ -331,7 +315,7 @@ class phpbb_db_driver_mssql extends phpbb_db_driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 56c111c871..1e3fb8235a 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * MSSQL Database Base Abstraction Layer * @package dbal */ -abstract class phpbb_db_driver_mssql_base extends phpbb_db_driver +abstract class mssql_base extends \phpbb\db\driver\driver { /** * {@inheritDoc} @@ -30,7 +24,7 @@ abstract class phpbb_db_driver_mssql_base extends phpbb_db_driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index a1d1a5d5dd..34b913dc8a 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Unified ODBC functions @@ -26,13 +20,13 @@ if (!defined('IN_PHPBB')) * * @package dbal */ -class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base +class mssql_odbc extends \phpbb\db\driver\mssql_base { var $last_query_text = ''; var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -89,10 +83,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -150,13 +141,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -242,7 +227,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -250,8 +235,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Fetch current row - * @note number of bytes returned depends on odbc.defaultlrl php.ini setting. If it is limited to 4K for example only 4K of data is returned max. + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -271,7 +255,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -292,7 +276,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -303,7 +287,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 28fc88298a..b449de2ae4 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -11,195 +11,20 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array - * and maintain our own cursor index into that array. - */ -class result_mssqlnative -{ - public function result_mssqlnative($queryresult = false) - { - $this->m_cursor = 0; - $this->m_rows = array(); - $this->m_num_fields = sqlsrv_num_fields($queryresult); - $this->m_field_meta = sqlsrv_field_metadata($queryresult); - - while ($row = sqlsrv_fetch_array($queryresult, SQLSRV_FETCH_ASSOC)) - { - if ($row !== null) - { - foreach($row as $k => $v) - { - if (is_object($v) && method_exists($v, 'format')) - { - $row[$k] = $v->format("Y-m-d\TH:i:s\Z"); - } - } - $this->m_rows[] = $row;//read results into memory, cursors are not supported - } - } - - $this->m_row_count = sizeof($this->m_rows); - } - - private function array_to_obj($array, &$obj) - { - foreach ($array as $key => $value) - { - if (is_array($value)) - { - $obj->$key = new stdClass(); - array_to_obj($value, $obj->$key); - } - else - { - $obj->$key = $value; - } - } - return $obj; - } - - public function fetch($mode = SQLSRV_FETCH_BOTH, $object_class = 'stdClass') - { - if ($this->m_cursor >= $this->m_row_count || $this->m_row_count == 0) - { - return false; - } - - $ret = false; - $arr_num = array(); - - if ($mode == SQLSRV_FETCH_NUMERIC || $mode == SQLSRV_FETCH_BOTH) - { - foreach($this->m_rows[$this->m_cursor] as $key => $value) - { - $arr_num[] = $value; - } - } - - switch ($mode) - { - case SQLSRV_FETCH_ASSOC: - $ret = $this->m_rows[$this->m_cursor]; - break; - case SQLSRV_FETCH_NUMERIC: - $ret = $arr_num; - break; - case 'OBJECT': - $ret = $this->array_to_obj($this->m_rows[$this->m_cursor], $o = new $object_class); - break; - case SQLSRV_FETCH_BOTH: - default: - $ret = $this->m_rows[$this->m_cursor] + $arr_num; - break; - } - $this->m_cursor++; - return $ret; - } - - public function get($pos, $fld) - { - return $this->m_rows[$pos][$fld]; - } - - public function num_rows() - { - return $this->m_row_count; - } - - public function seek($iRow) - { - $this->m_cursor = min($iRow, $this->m_row_count); - } - - public function num_fields() - { - return $this->m_num_fields; - } - - public function field_name($nr) - { - $arr_keys = array_keys($this->m_rows[0]); - return $arr_keys[$nr]; - } - - public function field_type($nr) - { - $i = 0; - $int_type = -1; - $str_type = ''; - - foreach ($this->m_field_meta as $meta) - { - if ($nr == $i) - { - $int_type = $meta['Type']; - break; - } - $i++; - } - - //http://msdn.microsoft.com/en-us/library/cc296183.aspx contains type table - switch ($int_type) - { - case SQLSRV_SQLTYPE_BIGINT: $str_type = 'bigint'; break; - case SQLSRV_SQLTYPE_BINARY: $str_type = 'binary'; break; - case SQLSRV_SQLTYPE_BIT: $str_type = 'bit'; break; - case SQLSRV_SQLTYPE_CHAR: $str_type = 'char'; break; - case SQLSRV_SQLTYPE_DATETIME: $str_type = 'datetime'; break; - case SQLSRV_SQLTYPE_DECIMAL/*($precision, $scale)*/: $str_type = 'decimal'; break; - case SQLSRV_SQLTYPE_FLOAT: $str_type = 'float'; break; - case SQLSRV_SQLTYPE_IMAGE: $str_type = 'image'; break; - case SQLSRV_SQLTYPE_INT: $str_type = 'int'; break; - case SQLSRV_SQLTYPE_MONEY: $str_type = 'money'; break; - case SQLSRV_SQLTYPE_NCHAR/*($charCount)*/: $str_type = 'nchar'; break; - case SQLSRV_SQLTYPE_NUMERIC/*($precision, $scale)*/: $str_type = 'numeric'; break; - case SQLSRV_SQLTYPE_NVARCHAR/*($charCount)*/: $str_type = 'nvarchar'; break; - case SQLSRV_SQLTYPE_NTEXT: $str_type = 'ntext'; break; - case SQLSRV_SQLTYPE_REAL: $str_type = 'real'; break; - case SQLSRV_SQLTYPE_SMALLDATETIME: $str_type = 'smalldatetime'; break; - case SQLSRV_SQLTYPE_SMALLINT: $str_type = 'smallint'; break; - case SQLSRV_SQLTYPE_SMALLMONEY: $str_type = 'smallmoney'; break; - case SQLSRV_SQLTYPE_TEXT: $str_type = 'text'; break; - case SQLSRV_SQLTYPE_TIMESTAMP: $str_type = 'timestamp'; break; - case SQLSRV_SQLTYPE_TINYINT: $str_type = 'tinyint'; break; - case SQLSRV_SQLTYPE_UNIQUEIDENTIFIER: $str_type = 'uniqueidentifier'; break; - case SQLSRV_SQLTYPE_UDT: $str_type = 'UDT'; break; - case SQLSRV_SQLTYPE_VARBINARY/*($byteCount)*/: $str_type = 'varbinary'; break; - case SQLSRV_SQLTYPE_VARCHAR/*($charCount)*/: $str_type = 'varchar'; break; - case SQLSRV_SQLTYPE_XML: $str_type = 'xml'; break; - default: $str_type = $int_type; - } - return $str_type; - } - - public function free() - { - unset($this->m_rows); - return; - } -} +namespace phpbb\db\driver; /** * @package dbal */ -class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base +class mssqlnative extends \phpbb\db\driver\mssql_base { - var $m_insert_id = NULL; + var $m_insert_id = null; var $last_query_text = ''; var $query_options = array(); var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -228,10 +53,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -288,13 +110,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -390,7 +206,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -398,7 +214,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -425,7 +241,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base { foreach ($row as $key => $value) { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; + $row[$key] = ($value === ' ' || $value === null) ? '' : $value; } // remove helper values from LIMIT queries @@ -438,7 +254,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -458,7 +274,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -469,7 +285,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -479,6 +295,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base unset($this->open_queries[(int) $query_id]); return @sqlsrv_free_stmt($query_id); } + return false; } diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index f3744ac09d..1a4fd364df 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * MySQL4 Database Abstraction Layer @@ -24,14 +18,13 @@ if (!defined('IN_PHPBB')) * MySQL 5.0+ * @package dbal */ -class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base +class mysql extends \phpbb\db\driver\mysql_base { var $multi_insert = true; var $connect_error = ''; /** - * Connect to server - * @access public + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -109,10 +102,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -160,13 +150,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -219,7 +203,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -227,7 +211,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -247,8 +231,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -268,7 +251,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -276,7 +259,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -287,7 +270,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -302,7 +285,7 @@ class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index ba44ea61aa..d0f6a9e8fa 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Abstract MySQL Database Base Abstraction Layer * @package dbal */ -abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver +abstract class mysql_base extends \phpbb\db\driver\driver { /** * {@inheritDoc} @@ -49,14 +43,7 @@ abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver } /** - * Gets the estimated number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Number of rows in $table_name. - * Prefixed with ~ if estimated (otherwise exact). - * - * @access public + * {@inheritDoc} */ function get_estimated_row_count($table_name) { @@ -78,13 +65,7 @@ abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver } /** - * Gets the exact number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Exact number of rows in $table_name. - * - * @access public + * {@inheritDoc} */ function get_row_count($table_name) { diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 0f7a73ee6e..6814599b24 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * MySQLi Database Abstraction Layer @@ -21,15 +15,15 @@ if (!defined('IN_PHPBB')) * MySQL 4.1+ or MySQL 5.0+ * @package dbal */ -class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base +class mysqli extends \phpbb\db\driver\mysql_base { var $multi_insert = true; var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { if (!function_exists('mysqli_connect')) { @@ -45,11 +39,11 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base $this->server = ($this->persistency) ? 'p:' . (($sqlserver) ? $sqlserver : 'localhost') : $sqlserver; $this->dbname = $database; - $port = (!$port) ? NULL : $port; + $port = (!$port) ? null : $port; // If port is set and it is not numeric, most likely mysqli socket is set. // Try to map it to the $socket parameter. - $socket = NULL; + $socket = null; if ($port) { if (is_numeric($port)) @@ -59,7 +53,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base else { $socket = $port; - $port = NULL; + $port = null; } } @@ -102,10 +96,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -157,13 +148,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -211,7 +196,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -219,7 +204,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -245,8 +230,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -266,7 +250,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -274,7 +258,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -294,7 +278,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index e21e07055d..8a304b5042 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -7,25 +7,19 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Oracle Database Abstraction Layer * @package dbal */ -class phpbb_db_driver_oracle extends phpbb_db_driver +class oracle extends \phpbb\db\driver\driver { var $last_query_text = ''; var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -78,10 +72,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache forced to false for Oracle - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -246,13 +237,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -479,7 +464,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -487,7 +472,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -538,8 +523,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -576,7 +560,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -608,7 +592,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -619,7 +603,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -634,7 +618,7 @@ class phpbb_db_driver_oracle extends phpbb_db_driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 14854d179d..9e091f0a5d 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -7,26 +7,20 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * PostgreSQL Database Abstraction Layer * Minimum Requirement is Version 7.3+ * @package dbal */ -class phpbb_db_driver_postgres extends phpbb_db_driver +class postgres extends \phpbb\db\driver\driver { var $last_query_text = ''; var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -84,7 +78,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $this->connect_error = 'pg_pconnect function does not exist, is pgsql extension installed?'; return $this->sql_error(''); } - $collector = new phpbb_error_collector; + $collector = new \phpbb\error_collector; $collector->install(); $this->db_connect_id = (!$new_link) ? @pg_pconnect($connect_string) : @pg_pconnect($connect_string, PGSQL_CONNECT_FORCE_NEW); } @@ -95,7 +89,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $this->connect_error = 'pg_connect function does not exist, is pgsql extension installed?'; return $this->sql_error(''); } - $collector = new phpbb_error_collector; + $collector = new \phpbb\error_collector; $collector->install(); $this->db_connect_id = (!$new_link) ? @pg_connect($connect_string) : @pg_connect($connect_string, PGSQL_CONNECT_FORCE_NEW); } @@ -121,10 +115,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -172,13 +163,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -259,7 +244,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -267,7 +252,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -287,8 +272,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -308,7 +292,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -326,7 +310,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver return false; } - $temp_result = @pg_fetch_assoc($temp_q_id, NULL); + $temp_result = @pg_fetch_assoc($temp_q_id, null); @pg_free_result($query_id); return ($temp_result) ? $temp_result['last_value'] : false; @@ -337,7 +321,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -348,7 +332,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -363,8 +347,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * Escape string used in sql query - * Note: Do not use for bytea values if we may use them at a later stage + * {@inheritDoc} */ function sql_escape($msg) { @@ -381,7 +364,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -389,7 +372,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_string($expression) { @@ -454,7 +437,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query")) { - while ($row = @pg_fetch_assoc($result, NULL)) + while ($row = @pg_fetch_assoc($result, null)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } @@ -474,7 +457,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $endtime = $endtime[0] + $endtime[1]; $result = @pg_query($this->db_connect_id, $query); - while ($void = @pg_fetch_assoc($result, NULL)) + while ($void = @pg_fetch_assoc($result, null)) { // Take the time spent on parsing rows into account } diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 7188f0daa2..86a585f4eb 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -7,25 +7,19 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\driver; /** * Sqlite Database Abstraction Layer * Minimum Requirement: 2.8.2+ * @package dbal */ -class phpbb_db_driver_sqlite extends phpbb_db_driver +class sqlite extends \phpbb\db\driver\driver { var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -64,10 +58,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache if true, it is safe to retrieve the stored value from the cache - * @return string sql server version + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -114,13 +105,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -191,7 +176,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -199,7 +184,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -219,8 +204,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -240,7 +224,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -248,7 +232,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -259,7 +243,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -268,7 +252,7 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { @@ -276,7 +260,8 @@ class phpbb_db_driver_sqlite extends phpbb_db_driver } /** - * Correctly adjust LIKE expression for special characters + * {@inheritDoc} + * * For SQLite an underscore is a not-known character... this may change with SQLite3 */ function sql_like_expression($expression) diff --git a/phpBB/phpbb/db/migration/data/30x/local_url_bbcode.php b/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php index f324b8880d..5e6ba90336 100644 --- a/phpBB/phpbb/db/migration/data/30x/local_url_bbcode.php +++ b/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php @@ -7,11 +7,13 @@ * */ -class phpbb_db_migration_data_30x_local_url_bbcode extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class local_url_bbcode extends \phpbb\db\migration\migration { static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_12_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc1'); } public function update_data() @@ -44,7 +46,7 @@ class phpbb_db_migration_data_30x_local_url_bbcode extends phpbb_db_migration $bbcode_match = $row['bbcode_match']; $bbcode_tpl = $row['bbcode_tpl']; - $acp_bbcodes = new acp_bbcodes(); + $acp_bbcodes = new \acp_bbcodes(); $sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl); $sql = 'UPDATE ' . BBCODES_TABLE . ' diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php new file mode 100644 index 0000000000..41ade22a29 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php @@ -0,0 +1,1177 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_0 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.0.0', '>='); + } + + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'attachments' => array( + 'COLUMNS' => array( + 'attach_id' => array('UINT', NULL, 'auto_increment'), + 'post_msg_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'in_message' => array('BOOL', 0), + 'poster_id' => array('UINT', 0), + 'is_orphan' => array('BOOL', 1), + 'physical_filename' => array('VCHAR', ''), + 'real_filename' => array('VCHAR', ''), + 'download_count' => array('UINT', 0), + 'attach_comment' => array('TEXT_UNI', ''), + 'extension' => array('VCHAR:100', ''), + 'mimetype' => array('VCHAR:100', ''), + 'filesize' => array('UINT:20', 0), + 'filetime' => array('TIMESTAMP', 0), + 'thumbnail' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'attach_id', + 'KEYS' => array( + 'filetime' => array('INDEX', 'filetime'), + 'post_msg_id' => array('INDEX', 'post_msg_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'poster_id' => array('INDEX', 'poster_id'), + 'is_orphan' => array('INDEX', 'is_orphan'), + ), + ), + + $this->table_prefix . 'acl_groups' => array( + 'COLUMNS' => array( + 'group_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_role_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'KEYS' => array( + 'group_id' => array('INDEX', 'group_id'), + 'auth_opt_id' => array('INDEX', 'auth_option_id'), + 'auth_role_id' => array('INDEX', 'auth_role_id'), + ), + ), + + $this->table_prefix . 'acl_options' => array( + 'COLUMNS' => array( + 'auth_option_id' => array('UINT', NULL, 'auto_increment'), + 'auth_option' => array('VCHAR:50', ''), + 'is_global' => array('BOOL', 0), + 'is_local' => array('BOOL', 0), + 'founder_only' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'auth_option_id', + 'KEYS' => array( + 'auth_option' => array('INDEX', 'auth_option'), + ), + ), + + $this->table_prefix . 'acl_roles' => array( + 'COLUMNS' => array( + 'role_id' => array('UINT', NULL, 'auto_increment'), + 'role_name' => array('VCHAR_UNI', ''), + 'role_description' => array('TEXT_UNI', ''), + 'role_type' => array('VCHAR:10', ''), + 'role_order' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'role_id', + 'KEYS' => array( + 'role_type' => array('INDEX', 'role_type'), + 'role_order' => array('INDEX', 'role_order'), + ), + ), + + $this->table_prefix . 'acl_roles_data' => array( + 'COLUMNS' => array( + 'role_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'PRIMARY_KEY' => array('role_id', 'auth_option_id'), + 'KEYS' => array( + 'ath_op_id' => array('INDEX', 'auth_option_id'), + ), + ), + + $this->table_prefix . 'acl_users' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_role_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + 'auth_option_id' => array('INDEX', 'auth_option_id'), + 'auth_role_id' => array('INDEX', 'auth_role_id'), + ), + ), + + $this->table_prefix . 'banlist' => array( + 'COLUMNS' => array( + 'ban_id' => array('UINT', NULL, 'auto_increment'), + 'ban_userid' => array('UINT', 0), + 'ban_ip' => array('VCHAR:40', ''), + 'ban_email' => array('VCHAR_UNI:100', ''), + 'ban_start' => array('TIMESTAMP', 0), + 'ban_end' => array('TIMESTAMP', 0), + 'ban_exclude' => array('BOOL', 0), + 'ban_reason' => array('VCHAR_UNI', ''), + 'ban_give_reason' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'ban_id', + 'KEYS' => array( + 'ban_end' => array('INDEX', 'ban_end'), + 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')), + 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')), + 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')), + ), + ), + + $this->table_prefix . 'bbcodes' => array( + 'COLUMNS' => array( + 'bbcode_id' => array('TINT:3', 0), + 'bbcode_tag' => array('VCHAR:16', ''), + 'bbcode_helpline' => array('VCHAR_UNI', ''), + 'display_on_posting' => array('BOOL', 0), + 'bbcode_match' => array('TEXT_UNI', ''), + 'bbcode_tpl' => array('MTEXT_UNI', ''), + 'first_pass_match' => array('MTEXT_UNI', ''), + 'first_pass_replace' => array('MTEXT_UNI', ''), + 'second_pass_match' => array('MTEXT_UNI', ''), + 'second_pass_replace' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'bbcode_id', + 'KEYS' => array( + 'display_on_post' => array('INDEX', 'display_on_posting'), + ), + ), + + $this->table_prefix . 'bookmarks' => array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + ), + 'PRIMARY_KEY' => array('topic_id', 'user_id'), + ), + + $this->table_prefix . 'bots' => array( + 'COLUMNS' => array( + 'bot_id' => array('UINT', NULL, 'auto_increment'), + 'bot_active' => array('BOOL', 1), + 'bot_name' => array('STEXT_UNI', ''), + 'user_id' => array('UINT', 0), + 'bot_agent' => array('VCHAR', ''), + 'bot_ip' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'bot_id', + 'KEYS' => array( + 'bot_active' => array('INDEX', 'bot_active'), + ), + ), + + $this->table_prefix . 'config' => array( + 'COLUMNS' => array( + 'config_name' => array('VCHAR', ''), + 'config_value' => array('VCHAR_UNI', ''), + 'is_dynamic' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'config_name', + 'KEYS' => array( + 'is_dynamic' => array('INDEX', 'is_dynamic'), + ), + ), + + $this->table_prefix . 'confirm' => array( + 'COLUMNS' => array( + 'confirm_id' => array('CHAR:32', ''), + 'session_id' => array('CHAR:32', ''), + 'confirm_type' => array('TINT:3', 0), + 'code' => array('VCHAR:8', ''), + 'seed' => array('UINT:10', 0), + ), + 'PRIMARY_KEY' => array('session_id', 'confirm_id'), + 'KEYS' => array( + 'confirm_type' => array('INDEX', 'confirm_type'), + ), + ), + + $this->table_prefix . 'disallow' => array( + 'COLUMNS' => array( + 'disallow_id' => array('UINT', NULL, 'auto_increment'), + 'disallow_username' => array('VCHAR_UNI:255', ''), + ), + 'PRIMARY_KEY' => 'disallow_id', + ), + + $this->table_prefix . 'drafts' => array( + 'COLUMNS' => array( + 'draft_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'save_time' => array('TIMESTAMP', 0), + 'draft_subject' => array('XSTEXT_UNI', ''), + 'draft_message' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'draft_id', + 'KEYS' => array( + 'save_time' => array('INDEX', 'save_time'), + ), + ), + + $this->table_prefix . 'extensions' => array( + 'COLUMNS' => array( + 'extension_id' => array('UINT', NULL, 'auto_increment'), + 'group_id' => array('UINT', 0), + 'extension' => array('VCHAR:100', ''), + ), + 'PRIMARY_KEY' => 'extension_id', + ), + + $this->table_prefix . 'extension_groups' => array( + 'COLUMNS' => array( + 'group_id' => array('UINT', NULL, 'auto_increment'), + 'group_name' => array('VCHAR_UNI', ''), + 'cat_id' => array('TINT:2', 0), + 'allow_group' => array('BOOL', 0), + 'download_mode' => array('BOOL', 1), + 'upload_icon' => array('VCHAR', ''), + 'max_filesize' => array('UINT:20', 0), + 'allowed_forums' => array('TEXT', ''), + 'allow_in_pm' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'group_id', + ), + + $this->table_prefix . 'forums' => array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', NULL, 'auto_increment'), + 'parent_id' => array('UINT', 0), + 'left_id' => array('UINT', 0), + 'right_id' => array('UINT', 0), + 'forum_parents' => array('MTEXT', ''), + 'forum_name' => array('STEXT_UNI', ''), + 'forum_desc' => array('TEXT_UNI', ''), + 'forum_desc_bitfield' => array('VCHAR:255', ''), + 'forum_desc_options' => array('UINT:11', 7), + 'forum_desc_uid' => array('VCHAR:8', ''), + 'forum_link' => array('VCHAR_UNI', ''), + 'forum_password' => array('VCHAR_UNI:40', ''), + 'forum_style' => array('USINT', 0), + 'forum_image' => array('VCHAR', ''), + 'forum_rules' => array('TEXT_UNI', ''), + 'forum_rules_link' => array('VCHAR_UNI', ''), + 'forum_rules_bitfield' => array('VCHAR:255', ''), + 'forum_rules_options' => array('UINT:11', 7), + 'forum_rules_uid' => array('VCHAR:8', ''), + 'forum_topics_per_page' => array('TINT:4', 0), + 'forum_type' => array('TINT:4', 0), + 'forum_status' => array('TINT:4', 0), + 'forum_posts' => array('UINT', 0), + 'forum_topics' => array('UINT', 0), + 'forum_topics_real' => array('UINT', 0), + 'forum_last_post_id' => array('UINT', 0), + 'forum_last_poster_id' => array('UINT', 0), + 'forum_last_post_subject' => array('XSTEXT_UNI', ''), + 'forum_last_post_time' => array('TIMESTAMP', 0), + 'forum_last_poster_name'=> array('VCHAR_UNI', ''), + 'forum_last_poster_colour'=> array('VCHAR:6', ''), + 'forum_flags' => array('TINT:4', 32), + 'display_on_index' => array('BOOL', 1), + 'enable_indexing' => array('BOOL', 1), + 'enable_icons' => array('BOOL', 1), + 'enable_prune' => array('BOOL', 0), + 'prune_next' => array('TIMESTAMP', 0), + 'prune_days' => array('UINT', 0), + 'prune_viewed' => array('UINT', 0), + 'prune_freq' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'forum_id', + 'KEYS' => array( + 'left_right_id' => array('INDEX', array('left_id', 'right_id')), + 'forum_lastpost_id' => array('INDEX', 'forum_last_post_id'), + ), + ), + + $this->table_prefix . 'forums_access' => array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'session_id' => array('CHAR:32', ''), + ), + 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'), + ), + + $this->table_prefix . 'forums_track' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'mark_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'forum_id'), + ), + + $this->table_prefix . 'forums_watch' => array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'notify_status' => array('BOOL', 0), + ), + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'user_id' => array('INDEX', 'user_id'), + 'notify_stat' => array('INDEX', 'notify_status'), + ), + ), + + $this->table_prefix . 'groups' => array( + 'COLUMNS' => array( + 'group_id' => array('UINT', NULL, 'auto_increment'), + 'group_type' => array('TINT:4', 1), + 'group_founder_manage' => array('BOOL', 0), + 'group_name' => array('VCHAR_CI', ''), + 'group_desc' => array('TEXT_UNI', ''), + 'group_desc_bitfield' => array('VCHAR:255', ''), + 'group_desc_options' => array('UINT:11', 7), + 'group_desc_uid' => array('VCHAR:8', ''), + 'group_display' => array('BOOL', 0), + 'group_avatar' => array('VCHAR', ''), + 'group_avatar_type' => array('TINT:2', 0), + 'group_avatar_width' => array('USINT', 0), + 'group_avatar_height' => array('USINT', 0), + 'group_rank' => array('UINT', 0), + 'group_colour' => array('VCHAR:6', ''), + 'group_sig_chars' => array('UINT', 0), + 'group_receive_pm' => array('BOOL', 0), + 'group_message_limit' => array('UINT', 0), + 'group_legend' => array('BOOL', 1), + ), + 'PRIMARY_KEY' => 'group_id', + 'KEYS' => array( + 'group_legend' => array('INDEX', 'group_legend'), + ), + ), + + $this->table_prefix . 'icons' => array( + 'COLUMNS' => array( + 'icons_id' => array('UINT', NULL, 'auto_increment'), + 'icons_url' => array('VCHAR', ''), + 'icons_width' => array('TINT:4', 0), + 'icons_height' => array('TINT:4', 0), + 'icons_order' => array('UINT', 0), + 'display_on_posting' => array('BOOL', 1), + ), + 'PRIMARY_KEY' => 'icons_id', + 'KEYS' => array( + 'display_on_posting' => array('INDEX', 'display_on_posting'), + ), + ), + + $this->table_prefix . 'lang' => array( + 'COLUMNS' => array( + 'lang_id' => array('TINT:4', NULL, 'auto_increment'), + 'lang_iso' => array('VCHAR:30', ''), + 'lang_dir' => array('VCHAR:30', ''), + 'lang_english_name' => array('VCHAR_UNI:100', ''), + 'lang_local_name' => array('VCHAR_UNI:255', ''), + 'lang_author' => array('VCHAR_UNI:255', ''), + ), + 'PRIMARY_KEY' => 'lang_id', + 'KEYS' => array( + 'lang_iso' => array('INDEX', 'lang_iso'), + ), + ), + + $this->table_prefix . 'log' => array( + 'COLUMNS' => array( + 'log_id' => array('UINT', NULL, 'auto_increment'), + 'log_type' => array('TINT:4', 0), + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'reportee_id' => array('UINT', 0), + 'log_ip' => array('VCHAR:40', ''), + 'log_time' => array('TIMESTAMP', 0), + 'log_operation' => array('TEXT_UNI', ''), + 'log_data' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'log_id', + 'KEYS' => array( + 'log_type' => array('INDEX', 'log_type'), + 'forum_id' => array('INDEX', 'forum_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'reportee_id' => array('INDEX', 'reportee_id'), + 'user_id' => array('INDEX', 'user_id'), + ), + ), + + $this->table_prefix . 'moderator_cache' => array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'username' => array('VCHAR_UNI:255', ''), + 'group_id' => array('UINT', 0), + 'group_name' => array('VCHAR_UNI', ''), + 'display_on_index' => array('BOOL', 1), + ), + 'KEYS' => array( + 'disp_idx' => array('INDEX', 'display_on_index'), + 'forum_id' => array('INDEX', 'forum_id'), + ), + ), + + $this->table_prefix . 'modules' => array( + 'COLUMNS' => array( + 'module_id' => array('UINT', NULL, 'auto_increment'), + 'module_enabled' => array('BOOL', 1), + 'module_display' => array('BOOL', 1), + 'module_basename' => array('VCHAR', ''), + 'module_class' => array('VCHAR:10', ''), + 'parent_id' => array('UINT', 0), + 'left_id' => array('UINT', 0), + 'right_id' => array('UINT', 0), + 'module_langname' => array('VCHAR', ''), + 'module_mode' => array('VCHAR', ''), + 'module_auth' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'module_id', + 'KEYS' => array( + 'left_right_id' => array('INDEX', array('left_id', 'right_id')), + 'module_enabled' => array('INDEX', 'module_enabled'), + 'class_left_id' => array('INDEX', array('module_class', 'left_id')), + ), + ), + + $this->table_prefix . 'poll_options' => array( + 'COLUMNS' => array( + 'poll_option_id' => array('TINT:4', 0), + 'topic_id' => array('UINT', 0), + 'poll_option_text' => array('TEXT_UNI', ''), + 'poll_option_total' => array('UINT', 0), + ), + 'KEYS' => array( + 'poll_opt_id' => array('INDEX', 'poll_option_id'), + 'topic_id' => array('INDEX', 'topic_id'), + ), + ), + + $this->table_prefix . 'poll_votes' => array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'poll_option_id' => array('TINT:4', 0), + 'vote_user_id' => array('UINT', 0), + 'vote_user_ip' => array('VCHAR:40', ''), + ), + 'KEYS' => array( + 'topic_id' => array('INDEX', 'topic_id'), + 'vote_user_id' => array('INDEX', 'vote_user_id'), + 'vote_user_ip' => array('INDEX', 'vote_user_ip'), + ), + ), + + $this->table_prefix . 'posts' => array( + 'COLUMNS' => array( + 'post_id' => array('UINT', NULL, 'auto_increment'), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'poster_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'poster_ip' => array('VCHAR:40', ''), + 'post_time' => array('TIMESTAMP', 0), + 'post_approved' => array('BOOL', 1), + 'post_reported' => array('BOOL', 0), + 'enable_bbcode' => array('BOOL', 1), + 'enable_smilies' => array('BOOL', 1), + 'enable_magic_url' => array('BOOL', 1), + 'enable_sig' => array('BOOL', 1), + 'post_username' => array('VCHAR_UNI:255', ''), + 'post_subject' => array('XSTEXT_UNI', '', 'true_sort'), + 'post_text' => array('MTEXT_UNI', ''), + 'post_checksum' => array('VCHAR:32', ''), + 'post_attachment' => array('BOOL', 0), + 'bbcode_bitfield' => array('VCHAR:255', ''), + 'bbcode_uid' => array('VCHAR:8', ''), + 'post_postcount' => array('BOOL', 1), + 'post_edit_time' => array('TIMESTAMP', 0), + 'post_edit_reason' => array('STEXT_UNI', ''), + 'post_edit_user' => array('UINT', 0), + 'post_edit_count' => array('USINT', 0), + 'post_edit_locked' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'post_id', + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'poster_ip' => array('INDEX', 'poster_ip'), + 'poster_id' => array('INDEX', 'poster_id'), + 'post_approved' => array('INDEX', 'post_approved'), + 'tid_post_time' => array('INDEX', array('topic_id', 'post_time')), + ), + ), + + $this->table_prefix . 'privmsgs' => array( + 'COLUMNS' => array( + 'msg_id' => array('UINT', NULL, 'auto_increment'), + 'root_level' => array('UINT', 0), + 'author_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'author_ip' => array('VCHAR:40', ''), + 'message_time' => array('TIMESTAMP', 0), + 'enable_bbcode' => array('BOOL', 1), + 'enable_smilies' => array('BOOL', 1), + 'enable_magic_url' => array('BOOL', 1), + 'enable_sig' => array('BOOL', 1), + 'message_subject' => array('XSTEXT_UNI', ''), + 'message_text' => array('MTEXT_UNI', ''), + 'message_edit_reason' => array('STEXT_UNI', ''), + 'message_edit_user' => array('UINT', 0), + 'message_attachment' => array('BOOL', 0), + 'bbcode_bitfield' => array('VCHAR:255', ''), + 'bbcode_uid' => array('VCHAR:8', ''), + 'message_edit_time' => array('TIMESTAMP', 0), + 'message_edit_count' => array('USINT', 0), + 'to_address' => array('TEXT_UNI', ''), + 'bcc_address' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'msg_id', + 'KEYS' => array( + 'author_ip' => array('INDEX', 'author_ip'), + 'message_time' => array('INDEX', 'message_time'), + 'author_id' => array('INDEX', 'author_id'), + 'root_level' => array('INDEX', 'root_level'), + ), + ), + + $this->table_prefix . 'privmsgs_folder' => array( + 'COLUMNS' => array( + 'folder_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'folder_name' => array('VCHAR_UNI', ''), + 'pm_count' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'folder_id', + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + ), + ), + + $this->table_prefix . 'privmsgs_rules' => array( + 'COLUMNS' => array( + 'rule_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'rule_check' => array('UINT', 0), + 'rule_connection' => array('UINT', 0), + 'rule_string' => array('VCHAR_UNI', ''), + 'rule_user_id' => array('UINT', 0), + 'rule_group_id' => array('UINT', 0), + 'rule_action' => array('UINT', 0), + 'rule_folder_id' => array('INT:11', 0), + ), + 'PRIMARY_KEY' => 'rule_id', + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + ), + ), + + $this->table_prefix . 'privmsgs_to' => array( + 'COLUMNS' => array( + 'msg_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'author_id' => array('UINT', 0), + 'pm_deleted' => array('BOOL', 0), + 'pm_new' => array('BOOL', 1), + 'pm_unread' => array('BOOL', 1), + 'pm_replied' => array('BOOL', 0), + 'pm_marked' => array('BOOL', 0), + 'pm_forwarded' => array('BOOL', 0), + 'folder_id' => array('INT:11', 0), + ), + 'KEYS' => array( + 'msg_id' => array('INDEX', 'msg_id'), + 'author_id' => array('INDEX', 'author_id'), + 'usr_flder_id' => array('INDEX', array('user_id', 'folder_id')), + ), + ), + + $this->table_prefix . 'profile_fields' => array( + 'COLUMNS' => array( + 'field_id' => array('UINT', NULL, 'auto_increment'), + 'field_name' => array('VCHAR_UNI', ''), + 'field_type' => array('TINT:4', 0), + 'field_ident' => array('VCHAR:20', ''), + 'field_length' => array('VCHAR:20', ''), + 'field_minlen' => array('VCHAR', ''), + 'field_maxlen' => array('VCHAR', ''), + 'field_novalue' => array('VCHAR_UNI', ''), + 'field_default_value' => array('VCHAR_UNI', ''), + 'field_validation' => array('VCHAR_UNI:20', ''), + 'field_required' => array('BOOL', 0), + 'field_show_on_reg' => array('BOOL', 0), + 'field_hide' => array('BOOL', 0), + 'field_no_view' => array('BOOL', 0), + 'field_active' => array('BOOL', 0), + 'field_order' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'field_id', + 'KEYS' => array( + 'fld_type' => array('INDEX', 'field_type'), + 'fld_ordr' => array('INDEX', 'field_order'), + ), + ), + + $this->table_prefix . 'profile_fields_data' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'user_id', + ), + + $this->table_prefix . 'profile_fields_lang' => array( + 'COLUMNS' => array( + 'field_id' => array('UINT', 0), + 'lang_id' => array('UINT', 0), + 'option_id' => array('UINT', 0), + 'field_type' => array('TINT:4', 0), + 'lang_value' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => array('field_id', 'lang_id', 'option_id'), + ), + + $this->table_prefix . 'profile_lang' => array( + 'COLUMNS' => array( + 'field_id' => array('UINT', 0), + 'lang_id' => array('UINT', 0), + 'lang_name' => array('VCHAR_UNI', ''), + 'lang_explain' => array('TEXT_UNI', ''), + 'lang_default_value' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => array('field_id', 'lang_id'), + ), + + $this->table_prefix . 'ranks' => array( + 'COLUMNS' => array( + 'rank_id' => array('UINT', NULL, 'auto_increment'), + 'rank_title' => array('VCHAR_UNI', ''), + 'rank_min' => array('UINT', 0), + 'rank_special' => array('BOOL', 0), + 'rank_image' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'rank_id', + ), + + $this->table_prefix . 'reports' => array( + 'COLUMNS' => array( + 'report_id' => array('UINT', NULL, 'auto_increment'), + 'reason_id' => array('USINT', 0), + 'post_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'user_notify' => array('BOOL', 0), + 'report_closed' => array('BOOL', 0), + 'report_time' => array('TIMESTAMP', 0), + 'report_text' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'report_id', + ), + + $this->table_prefix . 'reports_reasons' => array( + 'COLUMNS' => array( + 'reason_id' => array('USINT', NULL, 'auto_increment'), + 'reason_title' => array('VCHAR_UNI', ''), + 'reason_description' => array('MTEXT_UNI', ''), + 'reason_order' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'reason_id', + ), + + $this->table_prefix . 'search_results' => array( + 'COLUMNS' => array( + 'search_key' => array('VCHAR:32', ''), + 'search_time' => array('TIMESTAMP', 0), + 'search_keywords' => array('MTEXT_UNI', ''), + 'search_authors' => array('MTEXT', ''), + ), + 'PRIMARY_KEY' => 'search_key', + ), + + $this->table_prefix . 'search_wordlist' => array( + 'COLUMNS' => array( + 'word_id' => array('UINT', NULL, 'auto_increment'), + 'word_text' => array('VCHAR_UNI', ''), + 'word_common' => array('BOOL', 0), + 'word_count' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'word_id', + 'KEYS' => array( + 'wrd_txt' => array('UNIQUE', 'word_text'), + 'wrd_cnt' => array('INDEX', 'word_count'), + ), + ), + + $this->table_prefix . 'search_wordmatch' => array( + 'COLUMNS' => array( + 'post_id' => array('UINT', 0), + 'word_id' => array('UINT', 0), + 'title_match' => array('BOOL', 0), + ), + 'KEYS' => array( + 'unq_mtch' => array('UNIQUE', array('word_id', 'post_id', 'title_match')), + 'word_id' => array('INDEX', 'word_id'), + 'post_id' => array('INDEX', 'post_id'), + ), + ), + + $this->table_prefix . 'sessions' => array( + 'COLUMNS' => array( + 'session_id' => array('CHAR:32', ''), + 'session_user_id' => array('UINT', 0), + 'session_last_visit' => array('TIMESTAMP', 0), + 'session_start' => array('TIMESTAMP', 0), + 'session_time' => array('TIMESTAMP', 0), + 'session_ip' => array('VCHAR:40', ''), + 'session_browser' => array('VCHAR:150', ''), + 'session_forwarded_for' => array('VCHAR:255', ''), + 'session_page' => array('VCHAR_UNI', ''), + 'session_viewonline' => array('BOOL', 1), + 'session_autologin' => array('BOOL', 0), + 'session_admin' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'session_id', + 'KEYS' => array( + 'session_time' => array('INDEX', 'session_time'), + 'session_user_id' => array('INDEX', 'session_user_id'), + ), + ), + + $this->table_prefix . 'sessions_keys' => array( + 'COLUMNS' => array( + 'key_id' => array('CHAR:32', ''), + 'user_id' => array('UINT', 0), + 'last_ip' => array('VCHAR:40', ''), + 'last_login' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('key_id', 'user_id'), + 'KEYS' => array( + 'last_login' => array('INDEX', 'last_login'), + ), + ), + + $this->table_prefix . 'sitelist' => array( + 'COLUMNS' => array( + 'site_id' => array('UINT', NULL, 'auto_increment'), + 'site_ip' => array('VCHAR:40', ''), + 'site_hostname' => array('VCHAR', ''), + 'ip_exclude' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'site_id', + ), + + $this->table_prefix . 'smilies' => array( + 'COLUMNS' => array( + 'smiley_id' => array('UINT', NULL, 'auto_increment'), +// We may want to set 'code' to VCHAR:50 or check if unicode support is possible... at the moment only ASCII characters are allowed. + 'code' => array('VCHAR_UNI:50', ''), + 'emotion' => array('VCHAR_UNI:50', ''), + 'smiley_url' => array('VCHAR:50', ''), + 'smiley_width' => array('USINT', 0), + 'smiley_height' => array('USINT', 0), + 'smiley_order' => array('UINT', 0), + 'display_on_posting'=> array('BOOL', 1), + ), + 'PRIMARY_KEY' => 'smiley_id', + 'KEYS' => array( + 'display_on_post' => array('INDEX', 'display_on_posting'), + ), + ), + + $this->table_prefix . 'styles' => array( + 'COLUMNS' => array( + 'style_id' => array('USINT', NULL, 'auto_increment'), + 'style_name' => array('VCHAR_UNI:255', ''), + 'style_copyright' => array('VCHAR_UNI', ''), + 'style_active' => array('BOOL', 1), + 'template_id' => array('USINT', 0), + 'theme_id' => array('USINT', 0), + 'imageset_id' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'style_id', + 'KEYS' => array( + 'style_name' => array('UNIQUE', 'style_name'), + 'template_id' => array('INDEX', 'template_id'), + 'theme_id' => array('INDEX', 'theme_id'), + 'imageset_id' => array('INDEX', 'imageset_id'), + ), + ), + + $this->table_prefix . 'styles_template' => array( + 'COLUMNS' => array( + 'template_id' => array('USINT', NULL, 'auto_increment'), + 'template_name' => array('VCHAR_UNI:255', ''), + 'template_copyright' => array('VCHAR_UNI', ''), + 'template_path' => array('VCHAR:100', ''), + 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), + 'template_storedb' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'template_id', + 'KEYS' => array( + 'tmplte_nm' => array('UNIQUE', 'template_name'), + ), + ), + + $this->table_prefix . 'styles_template_data' => array( + 'COLUMNS' => array( + 'template_id' => array('USINT', 0), + 'template_filename' => array('VCHAR:100', ''), + 'template_included' => array('TEXT', ''), + 'template_mtime' => array('TIMESTAMP', 0), + 'template_data' => array('MTEXT_UNI', ''), + ), + 'KEYS' => array( + 'tid' => array('INDEX', 'template_id'), + 'tfn' => array('INDEX', 'template_filename'), + ), + ), + + $this->table_prefix . 'styles_theme' => array( + 'COLUMNS' => array( + 'theme_id' => array('USINT', NULL, 'auto_increment'), + 'theme_name' => array('VCHAR_UNI:255', ''), + 'theme_copyright' => array('VCHAR_UNI', ''), + 'theme_path' => array('VCHAR:100', ''), + 'theme_storedb' => array('BOOL', 0), + 'theme_mtime' => array('TIMESTAMP', 0), + 'theme_data' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'theme_id', + 'KEYS' => array( + 'theme_name' => array('UNIQUE', 'theme_name'), + ), + ), + + $this->table_prefix . 'styles_imageset' => array( + 'COLUMNS' => array( + 'imageset_id' => array('USINT', NULL, 'auto_increment'), + 'imageset_name' => array('VCHAR_UNI:255', ''), + 'imageset_copyright' => array('VCHAR_UNI', ''), + 'imageset_path' => array('VCHAR:100', ''), + ), + 'PRIMARY_KEY' => 'imageset_id', + 'KEYS' => array( + 'imgset_nm' => array('UNIQUE', 'imageset_name'), + ), + ), + + $this->table_prefix . 'styles_imageset_data' => array( + 'COLUMNS' => array( + 'image_id' => array('USINT', NULL, 'auto_increment'), + 'image_name' => array('VCHAR:200', ''), + 'image_filename' => array('VCHAR:200', ''), + 'image_lang' => array('VCHAR:30', ''), + 'image_height' => array('USINT', 0), + 'image_width' => array('USINT', 0), + 'imageset_id' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'image_id', + 'KEYS' => array( + 'i_d' => array('INDEX', 'imageset_id'), + ), + ), + + $this->table_prefix . 'topics' => array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', NULL, 'auto_increment'), + 'forum_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'topic_attachment' => array('BOOL', 0), + 'topic_approved' => array('BOOL', 1), + 'topic_reported' => array('BOOL', 0), + 'topic_title' => array('XSTEXT_UNI', '', 'true_sort'), + 'topic_poster' => array('UINT', 0), + 'topic_time' => array('TIMESTAMP', 0), + 'topic_time_limit' => array('TIMESTAMP', 0), + 'topic_views' => array('UINT', 0), + 'topic_replies' => array('UINT', 0), + 'topic_replies_real' => array('UINT', 0), + 'topic_status' => array('TINT:3', 0), + 'topic_type' => array('TINT:3', 0), + 'topic_first_post_id' => array('UINT', 0), + 'topic_first_poster_name' => array('VCHAR_UNI', ''), + 'topic_first_poster_colour' => array('VCHAR:6', ''), + 'topic_last_post_id' => array('UINT', 0), + 'topic_last_poster_id' => array('UINT', 0), + 'topic_last_poster_name' => array('VCHAR_UNI', ''), + 'topic_last_poster_colour' => array('VCHAR:6', ''), + 'topic_last_post_subject' => array('XSTEXT_UNI', ''), + 'topic_last_post_time' => array('TIMESTAMP', 0), + 'topic_last_view_time' => array('TIMESTAMP', 0), + 'topic_moved_id' => array('UINT', 0), + 'topic_bumped' => array('BOOL', 0), + 'topic_bumper' => array('UINT', 0), + 'poll_title' => array('STEXT_UNI', ''), + 'poll_start' => array('TIMESTAMP', 0), + 'poll_length' => array('TIMESTAMP', 0), + 'poll_max_options' => array('TINT:4', 1), + 'poll_last_vote' => array('TIMESTAMP', 0), + 'poll_vote_change' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'topic_id', + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'forum_id_type' => array('INDEX', array('forum_id', 'topic_type')), + 'last_post_time' => array('INDEX', 'topic_last_post_time'), + 'topic_approved' => array('INDEX', 'topic_approved'), + 'forum_appr_last' => array('INDEX', array('forum_id', 'topic_approved', 'topic_last_post_id')), + 'fid_time_moved' => array('INDEX', array('forum_id', 'topic_last_post_time', 'topic_moved_id')), + ), + ), + + $this->table_prefix . 'topics_track' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'mark_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'topic_id'), + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + ), + ), + + $this->table_prefix . 'topics_posted' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'topic_posted' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'topic_id'), + ), + + $this->table_prefix . 'topics_watch' => array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'notify_status' => array('BOOL', 0), + ), + 'KEYS' => array( + 'topic_id' => array('INDEX', 'topic_id'), + 'user_id' => array('INDEX', 'user_id'), + 'notify_stat' => array('INDEX', 'notify_status'), + ), + ), + + $this->table_prefix . 'user_group' => array( + 'COLUMNS' => array( + 'group_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'group_leader' => array('BOOL', 0), + 'user_pending' => array('BOOL', 1), + ), + 'KEYS' => array( + 'group_id' => array('INDEX', 'group_id'), + 'user_id' => array('INDEX', 'user_id'), + 'group_leader' => array('INDEX', 'group_leader'), + ), + ), + + $this->table_prefix . 'users' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', NULL, 'auto_increment'), + 'user_type' => array('TINT:2', 0), + 'group_id' => array('UINT', 3), + 'user_permissions' => array('MTEXT', ''), + 'user_perm_from' => array('UINT', 0), + 'user_ip' => array('VCHAR:40', ''), + 'user_regdate' => array('TIMESTAMP', 0), + 'username' => array('VCHAR_CI', ''), + 'username_clean' => array('VCHAR_CI', ''), + 'user_password' => array('VCHAR_UNI:40', ''), + 'user_passchg' => array('TIMESTAMP', 0), + 'user_pass_convert' => array('BOOL', 0), + 'user_email' => array('VCHAR_UNI:100', ''), + 'user_email_hash' => array('BINT', 0), + 'user_birthday' => array('VCHAR:10', ''), + 'user_lastvisit' => array('TIMESTAMP', 0), + 'user_lastmark' => array('TIMESTAMP', 0), + 'user_lastpost_time' => array('TIMESTAMP', 0), + 'user_lastpage' => array('VCHAR_UNI:200', ''), + 'user_last_confirm_key' => array('VCHAR:10', ''), + 'user_last_search' => array('TIMESTAMP', 0), + 'user_warnings' => array('TINT:4', 0), + 'user_last_warning' => array('TIMESTAMP', 0), + 'user_login_attempts' => array('TINT:4', 0), + 'user_inactive_reason' => array('TINT:2', 0), + 'user_inactive_time' => array('TIMESTAMP', 0), + 'user_posts' => array('UINT', 0), + 'user_lang' => array('VCHAR:30', ''), + 'user_timezone' => array('DECIMAL', 0), + 'user_dst' => array('BOOL', 0), + 'user_dateformat' => array('VCHAR_UNI:30', 'd M Y H:i'), + 'user_style' => array('USINT', 0), + 'user_rank' => array('UINT', 0), + 'user_colour' => array('VCHAR:6', ''), + 'user_new_privmsg' => array('INT:4', 0), + 'user_unread_privmsg' => array('INT:4', 0), + 'user_last_privmsg' => array('TIMESTAMP', 0), + 'user_message_rules' => array('BOOL', 0), + 'user_full_folder' => array('INT:11', -3), + 'user_emailtime' => array('TIMESTAMP', 0), + 'user_topic_show_days' => array('USINT', 0), + 'user_topic_sortby_type' => array('VCHAR:1', 't'), + 'user_topic_sortby_dir' => array('VCHAR:1', 'd'), + 'user_post_show_days' => array('USINT', 0), + 'user_post_sortby_type' => array('VCHAR:1', 't'), + 'user_post_sortby_dir' => array('VCHAR:1', 'a'), + 'user_notify' => array('BOOL', 0), + 'user_notify_pm' => array('BOOL', 1), + 'user_notify_type' => array('TINT:4', 0), + 'user_allow_pm' => array('BOOL', 1), + 'user_allow_viewonline' => array('BOOL', 1), + 'user_allow_viewemail' => array('BOOL', 1), + 'user_allow_massemail' => array('BOOL', 1), + 'user_options' => array('UINT:11', 895), + 'user_avatar' => array('VCHAR', ''), + 'user_avatar_type' => array('TINT:2', 0), + 'user_avatar_width' => array('USINT', 0), + 'user_avatar_height' => array('USINT', 0), + 'user_sig' => array('MTEXT_UNI', ''), + 'user_sig_bbcode_uid' => array('VCHAR:8', ''), + 'user_sig_bbcode_bitfield' => array('VCHAR:255', ''), + 'user_from' => array('VCHAR_UNI:100', ''), + 'user_icq' => array('VCHAR:15', ''), + 'user_aim' => array('VCHAR_UNI', ''), + 'user_yim' => array('VCHAR_UNI', ''), + 'user_msnm' => array('VCHAR_UNI', ''), + 'user_jabber' => array('VCHAR_UNI', ''), + 'user_website' => array('VCHAR_UNI:200', ''), + 'user_occ' => array('TEXT_UNI', ''), + 'user_interests' => array('TEXT_UNI', ''), + 'user_actkey' => array('VCHAR:32', ''), + 'user_newpasswd' => array('VCHAR_UNI:40', ''), + 'user_form_salt' => array('VCHAR_UNI:32', ''), + + ), + 'PRIMARY_KEY' => 'user_id', + 'KEYS' => array( + 'user_birthday' => array('INDEX', 'user_birthday'), + 'user_email_hash' => array('INDEX', 'user_email_hash'), + 'user_type' => array('INDEX', 'user_type'), + 'username_clean' => array('UNIQUE', 'username_clean'), + ), + ), + + $this->table_prefix . 'warnings' => array( + 'COLUMNS' => array( + 'warning_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'post_id' => array('UINT', 0), + 'log_id' => array('UINT', 0), + 'warning_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'warning_id', + ), + + $this->table_prefix . 'words' => array( + 'COLUMNS' => array( + 'word_id' => array('UINT', NULL, 'auto_increment'), + 'word' => array('VCHAR_UNI', ''), + 'replacement' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'word_id', + ), + + $this->table_prefix . 'zebra' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'zebra_id' => array('UINT', 0), + 'friend' => array('BOOL', 0), + 'foe' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'zebra_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'attachments', + $this->table_prefix . 'acl_groups', + $this->table_prefix . 'acl_options', + $this->table_prefix . 'acl_roles', + $this->table_prefix . 'acl_roles_data', + $this->table_prefix . 'acl_users', + $this->table_prefix . 'banlist', + $this->table_prefix . 'bbcodes', + $this->table_prefix . 'bookmarks', + $this->table_prefix . 'bots', + $this->table_prefix . 'config', + $this->table_prefix . 'confirm', + $this->table_prefix . 'disallow', + $this->table_prefix . 'drafts', + $this->table_prefix . 'extensions', + $this->table_prefix . 'extension_groups', + $this->table_prefix . 'forums', + $this->table_prefix . 'forums_access', + $this->table_prefix . 'forums_track', + $this->table_prefix . 'forums_watch', + $this->table_prefix . 'groups', + $this->table_prefix . 'icons', + $this->table_prefix . 'lang', + $this->table_prefix . 'log', + $this->table_prefix . 'moderator_cache', + $this->table_prefix . 'modules', + $this->table_prefix . 'poll_options', + $this->table_prefix . 'poll_votes', + $this->table_prefix . 'posts', + $this->table_prefix . 'privmsgs', + $this->table_prefix . 'privmsgs_folder', + $this->table_prefix . 'privmsgs_rules', + $this->table_prefix . 'privmsgs_to', + $this->table_prefix . 'profile_fields', + $this->table_prefix . 'profile_fields_data', + $this->table_prefix . 'profile_fields_lang', + $this->table_prefix . 'profile_lang', + $this->table_prefix . 'ranks', + $this->table_prefix . 'reports', + $this->table_prefix . 'reports_reasons', + $this->table_prefix . 'search_results', + $this->table_prefix . 'search_wordlist', + $this->table_prefix . 'search_wordmatch', + $this->table_prefix . 'sessions', + $this->table_prefix . 'sessions_keys', + $this->table_prefix . 'sitelist', + $this->table_prefix . 'smilies', + $this->table_prefix . 'styles', + $this->table_prefix . 'styles_template', + $this->table_prefix . 'styles_template_data', + $this->table_prefix . 'styles_theme', + $this->table_prefix . 'styles_imageset', + $this->table_prefix . 'styles_imageset_data', + $this->table_prefix . 'topics', + $this->table_prefix . 'topics_track', + $this->table_prefix . 'topics_posted', + $this->table_prefix . 'topics_watch', + $this->table_prefix . 'user_group', + $this->table_prefix . 'users', + $this->table_prefix . 'warnings', + $this->table_prefix . 'words', + $this->table_prefix . 'zebra', + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php index c5b1681d96..2b65bb0185 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_1_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_1_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_10.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php index 640fcbc16f..d6f3029f7e 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_10.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_10 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_10 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_10 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_10_rc3'); + return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc3'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php index e0aca09c3a..0ee2a46a00 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_10_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_10_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_10_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_9'); + return array('\phpbb\db\migration\data\v30x\release_3_0_9'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php index 394e030acf..e676571a15 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_10_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_10_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_10_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_10_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php index 92900e3aed..d2656397a2 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_10_rc3.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_10_rc3 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_10_rc3 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_10_rc3 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_10_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_11.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php index 3be03cec40..6b7c9735fa 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_11.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_11 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_11 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_11 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11_rc2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_11_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php index f7b0247fdb..91ffae2f05 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_11_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_11_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_11_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_11_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_10'); + return array('\phpbb\db\migration\data\v30x\release_3_0_10'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_11_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php index 204aa314ac..55290dcbcf 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_11_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_11_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_11_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_11_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11_rc1'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php new file mode 100644 index 0000000000..c4bf3a30ef --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_12 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.0.12', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc3'); + } + + public function update_data() + { + return array( + array('if', array( + phpbb_version_compare($this->config['version'], '3.0.12', '<'), + array('config.update', array('version', '3.0.12')), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_12_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php index 31d37afa48..ab8463cc73 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_12_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php @@ -3,22 +3,24 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +namespace phpbb\db\migration\data\v30x; + /** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.12-RC1 **/ -class phpbb_db_migration_data_30x_3_0_12_rc1 extends phpbb_db_migration +class release_3_0_12_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { return phpbb_version_compare($this->config['version'], '3.0.12-RC1', '>='); } - static public function depends_on() + static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php new file mode 100644 index 0000000000..f41f20954a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_12_rc2 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.0.12-RC2', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc1'); + } + + public function update_data() + { + return array( + array('if', array( + phpbb_version_compare($this->config['version'], '3.0.12-RC2', '<'), + array('config.update', array('version', '3.0.12-RC2')), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php new file mode 100644 index 0000000000..9171ceb26f --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v30x; + +class release_3_0_12_rc3 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.0.12-RC3', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc2'); + } + + public function update_data() + { + return array( + array('if', array( + phpbb_version_compare($this->config['version'], '3.0.12-RC3', '<'), + array('config.update', array('version', '3.0.12-RC3')), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_1_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php index 984b8fb37e..724a61ecce 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_1_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php @@ -3,17 +3,24 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_1_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_1_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { return phpbb_version_compare($this->config['version'], '3.0.1-RC1', '>='); } + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_0'); + } + public function update_schema() { return array( diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php index 6e11e5a145..53792d4ce1 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_2_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_2_rc2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_2_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php index 9a25628f25..691ad44406 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_2_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_2_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_2_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_2_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_2_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php index 6c37d6701b..26fa4f015b 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_2_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_2_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_2_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_2_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_2_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_2_rc1'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php index 11fd2a2e80..5374e8786a 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_3.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_3 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_3 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_3 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_3_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_3_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_3_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php index cbeb00499a..367bf2c806 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_3_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_3_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_3_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_3_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_2'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php index 4375a96dac..94bba00079 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_4.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_4 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_4 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_4 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_4_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_4_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_4_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php index 73334dcc6f..98aafc6d43 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_4_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_4_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_4_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_4_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_3'); + return array('\phpbb\db\migration\data\v30x\release_3_0_3'); } public function update_schema() @@ -82,7 +84,7 @@ class phpbb_db_migration_data_30x_3_0_4_rc1 extends phpbb_db_migration public function update_custom_profile_fields() { - // Update the Custom Profile Fields based on previous settings to the new format + // Update the Custom Profile Fields based on previous settings to the new \format $sql = 'SELECT field_id, field_required, field_show_on_reg, field_hide FROM ' . PROFILE_FIELDS_TABLE; $result = $this->db->sql_query($sql); diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_5.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php index 2700274f35..92555adf78 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_5.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_5 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_5 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_5 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_5_rc1part2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_5_rc1part2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php index 90c6b3b46a..c6b77bc379 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_5_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_5_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_5_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_5_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_4'); + return array('\phpbb\db\migration\data\v30x\release_3_0_4'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_5_rc1part2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php index 2d1e5cfed8..b56721bd80 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_5_rc1part2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_5_rc1part2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_5_rc1part2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_5_rc1part2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_5_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_5_rc1'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_6.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php index 1877b0c5a1..fb0957fc45 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_6.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_6 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_6 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_6 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_6_rc4'); + return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc4'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php index 3e2a9544c7..12b0122237 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_6_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_6_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_5'); + return array('\phpbb\db\migration\data\v30x\release_3_0_5'); } public function update_schema() @@ -318,7 +320,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc1 extends phpbb_db_migration // Clear permissions... include_once($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext); - $auth_admin = new auth_admin(); + $auth_admin = new \auth_admin(); $auth_admin->acl_clear_prefetch(); } } diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php index 439e25b100..351079e96c 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_6_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_6_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_6_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php index 77b62d7fc7..1ccfa1cb37 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc3.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_6_rc3 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_6_rc3 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc3 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_6_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc2'); } public function update_data() @@ -30,7 +32,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc3 extends phpbb_db_migration public function update_cp_fields() { - // Update the Custom Profile Fields based on previous settings to the new format + // Update the Custom Profile Fields based on previous settings to the new \format $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . ' SET field_show_on_vt = 1 WHERE field_hide = 0 diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php index 61a31d09e6..6451f4fe02 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_6_rc4.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_6_rc4 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_6_rc4 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_6_rc4 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_6_rc3'); + return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc3'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_7.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php index 3eb1caddbc..70cb1293e6 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_7.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_7 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_7 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_7 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_7_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_7_rc2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_7_pl1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php index c7b5c584ac..db2175a99a 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_7_pl1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_7_pl1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_7_pl1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_7_pl1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_7'); + return array('\phpbb\db\migration\data\v30x\release_3_0_7'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_7_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php index e0fd313834..3bdedf8c57 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_7_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_7_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_7_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_7_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_6'); + return array('\phpbb\db\migration\data\v30x\release_3_0_6'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_7_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php index f4f3327385..65ad905aa7 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_7_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_7_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_7_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_7_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_7_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_7_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_8.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php index 77771a9acd..c1e49f1dde 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_8.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_8 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_8 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_8 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_8_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_8_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_8_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php index c534cabb6c..e3c232f9e4 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_8_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_8_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_8_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_8_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_7_pl1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_7_pl1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_9.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php index 6a38793269..34e85f010a 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_9.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_9 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_9 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_9 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_9_rc4'); + return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc4'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php index 81c67550bd..79ef839005 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_9_rc1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_9_rc1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_9_rc1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_8'); + return array('\phpbb\db\migration\data\v30x\release_3_0_8'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php index 1531f408b7..1eb7837faf 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc2.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_9_rc2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_9_rc2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_9_rc2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_9_rc1'); + return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc1'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php index 851680b093..bbeb76509f 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc3.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_9_rc3 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_9_rc3 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_9_rc3 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_9_rc2'); + return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc2'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php index 879538c341..bc75891f4d 100644 --- a/phpBB/phpbb/db/migration/data/30x/3_0_9_rc4.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_30x_3_0_9_rc4 extends phpbb_db_migration +namespace phpbb\db\migration\data\v30x; + +class release_3_0_9_rc4 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_30x_3_0_9_rc4 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_9_rc3'); + return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc3'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php new file mode 100644 index 0000000000..aa44222cd8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php @@ -0,0 +1,77 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class acp_prune_users_module extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + $sql = 'SELECT module_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'acp' + AND module_langname = 'ACP_CAT_USERS'"; + $result = $this->db->sql_query($sql); + $acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + $sql = 'SELECT parent_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'acp' + AND module_basename = 'acp_prune' + AND module_mode = 'users'"; + $result = $this->db->sql_query($sql); + $acp_prune_users_parent = (int) $this->db->sql_fetchfield('parent_id'); + $this->db->sql_freeresult($result); + + // Skip migration if "Users" category has been deleted + // or the module has already been moved to that category + return !$acp_cat_users_id || $acp_cat_users_id === $acp_prune_users_parent; + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\beta1'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'move_prune_users_module'))), + ); + } + + public function move_prune_users_module() + { + $sql = 'SELECT module_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'acp' + AND module_basename = 'acp_prune' + AND module_mode = 'users'"; + $result = $this->db->sql_query($sql); + $acp_prune_users_id = (int) $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + $sql = 'SELECT module_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'acp' + AND module_langname = 'ACP_CAT_USERS'"; + $result = $this->db->sql_query($sql); + $acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + if (!class_exists('\acp_modules')) + { + include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); + } + $module_manager = new \acp_modules(); + $module_manager->module_class = 'acp'; + $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/acp_style_components_module.php b/phpBB/phpbb/db/migration/data/v310/acp_style_components_module.php new file mode 100644 index 0000000000..9f168f4fd6 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/acp_style_components_module.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class acp_style_components_module extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + $sql = 'SELECT module_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'acp' + AND module_langname = 'ACP_STYLE_COMPONENTS'"; + $result = $this->db->sql_query($sql); + $module_id = $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + return $module_id == false; + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\dev'); + } + + public function update_data() + { + return array( + array('module.remove', array( + 'acp', + false, + 'ACP_STYLE_COMPONENTS', + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/allow_cdn.php b/phpBB/phpbb/db/migration/data/v310/allow_cdn.php new file mode 100644 index 0000000000..2cb9e58767 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/allow_cdn.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class allow_cdn extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return isset($this->config['allow_cdn']); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\jquery_update', + ); + } + + public function update_data() + { + return array( + array('config.add', array('allow_cdn', (int) $this->config['load_jquery_cdn'])), + array('config.remove', array('load_jquery_cdn')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/alpha1.php b/phpBB/phpbb/db/migration/data/v310/alpha1.php new file mode 100644 index 0000000000..704f5a7a29 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/alpha1.php @@ -0,0 +1,44 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class alpha1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v30x\local_url_bbcode', + '\phpbb\db\migration\data\v30x\release_3_0_12', + '\phpbb\db\migration\data\v310\acp_style_components_module', + '\phpbb\db\migration\data\v310\allow_cdn', + '\phpbb\db\migration\data\v310\auth_provider_oauth', + '\phpbb\db\migration\data\v310\avatars', + '\phpbb\db\migration\data\v310\boardindex', + '\phpbb\db\migration\data\v310\config_db_text', + '\phpbb\db\migration\data\v310\forgot_password', + '\phpbb\db\migration\data\v310\mod_rewrite', + '\phpbb\db\migration\data\v310\mysql_fulltext_drop', + '\phpbb\db\migration\data\v310\namespaces', + '\phpbb\db\migration\data\v310\notifications_cron', + '\phpbb\db\migration\data\v310\notification_options_reconvert', + '\phpbb\db\migration\data\v310\plupload', + '\phpbb\db\migration\data\v310\signature_module_auth', + '\phpbb\db\migration\data\v310\softdelete_mcp_modules', + '\phpbb\db\migration\data\v310\teampage', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-a1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/alpha2.php b/phpBB/phpbb/db/migration/data/v310/alpha2.php new file mode 100644 index 0000000000..3c0853f924 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/alpha2.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class alpha2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\alpha1', + '\phpbb\db\migration\data\v310\notifications_cron_p2', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-a2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/alpha3.php b/phpBB/phpbb/db/migration/data/v310/alpha3.php new file mode 100644 index 0000000000..4bd2231bb9 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/alpha3.php @@ -0,0 +1,30 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class alpha3 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\alpha2', + '\phpbb\db\migration\data\v310\avatar_types', + '\phpbb\db\migration\data\v310\passwords', + '\phpbb\db\migration\data\v310\profilefield_types', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-a3')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php new file mode 100644 index 0000000000..daca99c255 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php @@ -0,0 +1,73 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class auth_provider_oauth extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->db_tools->sql_table_exists($this->table_prefix . 'auth_provider_oauth'); + } + + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'oauth_tokens' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), // phpbb_users.user_id + 'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set + 'provider' => array('VCHAR', ''), // Name of the OAuth provider + 'oauth_token' => array('MTEXT', ''), // Serialized token + ), + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + 'provider' => array('INDEX', 'provider'), + ), + ), + $this->table_prefix . 'oauth_accounts' => array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'provider' => array('VCHAR', ''), + 'oauth_provider_id' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => array( + 'user_id', + 'provider', + ), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'oauth_tokens', + $this->table_prefix . 'oauth_accounts', + ), + ); + } + + public function update_data() + { + return array( + array('module.add', array( + 'ucp', + 'UCP_PROFILE', + array( + 'module_basename' => 'ucp_auth_link', + 'modes' => array('auth_link'), + ), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php new file mode 100644 index 0000000000..692647dcde --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class auth_provider_oauth2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\auth_provider_oauth', + ); + } + + public function update_data() + { + return array( + array('custom', array( + array($this, 'update_auth_link_module_auth'), + )), + ); + } + + public function update_auth_link_module_auth() + { + $sql = 'UPDATE ' . MODULES_TABLE . " + SET module_auth = 'authmethod_oauth' + WHERE module_class = 'ucp' + AND module_basename = 'ucp_auth_link' + AND module_mode = 'auth_link' + AND module_auth = ''"; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/avatar_types.php b/phpBB/phpbb/db/migration/data/v310/avatar_types.php new file mode 100644 index 0000000000..17bb1f26ca --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/avatar_types.php @@ -0,0 +1,60 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class avatar_types extends \phpbb\db\migration\migration +{ + /** + * @var avatar type map + */ + protected $avatar_type_map = array( + AVATAR_UPLOAD => 'avatar.driver.upload', + AVATAR_REMOTE => 'avatar.driver.remote', + AVATAR_GALLERY => 'avatar.driver.local', + ); + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + '\phpbb\db\migration\data\v310\avatars', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_user_avatar_type'))), + array('custom', array(array($this, 'update_group_avatar_type'))), + ); + } + + public function update_user_avatar_type() + { + foreach ($this->avatar_type_map as $old => $new) + { + $sql = 'UPDATE ' . $this->table_prefix . "users + SET user_avatar_type = '$new' + WHERE user_avatar_type = '$old'"; + $this->db->sql_query($sql); + } + } + + public function update_group_avatar_type() + { + foreach ($this->avatar_type_map as $old => $new) + { + $sql = 'UPDATE ' . $this->table_prefix . "groups + SET group_avatar_type = '$new' + WHERE group_avatar_type = '$old'"; + $this->db->sql_query($sql); + } + } +} diff --git a/phpBB/phpbb/db/migration/data/310/avatars.php b/phpBB/phpbb/db/migration/data/v310/avatars.php index 79547337f7..b6cd914dd9 100644 --- a/phpBB/phpbb/db/migration/data/310/avatars.php +++ b/phpBB/phpbb/db/migration/data/v310/avatars.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_avatars extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class avatars extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_avatars extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/v310/beta1.php b/phpBB/phpbb/db/migration/data/v310/beta1.php new file mode 100644 index 0000000000..36d0c62b6f --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/beta1.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class beta1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\alpha3', + '\phpbb\db\migration\data\v310\passwords_p2', + '\phpbb\db\migration\data\v310\postgres_fulltext_drop', + '\phpbb\db\migration\data\v310\profilefield_change_load_settings', + '\phpbb\db\migration\data\v310\profilefield_location', + '\phpbb\db\migration\data\v310\soft_delete_mod_convert2', + '\phpbb\db\migration\data\v310\ucp_popuppm_module', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-b1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/beta2.php b/phpBB/phpbb/db/migration/data/v310/beta2.php new file mode 100644 index 0000000000..4cf29dfb3d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/beta2.php @@ -0,0 +1,29 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class beta2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\beta1', + '\phpbb\db\migration\data\v310\acp_prune_users_module', + '\phpbb\db\migration\data\v310\profilefield_location_cleanup', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-b2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/board_contact_name.php b/phpBB/phpbb/db/migration/data/v310/board_contact_name.php new file mode 100644 index 0000000000..37b4d50545 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/board_contact_name.php @@ -0,0 +1,30 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class board_contact_name extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return isset($this->config['board_contact_name']); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\beta2'); + } + + public function update_data() + { + return array( + array('config.add', array('board_contact_name', '')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/310/boardindex.php b/phpBB/phpbb/db/migration/data/v310/boardindex.php index 965e32c15c..17040a60b8 100644 --- a/phpBB/phpbb/db/migration/data/310/boardindex.php +++ b/phpBB/phpbb/db/migration/data/v310/boardindex.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_boardindex extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class boardindex extends \phpbb\db\migration\migration { public function effectively_installed() { diff --git a/phpBB/phpbb/db/migration/data/310/config_db_text.php b/phpBB/phpbb/db/migration/data/v310/config_db_text.php index 89f211adda..49f30d289f 100644 --- a/phpBB/phpbb/db/migration/data/310/config_db_text.php +++ b/phpBB/phpbb/db/migration/data/v310/config_db_text.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_config_db_text extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class config_db_text extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_config_db_text extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/310/dev.php b/phpBB/phpbb/db/migration/data/v310/dev.php index 0fc2950987..da78db7b89 100644 --- a/phpBB/phpbb/db/migration/data/310/dev.php +++ b/phpBB/phpbb/db/migration/data/v310/dev.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_dev extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class dev extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -17,10 +19,11 @@ class phpbb_db_migration_data_310_dev extends phpbb_db_migration static public function depends_on() { return array( - 'phpbb_db_migration_data_310_extensions', - 'phpbb_db_migration_data_310_style_update_p2', - 'phpbb_db_migration_data_310_timezone_p2', - 'phpbb_db_migration_data_310_reported_posts_display', + '\phpbb\db\migration\data\v310\extensions', + '\phpbb\db\migration\data\v310\style_update_p2', + '\phpbb\db\migration\data\v310\timezone_p2', + '\phpbb\db\migration\data\v310\reported_posts_display', + '\phpbb\db\migration\data\v310\migrations_table', ); } @@ -206,7 +209,7 @@ class phpbb_db_migration_data_310_dev extends phpbb_db_migration { include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext); } - $module_manager = new acp_modules(); + $module_manager = new \acp_modules(); $module_manager->module_class = 'acp'; $module_manager->move_module($language_module_id, $language_management_module_id); } diff --git a/phpBB/phpbb/db/migration/data/310/extensions.php b/phpBB/phpbb/db/migration/data/v310/extensions.php index 6a9caa1cfc..a0d57087d4 100644 --- a/phpBB/phpbb/db/migration/data/310/extensions.php +++ b/phpBB/phpbb/db/migration/data/v310/extensions.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_extensions extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class extensions extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_extensions extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/310/forgot_password.php b/phpBB/phpbb/db/migration/data/v310/forgot_password.php index a553e51f35..523f4e2c0a 100644 --- a/phpBB/phpbb/db/migration/data/310/forgot_password.php +++ b/phpBB/phpbb/db/migration/data/v310/forgot_password.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_forgot_password extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class forgot_password extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_forgot_password extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/310/jquery_update.php b/phpBB/phpbb/db/migration/data/v310/jquery_update.php index dc49f74fcb..187d6b876a 100644 --- a/phpBB/phpbb/db/migration/data/310/jquery_update.php +++ b/phpBB/phpbb/db/migration/data/v310/jquery_update.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_jquery_update extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class jquery_update extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -17,7 +19,7 @@ class phpbb_db_migration_data_310_jquery_update extends phpbb_db_migration static public function depends_on() { return array( - 'phpbb_db_migration_data_310_dev', + '\phpbb\db\migration\data\v310\dev', ); } diff --git a/phpBB/phpbb/db/migration/data/v310/jquery_update2.php b/phpBB/phpbb/db/migration/data/v310/jquery_update2.php new file mode 100644 index 0000000000..46a115d8ad --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/jquery_update2.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class jquery_update2 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'; + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\jquery_update', + ); + } + + public function update_data() + { + return array( + array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js')), + ); + } + +} diff --git a/phpBB/phpbb/db/migration/data/v310/migrations_table.php b/phpBB/phpbb/db/migration/data/v310/migrations_table.php new file mode 100644 index 0000000000..e70fd35819 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/migrations_table.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class migrations_table extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->db_tools->sql_table_exists($this->table_prefix . 'migrations'); + } + + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'migrations' => array( + 'COLUMNS' => array( + 'migration_name' => array('VCHAR', ''), + 'migration_depends_on' => array('TEXT', ''), + 'migration_schema_done' => array('BOOL', 0), + 'migration_data_done' => array('BOOL', 0), + 'migration_data_state' => array('TEXT', ''), + 'migration_start_time' => array('TIMESTAMP', 0), + 'migration_end_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'migration_name', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'migrations', + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php b/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php new file mode 100644 index 0000000000..e7d71f63e3 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php @@ -0,0 +1,27 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class mod_rewrite extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_data() + { + return array( + array('config.add', array('enable_mod_rewrite', '0')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php new file mode 100644 index 0000000000..97d174d4bc --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class mysql_fulltext_drop extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + // This migration is irrelevant for all non-MySQL DBMSes. + return strpos($this->db->sql_layer, 'mysql') === false; + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_schema() + { + /* + * Drop FULLTEXT indexes related to MySQL fulltext search. + * Doing so is equivalent to dropping the search index from the ACP. + * Possibly time-consuming recreation of the search index (i.e. + * FULLTEXT indexes) is left as a task to the admin to not + * unnecessarily stall the upgrade process. The new search index will + * then require about 40% less table space (also see PHPBB3-11621). + */ + return array( + 'drop_keys' => array( + $this->table_prefix . 'posts' => array( + 'post_subject', + 'post_text', + 'post_content', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/namespaces.php b/phpBB/phpbb/db/migration/data/v310/namespaces.php new file mode 100644 index 0000000000..aa0b2bbfac --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/namespaces.php @@ -0,0 +1,30 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class namespaces extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_data() + { + return array( + array('if', array( + (preg_match('#^phpbb_search_#', $this->config['search_type'])), + array('config.update', array('search_type', str_replace('phpbb_search_', '\\phpbb\\search\\', $this->config['search_type']))), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/310/notification_options_reconvert.php b/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php index d994d7ec5f..4195623618 100644 --- a/phpBB/phpbb/db/migration/data/310/notification_options_reconvert.php +++ b/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php @@ -7,45 +7,56 @@ * */ -class phpbb_db_migration_data_310_notification_options_reconvert extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class notification_options_reconvert extends \phpbb\db\migration\migration { static public function depends_on() { - return array('phpbb_db_migration_data_310_notifications_schema_fix'); + return array('\phpbb\db\migration\data\v310\notifications_schema_fix'); } public function update_data() { return array( + array('custom', array(array($this, 'purge_notifications'))), array('custom', array(array($this, 'convert_notifications'))), ); } - public function convert_notifications() + public function purge_notifications() + { + $sql = 'DELETE FROM ' . $this->table_prefix . 'user_notifications'; + $this->sql_query($sql); + } + + public function convert_notifications($start) { - $insert_table = $this->table_prefix . 'user_notifications'; - $insert_buffer = new phpbb_db_sql_insert_buffer($this->db, $insert_table); + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'user_notifications'); - $this->perform_conversion($insert_buffer, $insert_table); + return $this->perform_conversion($insert_buffer, $start); } /** * Perform the conversion (separate for testability) * - * @param phpbb_db_sql_insert_buffer $insert_buffer - * @param string $insert_table + * @param \phpbb\db\sql_insert_buffer $insert_buffer + * @param int $start Start of staggering step + * @return mixed int start of the next step, null if the end was reached */ - public function perform_conversion(phpbb_db_sql_insert_buffer $insert_buffer, $insert_table) + public function perform_conversion(\phpbb\db\sql_insert_buffer $insert_buffer, $start) { - $sql = 'DELETE FROM ' . $insert_table; - $this->db->sql_query($sql); + $limit = 250; + $converted_users = 0; $sql = 'SELECT user_id, user_notify_type, user_notify_pm - FROM ' . USERS_TABLE; - $result = $this->db->sql_query($sql); + FROM ' . $this->table_prefix . 'users + ORDER BY user_id'; + $result = $this->db->sql_query_limit($sql, $limit, $start); while ($row = $this->db->sql_fetchrow($result)) { + $converted_users++; $notification_methods = array(); // In-board notification @@ -89,18 +100,26 @@ class phpbb_db_migration_data_310_notification_options_reconvert extends phpbb_d $this->db->sql_freeresult($result); $insert_buffer->flush(); + + if ($converted_users < $limit) + { + // No more users left, we are done... + return; + } + + return $start + $limit; } /** * Insert method rows to DB * - * @param phpbb_db_sql_insert_buffer $insert_buffer + * @param \phpbb\db\sql_insert_buffer $insert_buffer * @param string $item_type * @param int $item_id * @param int $user_id * @param string $methods */ - protected function add_method_rows(phpbb_db_sql_insert_buffer $insert_buffer, $item_type, $item_id, $user_id, array $methods) + protected function add_method_rows(\phpbb\db\sql_insert_buffer $insert_buffer, $item_type, $item_id, $user_id, array $methods) { $row_base = array( 'item_type' => $item_type, diff --git a/phpBB/phpbb/db/migration/data/310/notifications.php b/phpBB/phpbb/db/migration/data/v310/notifications.php index 17c939d95a..cf26436ccb 100644 --- a/phpBB/phpbb/db/migration/data/310/notifications.php +++ b/phpBB/phpbb/db/migration/data/v310/notifications.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_notifications extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class notifications extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_notifications extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_310_dev'); + return array('\phpbb\db\migration\data\v310\dev'); } public function update_schema() @@ -32,7 +34,7 @@ class phpbb_db_migration_data_310_notifications extends phpbb_db_migration ), $this->table_prefix . 'notifications' => array( 'COLUMNS' => array( - 'notification_id' => array('UINT', NULL, 'auto_increment'), + 'notification_id' => array('UINT', null, 'auto_increment'), 'item_type' => array('VCHAR:255', ''), 'item_id' => array('UINT', 0), 'item_parent_id' => array('UINT', 0), diff --git a/phpBB/phpbb/db/migration/data/v310/notifications_cron.php b/phpBB/phpbb/db/migration/data/v310/notifications_cron.php new file mode 100644 index 0000000000..d5fa9c58a5 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/notifications_cron.php @@ -0,0 +1,27 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class notifications_cron extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\notifications'); + } + + public function update_data() + { + return array( + array('config.add', array('read_notification_expire_days', 30)), + array('config.add', array('read_notification_last_gc', 0)), // last run + array('config.add', array('read_notification_gc', (60 * 60 * 24))), // seconds between run; 1 day + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/notifications_cron_p2.php b/phpBB/phpbb/db/migration/data/v310/notifications_cron_p2.php new file mode 100644 index 0000000000..050e679cc0 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/notifications_cron_p2.php @@ -0,0 +1,27 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class notifications_cron_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\notifications_cron'); + } + + public function update_data() + { + return array( + // Make read_notification_last_gc dynamic. + array('config.remove', array('read_notification_last_gc')), + array('config.add', array('read_notification_last_gc', 0, 1)), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/310/notifications_schema_fix.php b/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php index 27e63e10d0..a9d11d384c 100644 --- a/phpBB/phpbb/db/migration/data/310/notifications_schema_fix.php +++ b/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php @@ -3,15 +3,17 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_notifications_schema_fix extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class notifications_schema_fix extends \phpbb\db\migration\migration { static public function depends_on() { - return array('phpbb_db_migration_data_310_notifications'); + return array('\phpbb\db\migration\data\v310\notifications'); } public function update_schema() @@ -24,7 +26,7 @@ class phpbb_db_migration_data_310_notifications_schema_fix extends phpbb_db_migr 'add_tables' => array( $this->table_prefix . 'notification_types' => array( 'COLUMNS' => array( - 'notification_type_id' => array('USINT', NULL, 'auto_increment'), + 'notification_type_id' => array('USINT', null, 'auto_increment'), 'notification_type_name' => array('VCHAR:255', ''), 'notification_type_enabled' => array('BOOL', 1), ), @@ -35,7 +37,7 @@ class phpbb_db_migration_data_310_notifications_schema_fix extends phpbb_db_migr ), $this->table_prefix . 'notifications' => array( 'COLUMNS' => array( - 'notification_id' => array('UINT:10', NULL, 'auto_increment'), + 'notification_id' => array('UINT:10', null, 'auto_increment'), 'notification_type_id' => array('USINT', 0), 'item_id' => array('UINT', 0), 'item_parent_id' => array('UINT', 0), @@ -71,7 +73,7 @@ class phpbb_db_migration_data_310_notifications_schema_fix extends phpbb_db_migr ), $this->table_prefix . 'notifications' => array( 'COLUMNS' => array( - 'notification_id' => array('UINT', NULL, 'auto_increment'), + 'notification_id' => array('UINT', null, 'auto_increment'), 'item_type' => array('VCHAR:255', ''), 'item_id' => array('UINT', 0), 'item_parent_id' => array('UINT', 0), diff --git a/phpBB/phpbb/db/migration/data/v310/passwords.php b/phpBB/phpbb/db/migration/data/v310/passwords.php new file mode 100644 index 0000000000..2bba9b7a70 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/passwords.php @@ -0,0 +1,46 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class passwords extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:255', ''), + ), + $this->table_prefix . 'forums' => array( + 'forum_password' => array('VCHAR:255', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:40', ''), + ), + $this->table_prefix . 'forums' => array( + 'forum_password' => array('VCHAR:40', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_p2.php b/phpBB/phpbb/db/migration/data/v310/passwords_p2.php new file mode 100644 index 0000000000..2768c8975d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/passwords_p2.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class passwords_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\passwords'); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_newpasswd' => array('VCHAR:255', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_newpasswd' => array('VCHAR:40', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/plupload.php b/phpBB/phpbb/db/migration/data/v310/plupload.php new file mode 100644 index 0000000000..7cdba507a2 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/plupload.php @@ -0,0 +1,32 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class plupload extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return isset($this->config['plupload_last_gc']) && + isset($this->config['plupload_salt']); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\dev'); + } + + public function update_data() + { + return array( + array('config.add', array('plupload_last_gc', 0)), + array('config.add', array('plupload_salt', unique_id())), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php new file mode 100644 index 0000000000..7d4aea3c95 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class postgres_fulltext_drop extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + // This migration is irrelevant for all non-PostgreSQL DBMSes. + return strpos($this->db->sql_layer, 'postgres') === false; + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_schema() + { + /* + * Drop FULLTEXT indexes related to PostgreSQL fulltext search. + * Doing so is equivalent to dropping the search index from the ACP. + * Possibly time-consuming recreation of the search index (i.e. + * FULLTEXT indexes) is left as a task to the admin to not + * unnecessarily stall the upgrade process. The new search index will + * then require about 40% less table space (also see PHPBB3-11040). + */ + return array( + 'drop_keys' => array( + $this->table_prefix . 'posts' => array( + 'post_subject', + 'post_text', + 'post_content', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php b/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php new file mode 100644 index 0000000000..87574cb858 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_aol extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_yahoo_cleanup', + ); + } + + protected $profilefield_name = 'phpbb_aol'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_aol', + 'field_type' => 'profilefields.type.string', + 'field_ident' => 'phpbb_aol', + 'field_length' => '40', + 'field_minlen' => '5', + 'field_maxlen' => '255', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_on_ml' => 0, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + 'field_is_contact' => 1, + 'field_contact_desc' => '', + 'field_contact_url' => '', + ); + + protected $user_column_name = 'user_aim'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php new file mode 100644 index 0000000000..a7088c6a7a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_aol_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_aim'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_aol', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_aim', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_aim' => array('VCHAR_UNI', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php b/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php new file mode 100644 index 0000000000..7d09d8149a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php @@ -0,0 +1,30 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_change_load_settings extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_aol_cleanup', + ); + } + + public function update_data() + { + return array( + array('config.update', array('load_cpf_memberlist', '1')), + array('config.update', array('load_cpf_pm', '1')), + array('config.update', array('load_cpf_viewprofile', '1')), + array('config.update', array('load_cpf_viewtopic', '1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php new file mode 100644 index 0000000000..625e74fba1 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_occ') && + !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_interests'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_interests', + '\phpbb\db\migration\data\v310\profilefield_occupation', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_occ', + 'user_interests', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_occ' => array('MTEXT', ''), + 'user_interests' => array('MTEXT', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php b/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php new file mode 100644 index 0000000000..c7617813eb --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_contact_field extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_is_contact'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_on_memberlist', + ); + } + + public function update_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_is_contact' => array('BOOL', 0), + 'field_contact_desc' => array('VCHAR', ''), + 'field_contact_url' => array('VCHAR', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_is_contact', + 'field_contact_desc', + 'field_contact_url', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php b/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php new file mode 100644 index 0000000000..2c8c8c511f --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php @@ -0,0 +1,50 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_icq extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_contact_field', + ); + } + + protected $profilefield_name = 'phpbb_icq'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_icq', + 'field_type' => 'profilefields.type.string', + 'field_ident' => 'phpbb_icq', + 'field_length' => '20', + 'field_minlen' => '3', + 'field_maxlen' => '15', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '[0-9]+', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + 'field_is_contact' => 1, + 'field_contact_desc' => 'SEND_ICQ_MESSAGE', + 'field_contact_url' => 'https://www.icq.com/people/%s/', + ); + + protected $user_column_name = 'user_icq'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php new file mode 100644 index 0000000000..0129a7248f --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_icq_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_icq'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_icq', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_icq', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_icq' => array('VCHAR:20', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php b/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php new file mode 100644 index 0000000000..53fae2ea1a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php @@ -0,0 +1,48 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_interests extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_show_novalue', + ); + } + + protected $profilefield_name = 'phpbb_interests'; + + protected $profilefield_database_type = array('MTEXT', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_interests', + 'field_type' => 'profilefields.type.text', + 'field_ident' => 'phpbb_interests', + 'field_length' => '3|30', + 'field_minlen' => '2', + 'field_maxlen' => '500', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 0, + 'field_show_on_vt' => 0, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + ); + + protected $user_column_name = 'user_interests'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_location.php b/phpBB/phpbb/db/migration/data/v310/profilefield_location.php new file mode 100644 index 0000000000..f4db79ca5e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_location.php @@ -0,0 +1,48 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_location extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_types', + '\phpbb\db\migration\data\v310\profilefield_on_memberlist', + ); + } + + protected $profilefield_name = 'phpbb_location'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_location', + 'field_type' => 'profilefields.type.string', + 'field_ident' => 'phpbb_location', + 'field_length' => '20', + 'field_minlen' => '2', + 'field_maxlen' => '100', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + ); + + protected $user_column_name = 'user_from'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php new file mode 100644 index 0000000000..54ff2a31eb --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_location_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_from'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_location', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_from', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_from' => array('VCHAR_UNI:100', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php b/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php new file mode 100644 index 0000000000..9a710fbcbc --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_occupation extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_interests', + ); + } + + protected $profilefield_name = 'phpbb_occupation'; + + protected $profilefield_database_type = array('MTEXT', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_occupation', + 'field_type' => 'profilefields.type.text', + 'field_ident' => 'phpbb_occupation', + 'field_length' => '3|30', + 'field_minlen' => '2', + 'field_maxlen' => '500', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 0, + 'field_show_on_vt' => 0, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + ); + + protected $user_column_name = 'user_occ'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php b/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php new file mode 100644 index 0000000000..4733b7713d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_on_memberlist extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_show_on_ml'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_cleanup', + ); + } + + public function update_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_show_on_ml' => array('BOOL', 0), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_show_on_ml', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php b/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php new file mode 100644 index 0000000000..d37103e2ce --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php @@ -0,0 +1,45 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_show_novalue extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_show_novalue'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\profilefield_types'); + } + + public function update_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_show_novalue' => array('BOOL', 0), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_show_novalue', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_types.php b/phpBB/phpbb/db/migration/data/v310/profilefield_types.php new file mode 100644 index 0000000000..9b54d87c9a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_types.php @@ -0,0 +1,106 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_types extends \phpbb\db\migration\migration +{ + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\alpha2', + ); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'profile_fields' => array( + 'field_type' => array('VCHAR:100', ''), + ), + $this->table_prefix . 'profile_fields_lang' => array( + 'field_type' => array('VCHAR:100', ''), + ), + ), + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_profile_fields_type'))), + array('custom', array(array($this, 'update_profile_fields_lang_type'))), + ); + } + + public function update_profile_fields_type() + { + // Update profile field types + $sql = 'SELECT field_type + FROM ' . $this->table_prefix . 'profile_fields + GROUP BY field_type'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $sql = 'UPDATE ' . $this->table_prefix . "profile_fields + SET field_type = '" . $this->db->sql_escape($this->convert_phpbb30_field_type($row['field_type'])) . "' + WHERE field_type = '" . $this->db->sql_escape($row['field_type']) . "'"; + $this->sql_query($sql); + } + $this->db->sql_freeresult($result); + } + + public function update_profile_fields_lang_type() + { + // Update profile field language types + $sql = 'SELECT field_type + FROM ' . $this->table_prefix . 'profile_fields_lang + GROUP BY field_type'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $sql = 'UPDATE ' . $this->table_prefix . "profile_fields_lang + SET field_type = '" . $this->db->sql_escape($this->convert_phpbb30_field_type($row['field_type'])) . "' + WHERE field_type = '" . $this->db->sql_escape($row['field_type']) . "'"; + $this->sql_query($sql); + } + $this->db->sql_freeresult($result); + } + + /** + * Determine the new field type for a given phpBB 3.0 field type + * + * @param $field_type string Field type in 3.0 + * @return string Field new type which is used since 3.1 + */ + public function convert_phpbb30_field_type($field_type) + { + switch ($field_type) + { + case FIELD_INT: + return 'profilefields.type.int'; + case FIELD_STRING: + return 'profilefields.type.string'; + case FIELD_TEXT: + return 'profilefields.type.text'; + case FIELD_BOOL: + return 'profilefields.type.bool'; + case FIELD_DROPDOWN: + return 'profilefields.type.dropdown'; + case FIELD_DATE: + return 'profilefields.type.date'; + default: + return $field_type; + } + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_website.php b/phpBB/phpbb/db/migration/data/v310/profilefield_website.php new file mode 100644 index 0000000000..818b66d2e4 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_website.php @@ -0,0 +1,52 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_website extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_on_memberlist', + '\phpbb\db\migration\data\v310\profilefield_icq_cleanup', + ); + } + + protected $profilefield_name = 'phpbb_website'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_website', + 'field_type' => 'profilefields.type.url', + 'field_ident' => 'phpbb_website', + 'field_length' => '40', + 'field_minlen' => '12', + 'field_maxlen' => '255', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_on_ml' => 1, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + 'field_is_contact' => 1, + 'field_contact_desc' => 'VISIT_WEBSITE', + 'field_contact_url' => '%s', + ); + + protected $user_column_name = 'user_website'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php new file mode 100644 index 0000000000..35cc92199e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_website_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_website'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_website', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_website', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_website' => array('VCHAR_UNI:200', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php new file mode 100644 index 0000000000..8a42f1fea1 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_wlm extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_website_cleanup', + ); + } + + protected $profilefield_name = 'phpbb_wlm'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_wlm', + 'field_type' => 'profilefields.type.string', + 'field_ident' => 'phpbb_wlm', + 'field_length' => '40', + 'field_minlen' => '5', + 'field_maxlen' => '255', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_on_ml' => 0, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + 'field_is_contact' => 1, + 'field_contact_desc' => '', + 'field_contact_url' => '', + ); + + protected $user_column_name = 'user_msnm'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php new file mode 100644 index 0000000000..98b92eb188 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_wlm_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_msnm'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_wlm', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_msnm', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_msnm' => array('VCHAR_UNI', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php new file mode 100644 index 0000000000..808aec8099 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_yahoo extends \phpbb\db\migration\profilefield_base_migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_wlm_cleanup', + ); + } + + protected $profilefield_name = 'phpbb_yahoo'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_yahoo', + 'field_type' => 'profilefields.type.string', + 'field_ident' => 'phpbb_yahoo', + 'field_length' => '40', + 'field_minlen' => '5', + 'field_maxlen' => '255', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '.*', + 'field_required' => 0, + 'field_show_novalue' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_pm' => 1, + 'field_show_on_vt' => 1, + 'field_show_on_ml' => 0, + 'field_show_profile' => 1, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_active' => 1, + 'field_is_contact' => 1, + 'field_contact_desc' => 'SEND_YIM_MESSAGE', + 'field_contact_url' => 'http://edit.yahoo.com/config/send_webmesg?.target=%s&.src=pg', + ); + + protected $user_column_name = 'user_yim'; +} diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php new file mode 100644 index 0000000000..c11d06576f --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_yahoo_cleanup extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_yim'); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\profilefield_yahoo', + ); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_yim', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_yim' => array('VCHAR_UNI', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php b/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php new file mode 100644 index 0000000000..83f5f903e8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php @@ -0,0 +1,46 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class prune_shadow_topics extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\dev'); + } + + public function update_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'forums' => array( + 'enable_shadow_prune' => array('BOOL', 0), + 'prune_shadow_days' => array('UINT', 7), + 'prune_shadow_freq' => array('UINT', 1), + 'prune_shadow_next' => array('INT:11', 0), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'forums' => array( + 'enable_shadow_prune', + 'prune_shadow_days', + 'prune_shadow_freq', + 'prune_shadow_next', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/310/reported_posts_display.php b/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php index 80a0a0e43f..c6618cf467 100644 --- a/phpBB/phpbb/db/migration/data/310/reported_posts_display.php +++ b/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_reported_posts_display extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class reported_posts_display extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_reported_posts_display extends phpbb_db_migrat static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/310/signature_module_auth.php b/phpBB/phpbb/db/migration/data/v310/signature_module_auth.php index 02cd70059a..6da1cb8009 100644 --- a/phpBB/phpbb/db/migration/data/310/signature_module_auth.php +++ b/phpBB/phpbb/db/migration/data/v310/signature_module_auth.php @@ -7,7 +7,9 @@ * */ -class phpbb_db_migration_data_310_signature_module_auth extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class signature_module_auth extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -25,7 +27,7 @@ class phpbb_db_migration_data_310_signature_module_auth extends phpbb_db_migrati static public function depends_on() { - return array('phpbb_db_migration_data_31x_dev'); + return array('\phpbb\db\migration\data\v310\dev'); } public function update_data() diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php new file mode 100644 index 0000000000..c9255d88ee --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php @@ -0,0 +1,128 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +/** + * Migration to convert the Soft Delete MOD for 3.0 + * + * https://www.phpbb.com/customise/db/mod/soft_delete/ + */ +class soft_delete_mod_convert extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\alpha3', + ); + } + + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_deleted'); + } + + public function update_data() + { + return array( + array('permission.remove', array('m_harddelete', true)), + array('permission.remove', array('m_harddelete', false)), + + array('custom', array(array($this, 'convert_posts'))), + array('custom', array(array($this, 'convert_topics'))), + ); + } + + public function convert_posts($start) + { + $content_visibility = $this->get_content_visibility(); + + $limit = 250; + $i = 0; + + $sql = 'SELECT p.*, t.topic_first_post_id, t.topic_last_post_id + FROM ' . $this->table_prefix . 'posts p, ' . $this->table_prefix . 'topics t + WHERE p.post_deleted > 0 + AND t.topic_id = p.topic_id'; + $result = $this->db->sql_query_limit($sql, $limit, $start); + + while ($row = $this->db->sql_fetchrow($result)) + { + $content_visibility->set_post_visibility( + ITEM_DELETED, + $row['post_id'], + $row['topic_id'], + $row['forum_id'], + $row['post_deleted'], + $row['post_deleted_time'], + '', + ($row['post_id'] == $row['topic_first_post_id']) ? true : false, + ($row['post_id'] == $row['topic_last_post_id']) ? true : false + ); + + $i++; + } + + $this->db->sql_freeresult($result); + + if ($i == $limit) + { + return $start + $i; + } + } + + public function convert_topics($start) + { + $content_visibility = $this->get_content_visibility(); + + $limit = 100; + $i = 0; + + $sql = 'SELECT * + FROM ' . $this->table_prefix . 'topics + WHERE topic_deleted > 0'; + $result = $this->db->sql_query_limit($sql, $limit, $start); + + while ($row = $this->db->sql_fetchrow($result)) + { + $content_visibility->set_topic_visibility( + ITEM_DELETED, + $row['topic_id'], + $row['forum_id'], + $row['topic_deleted'], + $row['topic_deleted_time'], + '' + ); + + $i++; + } + + $this->db->sql_freeresult($result); + + if ($i == $limit) + { + return $start + $i; + } + } + + protected function get_content_visibility() + { + return new \phpbb\content_visibility( + new \phpbb\auth\auth(), + $this->db, + new \phpbb\user(), + $this->phpbb_root_path, + $this->php_ext, + $this->table_prefix . 'forums', + $this->table_prefix . 'posts', + $this->table_prefix . 'topics', + $this->table_prefix . 'users' + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php new file mode 100644 index 0000000000..ab4be269e6 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php @@ -0,0 +1,62 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +/** + * Migration to convert the Soft Delete MOD for 3.0 + * + * https://www.phpbb.com/customise/db/mod/soft_delete/ + */ +class soft_delete_mod_convert2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\soft_delete_mod_convert', + ); + } + + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_deleted'); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'forums' => array('forum_deleted_topic_count', 'forum_deleted_reply_count'), + $this->table_prefix . 'posts' => array('post_deleted', 'post_deleted_time'), + $this->table_prefix . 'topics' => array('topic_deleted', 'topic_deleted_time', 'topic_deleted_reply_count'), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'forums' => array( + 'forum_deleted_topic_count' => array('UINT', 0), + 'forum_deleted_reply_count' => array('UINT', 0), + ), + $this->table_prefix . 'posts' => array( + 'post_deleted' => array('UINT', 0), + 'post_deleted_time' => array('TIMESTAMP', 0), + ), + $this->table_prefix . 'topics' => array( + 'topic_deleted' => array('UINT', 0), + 'topic_deleted_time' => array('TIMESTAMP', 0), + 'topic_deleted_reply_count' => array('UINT', 0), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/310/softdelete_mcp_modules.php b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php index f80f55d19a..18c225d19f 100644 --- a/phpBB/phpbb/db/migration/data/310/softdelete_mcp_modules.php +++ b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_softdelete_mcp_modules extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class softdelete_mcp_modules extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -26,8 +28,8 @@ class phpbb_db_migration_data_310_softdelete_mcp_modules extends phpbb_db_migrat static public function depends_on() { return array( - 'phpbb_db_migration_data_310_dev', - 'phpbb_db_migration_data_310_softdelete_p2', + '\phpbb\db\migration\data\v310\dev', + '\phpbb\db\migration\data\v310\softdelete_p2', ); } diff --git a/phpBB/phpbb/db/migration/data/310/softdelete_p1.php b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php index 84f8eebd4a..10243dc77f 100644 --- a/phpBB/phpbb/db/migration/data/310/softdelete_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class softdelete_p1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_310_dev'); + return array('\phpbb\db\migration\data\v310\dev'); } public function update_schema() @@ -99,7 +101,8 @@ class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration return array( array('custom', array(array($this, 'update_post_visibility'))), array('custom', array(array($this, 'update_topic_visibility'))), - array('custom', array(array($this, 'update_topic_forum_counts'))), + array('custom', array(array($this, 'update_topics_post_counts'))), + array('custom', array(array($this, 'update_forums_topic_and_post_counts'))), array('permission.add', array('f_softdelete', false)), array('permission.add', array('m_softdelete', false)), @@ -120,28 +123,52 @@ class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration $this->sql_query($sql); } - public function update_topic_forum_counts() + public function update_topics_post_counts() { + /* + * Using sql_case here to avoid "BIGINT UNSIGNED value is out of range" errors. + * As we update all topics in 2 queries, one broken topic would stop the conversion + * for all topics and the surpressed error will cause the admin to not even notice it. + */ $sql = 'UPDATE ' . $this->table_prefix . 'topics SET topic_posts_approved = topic_replies + 1, - topic_posts_unapproved = topic_replies_real - topic_replies + topic_posts_unapproved = ' . $this->db->sql_case('topic_replies_real > topic_replies', 'topic_replies_real - topic_replies', '0') . ' WHERE topic_visibility = ' . ITEM_APPROVED; $this->sql_query($sql); $sql = 'UPDATE ' . $this->table_prefix . 'topics SET topic_posts_approved = 0, - topic_posts_unapproved = (topic_replies_real - topic_replies) + 1 + topic_posts_unapproved = (' . $this->db->sql_case('topic_replies_real > topic_replies', 'topic_replies_real - topic_replies', '0') . ') + 1 WHERE topic_visibility = ' . ITEM_UNAPPROVED; $this->sql_query($sql); + } + + public function update_forums_topic_and_post_counts($start) + { + $start = (int) $start; + $limit = 10; + $converted_forums = 0; + + if (!$start) + { + // Preserve the forum_posts value for link forums as it represents redirects. + $sql = 'UPDATE ' . $this->table_prefix . 'forums + SET forum_posts_approved = forum_posts + WHERE forum_type = ' . FORUM_LINK; + $this->db->sql_query($sql); + } $sql = 'SELECT forum_id, topic_visibility, COUNT(topic_id) AS sum_topics, SUM(topic_posts_approved) AS sum_posts_approved, SUM(topic_posts_unapproved) AS sum_posts_unapproved FROM ' . $this->table_prefix . 'topics - GROUP BY forum_id, topic_visibility'; - $result = $this->db->sql_query($sql); + GROUP BY forum_id, topic_visibility + ORDER BY forum_id, topic_visibility'; + $result = $this->db->sql_query_limit($sql, $limit, $start); $update_forums = array(); while ($row = $this->db->sql_fetchrow($result)) { + $converted_forums++; + $forum_id = (int) $row['forum_id']; if (!isset($update_forums[$forum_id])) { @@ -167,5 +194,14 @@ class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration WHERE forum_id = ' . $forum_id; $this->sql_query($sql); } + + if ($converted_forums < $limit) + { + // There are no more topics, we are done + return; + } + + // There are still more topics to query, return the next start value + return $start + $limit; } } diff --git a/phpBB/phpbb/db/migration/data/310/softdelete_p2.php b/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php index 7320a2c2bf..6b84a1b980 100644 --- a/phpBB/phpbb/db/migration/data/310/softdelete_p2.php +++ b/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_softdelete_p2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class softdelete_p2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -17,8 +19,8 @@ class phpbb_db_migration_data_310_softdelete_p2 extends phpbb_db_migration static public function depends_on() { return array( - 'phpbb_db_migration_data_310_dev', - 'phpbb_db_migration_data_310_softdelete_p1', + '\phpbb\db\migration\data\v310\dev', + '\phpbb\db\migration\data\v310\softdelete_p1', ); } @@ -32,7 +34,10 @@ class phpbb_db_migration_data_310_softdelete_p2 extends phpbb_db_migration ), 'drop_keys' => array( $this->table_prefix . 'posts' => array('post_approved'), - $this->table_prefix . 'topics' => array('forum_appr_last'), + $this->table_prefix . 'topics' => array( + 'forum_appr_last', + 'topic_approved', + ), ), ); } @@ -61,6 +66,7 @@ class phpbb_db_migration_data_310_softdelete_p2 extends phpbb_db_migration ), $this->table_prefix . 'topics' => array( 'forum_appr_last' => array('forum_id', 'topic_approved', 'topic_last_post_id'), + 'topic_approved' => array('topic_approved'), ), ), ); diff --git a/phpBB/phpbb/db/migration/data/310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php index d43537559d..fcba1d73ed 100644 --- a/phpBB/phpbb/db/migration/data/310/style_update_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class style_update_p1 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() @@ -59,7 +61,7 @@ class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration // Get list of valid 3.1 styles $available_styles = array('prosilver'); - $iterator = new DirectoryIterator($this->phpbb_root_path . 'styles'); + $iterator = new \DirectoryIterator($this->phpbb_root_path . 'styles'); $skip_dirs = array('.', '..', 'prosilver'); foreach ($iterator as $fileinfo) { diff --git a/phpBB/phpbb/db/migration/data/310/style_update_p2.php b/phpBB/phpbb/db/migration/data/v310/style_update_p2.php index 7b10518a66..316741e11d 100644 --- a/phpBB/phpbb/db/migration/data/310/style_update_p2.php +++ b/phpBB/phpbb/db/migration/data/v310/style_update_p2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class style_update_p2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,12 +18,20 @@ class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_310_style_update_p1'); + return array('\phpbb\db\migration\data\v310\style_update_p1'); } public function update_schema() { return array( + 'drop_keys' => array( + $this->table_prefix . 'styles' => array( + 'imageset_id', + 'template_id', + 'theme_id', + ), + ), + 'drop_columns' => array( $this->table_prefix . 'styles' => array( 'imageset_id', @@ -51,10 +61,18 @@ class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration ), ), + 'add_index' => array( + $this->table_prefix . 'styles' => array( + 'imageset_id' => array('imageset_id'), + 'template_id' => array('template_id'), + 'theme_id' => array('theme_id'), + ), + ), + 'add_tables' => array( $this->table_prefix . 'styles_imageset' => array( 'COLUMNS' => array( - 'imageset_id' => array('UINT', NULL, 'auto_increment'), + 'imageset_id' => array('UINT', null, 'auto_increment'), 'imageset_name' => array('VCHAR_UNI:255', ''), 'imageset_copyright' => array('VCHAR_UNI', ''), 'imageset_path' => array('VCHAR:100', ''), @@ -66,7 +84,7 @@ class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration ), $this->table_prefix . 'styles_imageset_data' => array( 'COLUMNS' => array( - 'image_id' => array('UINT', NULL, 'auto_increment'), + 'image_id' => array('UINT', null, 'auto_increment'), 'image_name' => array('VCHAR:200', ''), 'image_filename' => array('VCHAR:200', ''), 'image_lang' => array('VCHAR:30', ''), @@ -81,7 +99,7 @@ class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration ), $this->table_prefix . 'styles_template' => array( 'COLUMNS' => array( - 'template_id' => array('UINT', NULL, 'auto_increment'), + 'template_id' => array('UINT', null, 'auto_increment'), 'template_name' => array('VCHAR_UNI:255', ''), 'template_copyright' => array('VCHAR_UNI', ''), 'template_path' => array('VCHAR:100', ''), @@ -110,7 +128,7 @@ class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration ), $this->table_prefix . 'styles_theme' => array( 'COLUMNS' => array( - 'theme_id' => array('UINT', NULL, 'auto_increment'), + 'theme_id' => array('UINT', null, 'auto_increment'), 'theme_name' => array('VCHAR_UNI:255', ''), 'theme_copyright' => array('VCHAR_UNI', ''), 'theme_path' => array('VCHAR:100', ''), diff --git a/phpBB/phpbb/db/migration/data/310/teampage.php b/phpBB/phpbb/db/migration/data/v310/teampage.php index 4e77da17b7..f03c09e04f 100644 --- a/phpBB/phpbb/db/migration/data/310/teampage.php +++ b/phpBB/phpbb/db/migration/data/v310/teampage.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_teampage extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class teampage extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_teampage extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_310_dev'); + return array('\phpbb\db\migration\data\v310\dev'); } public function update_schema() @@ -25,7 +27,7 @@ class phpbb_db_migration_data_310_teampage extends phpbb_db_migration 'add_tables' => array( $this->table_prefix . 'teampage' => array( 'COLUMNS' => array( - 'teampage_id' => array('UINT', NULL, 'auto_increment'), + 'teampage_id' => array('UINT', null, 'auto_increment'), 'group_id' => array('UINT', 0), 'teampage_name' => array('VCHAR_UNI:255', ''), 'teampage_position' => array('UINT', 0), diff --git a/phpBB/phpbb/db/migration/data/310/timezone.php b/phpBB/phpbb/db/migration/data/v310/timezone.php index 6e50cbe45f..2efedd4514 100644 --- a/phpBB/phpbb/db/migration/data/310/timezone.php +++ b/phpBB/phpbb/db/migration/data/v310/timezone.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_timezone extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class timezone extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_timezone extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() @@ -37,23 +39,48 @@ class phpbb_db_migration_data_310_timezone extends phpbb_db_migration ); } - public function update_timezones() + public function update_timezones($start) { - // Update user timezones - $sql = 'SELECT user_dst, user_timezone - FROM ' . $this->table_prefix . 'users - GROUP BY user_timezone, user_dst'; - $result = $this->db->sql_query($sql); + $start = (int) $start; + $limit = 500; + $converted = 0; + $update_blocks = array(); + + $sql = 'SELECT user_id, user_timezone, user_dst + FROM ' . $this->table_prefix . 'users + ORDER BY user_id ASC'; + $result = $this->db->sql_query_limit($sql, $limit, $start); while ($row = $this->db->sql_fetchrow($result)) { + $converted++; + + // In case this is somehow run twice on a row. + // Otherwise it would just end up as UTC on the second run + if (is_numeric($row['user_timezone'])) + { + $update_blocks[$row['user_timezone'] . ':' . $row['user_dst']][] = (int) $row['user_id']; + } + } + $this->db->sql_freeresult($result); + + // Update blocks of users who share the same timezone/dst + foreach ($update_blocks as $timezone => $user_ids) + { + $timezone = explode(':', $timezone); + $converted_timezone = $this->convert_phpbb30_timezone($timezone[0], $timezone[1]); + $sql = 'UPDATE ' . $this->table_prefix . "users - SET user_timezone = '" . $this->db->sql_escape($this->convert_phpbb30_timezone($row['user_timezone'], $row['user_dst'])) . "' - WHERE user_timezone = '" . $this->db->sql_escape($row['user_timezone']) . "' - AND user_dst = " . (int) $row['user_dst']; + SET user_timezone = '" . $this->db->sql_escape($converted_timezone) . "' + WHERE " . $this->db->sql_in_set('user_id', $user_ids); $this->sql_query($sql); } - $this->db->sql_freeresult($result); + + if ($converted == $limit) + { + // There are still more to convert + return $start + $limit; + } // Update board default timezone $sql = 'UPDATE ' . $this->table_prefix . "config diff --git a/phpBB/phpbb/db/migration/data/310/timezone_p2.php b/phpBB/phpbb/db/migration/data/v310/timezone_p2.php index 113b979e4f..891d8622a0 100644 --- a/phpBB/phpbb/db/migration/data/310/timezone_p2.php +++ b/phpBB/phpbb/db/migration/data/v310/timezone_p2.php @@ -3,11 +3,13 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -class phpbb_db_migration_data_310_timezone_p2 extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class timezone_p2 extends \phpbb\db\migration\migration { public function effectively_installed() { @@ -16,7 +18,7 @@ class phpbb_db_migration_data_310_timezone_p2 extends phpbb_db_migration static public function depends_on() { - return array('phpbb_db_migration_data_310_timezone'); + return array('\phpbb\db\migration\data\v310\timezone'); } public function update_schema() diff --git a/phpBB/phpbb/db/migration/data/v310/ucp_popuppm_module.php b/phpBB/phpbb/db/migration/data/v310/ucp_popuppm_module.php new file mode 100644 index 0000000000..f8ada6c6f5 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/ucp_popuppm_module.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration\data\v310; + +class ucp_popuppm_module extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + $sql = 'SELECT module_id + FROM ' . MODULES_TABLE . " + WHERE module_class = 'ucp' + AND module_langname = 'UCP_PM_POPUP_TITLE'"; + $result = $this->db->sql_query($sql); + $module_id = $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + return $module_id == false; + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\dev'); + } + + public function update_data() + { + return array( + array('module.remove', array( + 'ucp', + 'UCP_PM', + 'UCP_PM_POPUP_TITLE', + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/exception.php b/phpBB/phpbb/db/migration/exception.php index e84330dd71..c6c1a45947 100644 --- a/phpBB/phpbb/db/migration/exception.php +++ b/phpBB/phpbb/db/migration/exception.php @@ -3,24 +3,18 @@ * * @package db * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\migration; /** * The migrator is responsible for applying new migrations in the correct order. * * @package db */ -class phpbb_db_migration_exception extends \Exception +class exception extends \Exception { /** * Extra parameters sent to exception to aid in debugging @@ -64,12 +58,12 @@ class phpbb_db_migration_exception extends \Exception } /** - * Get localised message (with $user->lang()) - * - * @param phpbb_user $user + * Get localised message (with $user->lang()) + * + * @param \phpbb\user $user * @return string */ - public function getLocalisedMessage(phpbb_user $user) + public function getLocalisedMessage(\phpbb\user $user) { $parameters = $this->getParameters(); array_unshift($parameters, $this->getMessage()); diff --git a/phpBB/phpbb/db/migration/helper.php b/phpBB/phpbb/db/migration/helper.php new file mode 100644 index 0000000000..238b2dbe53 --- /dev/null +++ b/phpBB/phpbb/db/migration/helper.php @@ -0,0 +1,82 @@ +<?php +/** +* +* @package db +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration; + +/** +* The migrator is responsible for applying new migrations in the correct order. +* +* @package db +*/ +class helper +{ + /** + * Get the schema steps from an array of schema changes + * + * This splits up $schema_changes into individual changes so that the + * changes can be chunked + * + * @param array $schema_changes from migration + * @return array + */ + public function get_schema_steps($schema_changes) + { + $steps = array(); + + // Nested level of data (only supports 1/2 currently) + $nested_level = array( + 'drop_tables' => 1, + 'add_tables' => 1, + 'change_columns' => 2, + 'add_columns' => 2, + 'drop_keys' => 2, + 'drop_columns' => 2, + 'add_primary_keys' => 2, // perform_schema_changes only uses one level, but second is in the function + 'add_unique_index' => 2, + 'add_index' => 2, + ); + + foreach ($nested_level as $change_type => $data_depth) + { + if (!empty($schema_changes[$change_type])) + { + foreach ($schema_changes[$change_type] as $key => $value) + { + if ($data_depth === 1) + { + $steps[] = array( + 'dbtools.perform_schema_changes', array(array( + $change_type => array( + (!is_int($key)) ? $key : 0 => $value, + ), + )), + ); + } + else if ($data_depth === 2) + { + foreach ($value as $key2 => $value2) + { + $steps[] = array( + 'dbtools.perform_schema_changes', array(array( + $change_type => array( + $key => array( + $key2 => $value2, + ), + ), + )), + ); + } + } + } + } + } + + return $steps; + } +} diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php index 0ffa96fd14..85c5fc5d08 100644 --- a/phpBB/phpbb/db/migration/migration.php +++ b/phpBB/phpbb/db/migration/migration.php @@ -3,17 +3,11 @@ * * @package db * @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db\migration; /** * Abstract base class for database migrations @@ -24,15 +18,15 @@ if (!defined('IN_PHPBB')) * * @package db */ -abstract class phpbb_db_migration +abstract class migration { - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_db_tools */ + /** @var \phpbb\db\tools */ protected $db_tools; /** @var string */ @@ -53,14 +47,14 @@ abstract class phpbb_db_migration /** * Constructor * - * @param phpbb_config $config - * @param phpbb_db_driver $db - * @param phpbb_db_tools $db_tools + * @param \phpbb\config\config $config + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\db\tools $db_tools * @param string $phpbb_root_path * @param string $php_ext * @param string $table_prefix */ - public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php new file mode 100644 index 0000000000..3797d670f7 --- /dev/null +++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php @@ -0,0 +1,155 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration; + +abstract class profilefield_base_migration extends \phpbb\db\migration\migration +{ + protected $profilefield_name; + + protected $profilefield_database_type; + + protected $profilefield_data; + + protected $user_column_name; + + public function effectively_installed() + { + return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields_data', 'pf_' . $this->profilefield_name); + } + + public function update_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'profile_fields_data' => array( + 'pf_' . $this->profilefield_name => $this->profilefield_database_type, + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'profile_fields_data' => array( + 'pf_' . $this->profilefield_name, + ), + ), + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'create_custom_field'))), + array('custom', array(array($this, 'convert_user_field_to_custom_field'))), + ); + } + + public function create_custom_field() + { + $sql = 'SELECT MAX(field_order) as max_field_order + FROM ' . PROFILE_FIELDS_TABLE; + $result = $this->db->sql_query($sql); + $max_field_order = (int) $this->db->sql_fetchfield('max_field_order'); + $this->db->sql_freeresult($result); + + $sql_ary = array_merge($this->profilefield_data, array( + 'field_order' => $max_field_order + 1, + )); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); + $this->db->sql_query($sql); + $field_id = (int) $this->db->sql_nextid(); + + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE); + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE; + $result = $this->db->sql_query($sql); + while ($lang_id = (int) $this->db->sql_fetchfield('lang_id')) + { + $insert_buffer->insert(array( + 'field_id' => $field_id, + 'lang_id' => $lang_id, + 'lang_name' => strtoupper(substr($this->profilefield_name, 6)),// Remove phpbb_ from field name + 'lang_explain' => '', + 'lang_default_value' => '', + )); + } + $this->db->sql_freeresult($result); + + $insert_buffer->flush(); + } + + /** + * @param int $start Start of staggering step + * @return mixed int start of the next step, null if the end was reached + */ + public function convert_user_field_to_custom_field($start) + { + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'profile_fields_data'); + $limit = 250; + $converted_users = 0; + + $sql = 'SELECT user_id, ' . $this->user_column_name . ' + FROM ' . $this->table_prefix . 'users + WHERE ' . $this->user_column_name . " <> '' + ORDER BY user_id"; + $result = $this->db->sql_query_limit($sql, $limit, $start); + + while ($row = $this->db->sql_fetchrow($result)) + { + $converted_users++; + + $cp_data = array( + 'pf_' . $this->profilefield_name => $row[$this->user_column_name], + ); + + $sql = 'UPDATE ' . $this->table_prefix . 'profile_fields_data + SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . ' + WHERE user_id = ' . (int) $row['user_id']; + $this->db->sql_query($sql); + + if (!$this->db->sql_affectedrows()) + { + $cp_data['user_id'] = (int) $row['user_id']; + $cp_data = array_merge($this->get_insert_sql_array(), $cp_data); + $insert_buffer->insert($cp_data); + } + } + $this->db->sql_freeresult($result); + + $insert_buffer->flush(); + + if ($converted_users < $limit) + { + // No more users left, we are done... + return; + } + + return $start + $limit; + } + + protected function get_insert_sql_array() + { + static $profile_row; + + if ($profile_row === null) + { + global $phpbb_container; + $manager = $phpbb_container->get('profilefields.manager'); + $profile_row = $manager->build_insert_sql_array(array()); + } + + return $profile_row; + } +} diff --git a/phpBB/phpbb/db/migration/schema_generator.php b/phpBB/phpbb/db/migration/schema_generator.php new file mode 100644 index 0000000000..5d40b0b26f --- /dev/null +++ b/phpBB/phpbb/db/migration/schema_generator.php @@ -0,0 +1,215 @@ +<?php +/** +* +* @package db +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\db\migration; + +/** +* The schema generator generates the schema based on the existing migrations +* +* @package db +*/ +class schema_generator +{ + /** @var \phpbb\config\config */ + protected $config; + + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + /** @var \phpbb\db\tools */ + protected $db_tools; + + /** @var array */ + protected $class_names; + + /** @var string */ + protected $table_prefix; + + /** @var string */ + protected $phpbb_root_path; + + /** @var string */ + protected $php_ext; + + /** @var array */ + protected $tables; + + /** @var array */ + protected $dependencies = array(); + + /** + * Constructor + */ + public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) + { + $this->config = $config; + $this->db = $db; + $this->db_tools = $db_tools; + $this->class_names = $class_names; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->table_prefix = $table_prefix; + } + + /** + * Loads all migrations and their application state from the database. + * + * @return array + */ + public function get_schema() + { + if (!empty($this->tables)) + { + return $this->tables; + } + + $migrations = $this->class_names; + + $tree = array(); + $check_dependencies = true; + while (!empty($migrations)) + { + foreach ($migrations as $migration_class) + { + $open_dependencies = array_diff($migration_class::depends_on(), $tree); + + if (empty($open_dependencies)) + { + $migration = new $migration_class($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix); + $tree[] = $migration_class; + $migration_key = array_search($migration_class, $migrations); + + foreach ($migration->update_schema() as $change_type => $data) + { + if ($change_type === 'add_tables') + { + foreach ($data as $table => $table_data) + { + $this->tables[$table] = $table_data; + } + } + else if ($change_type === 'drop_tables') + { + foreach ($data as $table) + { + unset($this->tables[$table]); + } + } + else if ($change_type === 'add_columns') + { + foreach ($data as $table => $add_columns) + { + foreach ($add_columns as $column => $column_data) + { + $this->tables[$table]['COLUMNS'][$column] = $column_data; + } + } + } + else if ($change_type === 'change_columns') + { + foreach ($data as $table => $change_columns) + { + foreach ($change_columns as $column => $column_data) + { + $this->tables[$table]['COLUMNS'][$column] = $column_data; + } + } + } + else if ($change_type === 'drop_columns') + { + foreach ($data as $table => $drop_columns) + { + if (is_array($drop_columns)) + { + foreach ($drop_columns as $column) + { + unset($this->tables[$table]['COLUMNS'][$column]); + } + } + else + { + unset($this->tables[$table]['COLUMNS'][$drop_columns]); + } + } + } + else if ($change_type === 'add_unique_index') + { + foreach ($data as $table => $add_index) + { + foreach ($add_index as $key => $index_data) + { + $this->tables[$table]['KEYS'][$key] = array('UNIQUE', $index_data); + } + } + } + else if ($change_type === 'add_index') + { + foreach ($data as $table => $add_index) + { + foreach ($add_index as $key => $index_data) + { + $this->tables[$table]['KEYS'][$key] = array('INDEX', $index_data); + } + } + } + else if ($change_type === 'drop_keys') + { + foreach ($data as $table => $drop_keys) + { + foreach ($drop_keys as $key) + { + unset($this->tables[$table]['KEYS'][$key]); + } + } + } + else + { + var_dump($change_type); + } + } + unset($migrations[$migration_key]); + } + else if ($check_dependencies) + { + $this->dependencies = array_merge($this->dependencies, $open_dependencies); + } + } + + // Only run this check after the first run + if ($check_dependencies) + { + $this->check_dependencies(); + $check_dependencies = false; + } + } + + ksort($this->tables); + return $this->tables; + } + + /** + * Check if one of the migrations files' dependencies can't be resolved + * by the supplied list of migrations + * + * @throws UnexpectedValueException If a dependency can't be resolved + */ + protected function check_dependencies() + { + // Strip duplicate values from array + $this->dependencies = array_unique($this->dependencies); + + foreach ($this->dependencies as $dependency) + { + if (!in_array($dependency, $this->class_names)) + { + throw new \UnexpectedValueException("Unable to resolve the dependency '$dependency'"); + } + } + } +} diff --git a/phpBB/phpbb/db/migration/tool/config.php b/phpBB/phpbb/db/migration/tool/config.php index 0b626bf455..96d358f647 100644 --- a/phpBB/phpbb/db/migration/tool/config.php +++ b/phpBB/phpbb/db/migration/tool/config.php @@ -3,26 +3,28 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +namespace phpbb\db\migration\tool; + /** * Migration config tool * * @package db */ -class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interface +class config implements \phpbb\db\migration\tool\tool_interface { - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; /** * Constructor * - * @param phpbb_config $config + * @param \phpbb\config\config $config */ - public function __construct(phpbb_config $config) + public function __construct(\phpbb\config\config $config) { $this->config = $config; } @@ -67,7 +69,7 @@ class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interfac { if (!isset($this->config[$config_name])) { - throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name); + throw new \phpbb\db\migration\exception('CONFIG_NOT_EXIST', $config_name); } $this->config->set($config_name, $config_value); @@ -88,7 +90,7 @@ class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interfac { if (!isset($this->config[$config_name])) { - throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name); + throw new \phpbb\db\migration\exception('CONFIG_NOT_EXIST', $config_name); } $this->config->set_atomic($config_name, $compare, $config_value); @@ -128,6 +130,10 @@ class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interfac case 'remove': $call = 'add'; + if (sizeof($arguments) == 1) + { + $arguments[] = ''; + } break; case 'update_if_equals': diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index ac4d2c9bd7..96cc6b54a5 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -3,24 +3,26 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +namespace phpbb\db\migration\tool; + /** * Migration module management tool * * @package db */ -class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interface +class module implements \phpbb\db\migration\tool\tool_interface { - /** @var phpbb_cache_service */ + /** @var \phpbb\cache\service */ protected $cache; - /** @var dbal */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; /** @var string */ @@ -35,14 +37,14 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac /** * Constructor * - * @param phpbb_db_driver $db - * @param mixed $cache - * @param phpbb_user $user + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\cache\service $cache + * @param \phpbb\user $user * @param string $phpbb_root_path * @param string $php_ext * @param string $modules_table */ - public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_user $user, $phpbb_root_path, $php_ext, $modules_table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $phpbb_root_path, $php_ext, $modules_table) { $this->db = $db; $this->cache = $cache; @@ -133,7 +135,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac * * @param string $class The module class(acp|mcp|ucp) * @param int|string $parent The parent module_id|module_langname (0 for no parent) - * @param array $data an array of the data on the new module. + * @param array $data an array of the data on the new \module. * This can be setup in two different ways. * 1. The "manual" way. For inserting a category or one at a time. * It will be merged with the base array shown a bit below, @@ -161,11 +163,10 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac * ) * Optionally you may not send 'modes' and it will insert all of the * modules in that info file. - * @param string|bool $include_path If you would like to use a custom include * path, specify that here * @return null */ - public function add($class, $parent = 0, $data = array(), $include_path = false) + public function add($class, $parent = 0, $data = array()) { // Allows '' to be sent as 0 $parent = $parent ?: 0; @@ -180,9 +181,6 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac { // The "automatic" way $basename = (isset($data['module_basename'])) ? $data['module_basename'] : ''; - $basename = str_replace(array('/', '\\'), '', $basename); - $class = str_replace(array('/', '\\'), '', $class); - $module = $this->get_module_info($class, $basename); $result = ''; @@ -221,14 +219,14 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac if (!$module_id) { - throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent); + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); } $parent = $data['parent_id'] = $module_id; } else if (!$this->exists($class, false, $parent)) { - throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent); + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); } if ($this->exists($class, $parent, $data['module_langname'])) @@ -241,7 +239,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); $this->user->add_lang('acp/modules'); } - $acp_modules = new acp_modules(); + $acp_modules = new \acp_modules(); $module_data = array( 'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1, @@ -259,7 +257,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac if (is_string($result)) { // Error - throw new phpbb_db_migration_exception('MODULE_ERROR', $result); + throw new \phpbb\db\migration\exception('MODULE_ERROR', $result); } else { @@ -329,11 +327,10 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac * @param int|string|bool $parent The parent module_id|module_langname(0 for no parent). * Use false to ignore the parent check and check class wide. * @param int|string $module The module id|module_langname - * @param string|bool $include_path If you would like to use a custom include path, * specify that here * @return null */ - public function remove($class, $parent = 0, $module = '', $include_path = false) + public function remove($class, $parent = 0, $module = '') { // Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto if (is_array($module)) @@ -341,19 +338,17 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac if (isset($module['module_langname'])) { // Manual Method - return $this->remove($class, $parent, $module['module_langname'], $include_path); + return $this->remove($class, $parent, $module['module_langname']); } // Failed. if (!isset($module['module_basename'])) { - throw new phpbb_db_migration_exception('MODULE_NOT_EXIST'); + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST'); } // Automatic method - $basename = str_replace(array('/', '\\'), '', $module['module_basename']); - $class = str_replace(array('/', '\\'), '', $class); - + $basename = $module['module_basename']; $module_info = $this->get_module_info($class, $basename); foreach ($module_info['modes'] as $mode => $info) @@ -410,22 +405,10 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac $module_ids[] = (int) $module_id; } $this->db->sql_freeresult($result); - - $module_name = $module; } else { - $module = (int) $module; - $sql = 'SELECT module_langname - FROM ' . $this->modules_table . " - WHERE module_id = $module - AND module_class = '" . $this->db->sql_escape($class) . "' - $parent_sql"; - $result = $this->db->sql_query($sql); - $module_name = $this->db->sql_fetchfield('module_id'); - $this->db->sql_freeresult($result); - - $module_ids[] = $module; + $module_ids[] = (int) $module; } if (!class_exists('acp_modules')) @@ -433,7 +416,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); $this->user->add_lang('acp/modules'); } - $acp_modules = new acp_modules(); + $acp_modules = new \acp_modules(); $acp_modules->module_class = $class; foreach ($module_ids as $module_id) @@ -476,7 +459,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac } /** - * Wrapper for acp_modules::get_module_infos() + * Wrapper for \acp_modules::get_module_infos() * * @param string $class Module Class * @param string $basename Module Basename @@ -488,12 +471,12 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac { include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); } - $acp_modules = new acp_modules(); + $acp_modules = new \acp_modules(); $module = $acp_modules->get_module_infos($basename, $class, true); if (empty($module)) { - throw new phpbb_db_migration_exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename); + throw new \phpbb\db\migration\exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename); } return array_pop($module); diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php index 2f09c0ac72..6cb3f213f1 100644 --- a/phpBB/phpbb/db/migration/tool/permission.php +++ b/phpBB/phpbb/db/migration/tool/permission.php @@ -3,24 +3,26 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +namespace phpbb\db\migration\tool; + /** * Migration permission management tool * * @package db */ -class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_interface +class permission implements \phpbb\db\migration\tool\tool_interface { - /** @var phpbb_auth */ + /** @var \phpbb\auth\auth */ protected $auth; - /** @var phpbb_cache_service */ + /** @var \phpbb\cache\service */ protected $cache; - /** @var dbal */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; /** @var string */ @@ -32,13 +34,13 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte /** * Constructor * - * @param phpbb_db_driver $db - * @param mixed $cache - * @param phpbb_auth $auth + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\cache\service $cache + * @param \phpbb\auth\auth $auth * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_auth $auth, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext) { $this->db = $db; $this->cache = $cache; @@ -117,7 +119,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte { include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext); } - $auth_admin = new auth_admin(); + $auth_admin = new \auth_admin(); // We have to add a check to see if the !$global (if global, local, and if local, global) permission already exists. If it does, acl_add_option currently has a bug which would break the ACL system, so we are having a work-around here. if ($this->exists($auth_option, !$global)) @@ -290,7 +292,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte if (!$role_id) { - throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $old_role_name); + throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $old_role_name); } $sql = 'UPDATE ' . ACL_ROLES_TABLE . " @@ -380,7 +382,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte if (!$role_id) { - throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name); + throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name); } $sql = 'SELECT auth_option_id, auth_setting @@ -403,7 +405,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte if (!$group_id) { - throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name); + throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name); } // If the group has a role set for them we will add the requested permissions to that role. @@ -523,7 +525,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte if (!$role_id) { - throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name); + throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name); } $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' @@ -540,7 +542,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte if (!$group_id) { - throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name); + throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name); } // If the group has a role set for them we will remove the requested permissions from that role. diff --git a/phpBB/phpbb/db/migration/tool/interface.php b/phpBB/phpbb/db/migration/tool/tool_interface.php index ced53b2023..5eb1a2f521 100644 --- a/phpBB/phpbb/db/migration/tool/interface.php +++ b/phpBB/phpbb/db/migration/tool/tool_interface.php @@ -3,16 +3,18 @@ * * @package migration * @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +namespace phpbb\db\migration\tool; + /** * Migration tool interface * * @package db */ -interface phpbb_db_migration_tool_interface +interface tool_interface { /** * Retrieve a short name used for commands in migrations. diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index ca3ffc8043..5ad8563e5c 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -3,34 +3,31 @@ * * @package db * @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db; /** * The migrator is responsible for applying new migrations in the correct order. * * @package db */ -class phpbb_db_migrator +class migrator { - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_db_tools */ + /** @var \phpbb\db\tools */ protected $db_tools; + /** @var \phpbb\db\migration\helper */ + protected $helper; + /** @var string */ protected $table_prefix; @@ -71,11 +68,12 @@ class phpbb_db_migrator /** * Constructor of the database migrator */ - public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) { $this->config = $config; $this->db = $db; $this->db_tools = $db_tools; + $this->helper = $helper; $this->migrations_table = $migrations_table; @@ -89,6 +87,8 @@ class phpbb_db_migrator $this->tools[$tool->get_name()] = $tool; } + $this->tools['dbtools'] = $this->db_tools; + $this->load_migration_state(); } @@ -190,6 +190,11 @@ class phpbb_db_migrator foreach ($state['migration_depends_on'] as $depend) { + if ($this->unfulfillable($depend) !== false) + { + throw new \phpbb\db\migration\exception('MIGRATION_NOT_FULFILLABLE', $name, $depend); + } + if (!isset($this->migration_state[$depend]) || !$this->migration_state[$depend]['migration_schema_done'] || !$this->migration_state[$depend]['migration_data_done']) @@ -202,11 +207,12 @@ class phpbb_db_migrator 'name' => $name, 'class' => $migration, 'state' => $state, + 'task' => '', ); if (!isset($this->migration_state[$name])) { - if ($migration->effectively_installed()) + if ($state['migration_start_time'] == 0 && $migration->effectively_installed()) { $state = array( 'migration_depends_on' => $migration->depends_on(), @@ -225,22 +231,29 @@ class phpbb_db_migrator } } + $this->set_migration_state($name, $state); + if (!$state['migration_schema_done']) { - $this->apply_schema_changes($migration->update_schema()); - $state['migration_schema_done'] = true; + $this->last_run_migration['task'] = 'process_schema_step'; + $steps = $this->helper->get_schema_steps($migration->update_schema()); + $result = $this->process_data_step($steps, $state['migration_data_state']); + + $state['migration_data_state'] = ($result === true) ? '' : $result; + $state['migration_schema_done'] = ($result === true); } else if (!$state['migration_data_done']) { try { + $this->last_run_migration['task'] = 'process_data_step'; $result = $this->process_data_step($migration->update_data(), $state['migration_data_state']); $state['migration_data_state'] = ($result === true) ? '' : $result; $state['migration_data_done'] = ($result === true); $state['migration_end_time'] = ($result === true) ? time() : 0; } - catch (phpbb_db_migration_exception $e) + catch (\phpbb\db\migration\exception $e) { // Revert the schema changes $this->revert($name); @@ -304,6 +317,7 @@ class phpbb_db_migrator $this->last_run_migration = array( 'name' => $name, 'class' => $migration, + 'task' => '', ); if ($state['migration_data_done']) @@ -324,33 +338,28 @@ class phpbb_db_migrator $this->set_migration_state($name, $state); } - else + else if ($state['migration_schema_done']) { - $this->apply_schema_changes($migration->revert_schema()); + $steps = $this->helper->get_schema_steps($migration->revert_schema()); + $result = $this->process_data_step($steps, $state['migration_data_state']); - $sql = 'DELETE FROM ' . $this->migrations_table . " - WHERE migration_name = '" . $this->db->sql_escape($name) . "'"; - $this->db->sql_query($sql); + $state['migration_data_state'] = ($result === true) ? '' : $result; + $state['migration_schema_done'] = ($result === true) ? false : true; - unset($this->migration_state[$name]); + if (!$state['migration_schema_done']) + { + $sql = 'DELETE FROM ' . $this->migrations_table . " + WHERE migration_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + unset($this->migration_state[$name]); + } } return true; } /** - * Apply schema changes from a migration - * - * Just calls db_tools->perform_schema_changes - * - * @param array $schema_changes from migration - */ - protected function apply_schema_changes($schema_changes) - { - $this->db_tools->perform_schema_changes($schema_changes); - } - - /** * Process the data step of the migration * * @param array $steps The steps to run @@ -370,7 +379,7 @@ class phpbb_db_migrator foreach ($steps as $step_identifier => $step) { - $last_result = false; + $last_result = 0; if ($state) { // Continue until we reach the step that matches the last step called @@ -398,7 +407,7 @@ class phpbb_db_migrator )); } } - catch (phpbb_db_migration_exception $e) + catch (\phpbb\db\migration\exception $e) { // We should try rolling back here foreach ($steps as $reverse_step_identifier => $reverse_step) @@ -431,7 +440,7 @@ class phpbb_db_migrator * @param bool $reverse False to install, True to attempt uninstallation by reversing the call * @return null */ - protected function run_step($step, $last_result = false, $reverse = false) + protected function run_step($step, $last_result = 0, $reverse = false) { $callable_and_parameters = $this->get_callable_from_step($step, $last_result, $reverse); @@ -454,7 +463,7 @@ class phpbb_db_migrator * @param bool $reverse False to install, True to attempt uninstallation by reversing the call * @return array Array with parameters for call_user_func_array(), 0 is the callable, 1 is parameters */ - protected function get_callable_from_step(array $step, $last_result = false, $reverse = false) + protected function get_callable_from_step(array $step, $last_result = 0, $reverse = false) { $type = $step[0]; $parameters = $step[1]; @@ -474,12 +483,12 @@ class phpbb_db_migrator case 'if': if (!isset($parameters[0])) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_CONDITION', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_MISSING_CONDITION', $step); } if (!isset($parameters[1])) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step); } $condition = $parameters[0]; @@ -493,32 +502,40 @@ class phpbb_db_migrator return $this->get_callable_from_step($step); break; + case 'custom': if (!is_callable($parameters[0])) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE', $step); } - return array( - $parameters[0], - array($last_result), - ); + if ($reverse) + { + return false; + } + else + { + return array( + $parameters[0], + array($last_result), + ); + } break; default: if (!$method) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNKNOWN_TYPE', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_UNKNOWN_TYPE', $step); } if (!isset($this->tools[$class])) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_TOOL', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_UNDEFINED_TOOL', $step); } if (!method_exists(get_class($this->tools[$class]), $method)) { - throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_METHOD', $step); + throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_UNDEFINED_METHOD', $step); } // Attempt to reverse operations @@ -622,6 +639,7 @@ class phpbb_db_migrator { continue; } + return false; } @@ -656,7 +674,7 @@ class phpbb_db_migrator * Helper to get a migration * * @param string $name Name of the migration - * @return phpbb_db_migration + * @return \phpbb\db\migration\migration */ protected function get_migration($name) { @@ -694,7 +712,7 @@ class phpbb_db_migrator /** * Load migration data files from a directory * - * @param phpbb_extension_finder $finder + * @param \phpbb\extension\finder $finder * @param string $path Path to migration data files * @param bool $check_fulfillable If TRUE (default), we will check * if all of the migrations are fulfillable after loading them. @@ -703,11 +721,11 @@ class phpbb_db_migrator * with the last call to prevent throwing errors unnecessarily). * @return array Array of migration names */ - public function load_migrations(phpbb_extension_finder $finder, $path, $check_fulfillable = true) + public function load_migrations(\phpbb\extension\finder $finder, $path, $check_fulfillable = true) { if (!is_dir($path)) { - throw new phpbb_db_migration_exception('DIRECTORY INVALID', $path); + throw new \phpbb\db\migration\exception('DIRECTORY INVALID', $path); } $migrations = array(); @@ -736,7 +754,7 @@ class phpbb_db_migrator $unfulfillable = $this->unfulfillable($name); if ($unfulfillable !== false) { - throw new phpbb_db_migration_exception('MIGRATION_NOT_FULFILLABLE', $name, $unfulfillable); + throw new \phpbb\db\migration\exception('MIGRATION_NOT_FULFILLABLE', $name, $unfulfillable); } } } diff --git a/phpBB/phpbb/db/sql_insert_buffer.php b/phpBB/phpbb/db/sql_insert_buffer.php index c18f908429..0236a55b82 100644 --- a/phpBB/phpbb/db/sql_insert_buffer.php +++ b/phpBB/phpbb/db/sql_insert_buffer.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db; /** * Collects rows for insert into a database until the buffer size is reached. @@ -38,7 +32,7 @@ if (!defined('IN_PHPBB')) * * Usage: * <code> -* $buffer = new phpbb_db_sql_insert_buffer($db, 'test_table', 1234); +* $buffer = new \phpbb\db\sql_insert_buffer($db, 'test_table', 1234); * * while (do_stuff()) * { @@ -53,9 +47,9 @@ if (!defined('IN_PHPBB')) * * @package dbal */ -class phpbb_db_sql_insert_buffer +class sql_insert_buffer { - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; /** @var string */ @@ -68,11 +62,11 @@ class phpbb_db_sql_insert_buffer protected $buffer = array(); /** - * @param phpbb_db_driver $db + * @param \phpbb\db\driver\driver_interface $db * @param string $table_name * @param int $max_buffered_rows */ - public function __construct(phpbb_db_driver $db, $table_name, $max_buffered_rows = 500) + public function __construct(\phpbb\db\driver\driver_interface $db, $table_name, $max_buffered_rows = 500) { $this->db = $db; $this->table_name = $table_name; diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index dbe00f6be2..2b0132075b 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\db; /** * Database Tools for handling cross-db actions such as altering columns, etc. @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package dbal */ -class phpbb_db_tools +class tools { /** * Current sql layer @@ -31,7 +25,7 @@ class phpbb_db_tools /** * @var object DB object */ - var $db = NULL; + var $db = null; /** * The Column types for every database we support @@ -40,6 +34,12 @@ class phpbb_db_tools var $dbms_type_map = array(); /** + * Is the used MS SQL Server a SQL Server 2000? + * @var bool + */ + protected $is_sql_server_2000; + + /** * Get the column types for every database we support * * @return array @@ -310,10 +310,10 @@ class phpbb_db_tools /** * Constructor. Set DB Object and set {@link $return_statements return_statements}. * - * @param phpbb_db_driver $db Database connection + * @param \phpbb\db\driver\driver_interface $db Database connection * @param bool $return_statements True if only statements should be returned and no SQL being executed */ - public function __construct(phpbb_db_driver $db, $return_statements = false) + public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false) { $this->db = $db; $this->return_statements = $return_statements; @@ -473,9 +473,6 @@ class phpbb_db_tools // Determine if we have created a PRIMARY KEY in the earliest $primary_key_gen = false; - // Determine if the table must be created with TEXTIMAGE - $create_textimage = false; - // Determine if the table requires a sequence $create_sequence = false; @@ -492,13 +489,22 @@ class phpbb_db_tools break; } + if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') + { + if (!isset($table_data['PRIMARY_KEY'])) + { + $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment'); + $table_data['PRIMARY_KEY'] = 'mssqlindex'; + } + } + // Iterate through the columns to create a table foreach ($table_data['COLUMNS'] as $column_name => $column_data) { // here lies an array, filled with information compiled on the column's data $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen" + if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen" { trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR); } @@ -522,12 +528,6 @@ class phpbb_db_tools $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set']; } - // create textimage DDL based off of the existance of certain column types - if (!$create_textimage) - { - $create_textimage = isset($prepared_column['textimage']) && $prepared_column['textimage']; - } - // create sequence DDL based off of the existance of auto incrementing columns if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment']) { @@ -542,13 +542,9 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'firebird': - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - case 'mssql': case 'mssqlnative': - $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : ''); + $table_sql .= "\n);"; $statements[] = $table_sql; break; } @@ -902,7 +898,7 @@ class phpbb_db_tools } } - // Add unqiue indexes? + // Add unique indexes? if (!empty($schema_changes['add_unique_index'])) { foreach ($schema_changes['add_unique_index'] as $table => $index_array) @@ -1313,7 +1309,7 @@ class phpbb_db_tools } /** - * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. + * Check if a specified index exists in table. Does not return PRIMARY KEY indexes. * * @param string $table_name Table to check the index at * @param string $index_name The index name to check @@ -1480,52 +1476,7 @@ class phpbb_db_tools } // Get type - if (strpos($column_data[0], ':') !== false) - { - list($orig_column_type, $column_length) = explode(':', $column_data[0]); - if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) - { - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); - } - else - { - if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'])) - { - switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0]) - { - case 'div': - $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1]; - $column_length = ceil($column_length); - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); - break; - } - } - - if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'])) - { - switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0]) - { - case 'mult': - $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1]; - if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2]) - { - $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3]; - } - else - { - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); - } - break; - } - } - } - $orig_column_type .= ':'; - } - else - { - $orig_column_type = $column_data[0]; - $column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]]; - } + list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]); // Adjust default value if db-dependent specified if (is_array($column_data[1])) @@ -1701,6 +1652,65 @@ class phpbb_db_tools } /** + * Get the column's database type from the type map + * + * @param string $column_map_type + * @return array column type for this database + * and map type without length + */ + function get_column_type($column_map_type) + { + if (strpos($column_map_type, ':') !== false) + { + list($orig_column_type, $column_length) = explode(':', $column_map_type); + if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) + { + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); + } + else + { + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0]) + { + case 'div': + $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1]; + $column_length = ceil($column_length); + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + break; + } + } + + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0]) + { + case 'mult': + $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1]; + if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2]) + { + $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3]; + } + else + { + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + } + break; + } + } + } + $orig_column_type .= ':'; + } + else + { + $orig_column_type = $column_map_type; + $column_type = $this->dbms_type_map[$this->sql_layer][$column_map_type]; + } + + return array($column_type, $orig_column_type); + } + + /** * Add new column */ function sql_column_add($table_name, $column_name, $column_data, $inline = false) @@ -1842,23 +1852,46 @@ class phpbb_db_tools case 'mssql': case 'mssqlnative': - // remove default cosntraints first - // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx - $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) - SET @drop_default_name = - (SELECT so.name FROM sysobjects so - JOIN sysconstraints sc ON so.id = sc.constid - WHERE object_name(so.parent_obj) = '{$table_name}' - AND so.xtype = 'D' - AND sc.colid = (SELECT colid FROM syscolumns - WHERE id = object_id('{$table_name}') - AND name = '{$column_name}')) - IF @drop_default_name <> '' - BEGIN - SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' - EXEC(@cmd) - END"; + // We need the data here + $old_return_statements = $this->return_statements; + $this->return_statements = true; + + $indexes = $this->mssql_get_existing_indexes($table_name, $column_name); + + // Drop any indexes + $recreate_indexes = array(); + if (!empty($indexes)) + { + foreach ($indexes as $index_name => $index_data) + { + $result = $this->sql_index_drop($table_name, $index_name); + $statements = array_merge($statements, $result); + if (sizeof($index_data) > 1) + { + // Remove this column from the index and recreate it + $recreate_indexes[$index_name] = array_diff($index_data, array($column_name)); + } + } + } + + // Drop default value constraint + $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name); + $statements = array_merge($statements, $result); + + // Remove the column $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; + + if (!empty($recreate_indexes)) + { + // Recreate indexes after we removed the column + foreach ($recreate_indexes as $index_name => $index_data) + { + $result = $this->sql_create_index($table_name, $index_name, $index_data); + $statements = array_merge($statements, $result); + } + } + + $this->return_statements = $old_return_statements; break; case 'mysql_40': @@ -2061,7 +2094,7 @@ class phpbb_db_tools $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD "; $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED ("; $sql .= '[' . implode("],\n\t\t[", $column) . ']'; - $sql .= ') ON [PRIMARY]'; + $sql .= ')'; $statements[] = $sql; break; @@ -2159,7 +2192,7 @@ class phpbb_db_tools case 'mssql': case 'mssqlnative': - $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; + $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])'; break; } @@ -2212,7 +2245,7 @@ class phpbb_db_tools case 'mssql': case 'mssqlnative': - $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; + $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])'; break; } @@ -2340,28 +2373,46 @@ class phpbb_db_tools case 'mssql': case 'mssqlnative': + // We need the data here + $old_return_statements = $this->return_statements; + $this->return_statements = true; + + $indexes = $this->mssql_get_existing_indexes($table_name, $column_name); + + // Drop any indexes + if (!empty($indexes)) + { + foreach ($indexes as $index_name => $index_data) + { + $result = $this->sql_index_drop($table_name, $index_name); + $statements = array_merge($statements, $result); + } + } + + // Drop default value constraint + $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name); + $statements = array_merge($statements, $result); + + // Change the column $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; if (!empty($column_data['default'])) { - // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage - $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) - SET @drop_default_name = - (SELECT so.name FROM sysobjects so - JOIN sysconstraints sc ON so.id = sc.constid - WHERE object_name(so.parent_obj) = '{$table_name}' - AND so.xtype = 'D' - AND sc.colid = (SELECT colid FROM syscolumns - WHERE id = object_id('{$table_name}') - AND name = '{$column_name}')) - IF @drop_default_name <> '' - BEGIN - SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' - EXEC(@cmd) - END - SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]' - EXEC(@cmd)"; + // Add new default value constraint + $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $this->db->sql_escape($column_data['default']) . ' FOR [' . $column_name . ']'; + } + + if (!empty($indexes)) + { + // Recreate indexes after we changed the column + foreach ($indexes as $index_name => $index_data) + { + $result = $this->sql_create_index($table_name, $index_name, $index_data); + $statements = array_merge($statements, $result); + } } + + $this->return_statements = $old_return_statements; break; case 'mysql_40': @@ -2495,4 +2546,159 @@ class phpbb_db_tools return $this->_sql_run_sql($statements); } + + /** + * Get queries to drop the default constraints of a column + * + * We need to drop the default constraints of a column, + * before being able to change their type or deleting them. + * + * @param string $table_name + * @param string $column_name + * @return array Array with SQL statements + */ + protected function mssql_get_drop_default_constraints_queries($table_name, $column_name) + { + $statements = array(); + if ($this->mssql_is_sql_server_2000()) + { + // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx + // Deprecated in SQL Server 2005 + $sql = "SELECT so.name AS def_name + FROM sysobjects so + JOIN sysconstraints sc ON so.id = sc.constid + WHERE object_name(so.parent_obj) = '{$table_name}' + AND so.xtype = 'D' + AND sc.colid = (SELECT colid FROM syscolumns + WHERE id = object_id('{$table_name}') + AND name = '{$column_name}')"; + } + else + { + $sql = "SELECT dobj.name AS def_name + FROM sys.columns col + LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D') + WHERE col.object_id = object_id('{$table_name}') + AND col.name = '{$column_name}' + AND dobj.name IS NOT NULL"; + } + + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']'; + } + $this->db->sql_freeresult($result); + + return $statements; + } + + /** + * Get a list with existing indexes for the column + * + * @param string $table_name + * @param string $column_name + * @return array Array with Index name => columns + */ + protected function mssql_get_existing_indexes($table_name, $column_name) + { + $existing_indexes = array(); + if ($this->mssql_is_sql_server_2000()) + { + // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx + // Deprecated in SQL Server 2005 + $sql = "SELECT DISTINCT ix.name AS phpbb_index_name + FROM sysindexes ix + INNER JOIN sysindexkeys ixc + ON ixc.id = ix.id + AND ixc.indid = ix.indid + INNER JOIN syscolumns cols + ON cols.colid = ixc.colid + AND cols.id = ix.id + WHERE ix.id = object_id('{$table_name}') + AND cols.name = '{$column_name}'"; + } + else + { + $sql = "SELECT DISTINCT ix.name AS phpbb_index_name + FROM sys.indexes ix + INNER JOIN sys.index_columns ixc + ON ixc.object_id = ix.object_id + AND ixc.index_id = ix.index_id + INNER JOIN sys.columns cols + ON cols.column_id = ixc.column_id + AND cols.object_id = ix.object_id + WHERE ix.object_id = object_id('{$table_name}') + AND cols.name = '{$column_name}'"; + } + + $result = $this->db->sql_query($sql); + $existing_indexes = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $existing_indexes[$row['phpbb_index_name']] = array(); + } + $this->db->sql_freeresult($result); + + if (empty($existing_indexes)) + { + return array(); + } + + if ($this->mssql_is_sql_server_2000()) + { + $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name + FROM sysindexes ix + INNER JOIN sysindexkeys ixc + ON ixc.id = ix.id + AND ixc.indid = ix.indid + INNER JOIN syscolumns cols + ON cols.colid = ixc.colid + AND cols.id = ix.id + WHERE ix.id = object_id('{$table_name}') + AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes)); + } + else + { + $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name + FROM sys.indexes ix + INNER JOIN sys.index_columns ixc + ON ixc.object_id = ix.object_id + AND ixc.index_id = ix.index_id + INNER JOIN sys.columns cols + ON cols.column_id = ixc.column_id + AND cols.object_id = ix.object_id + WHERE ix.object_id = object_id('{$table_name}') + AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes)); + } + + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name']; + } + $this->db->sql_freeresult($result); + + return $existing_indexes; + } + + /** + * Is the used MS SQL Server a SQL Server 2000? + * + * @return bool + */ + protected function mssql_is_sql_server_2000() + { + if ($this->is_sql_server_2000 === null) + { + $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version"; + $result = $this->db->sql_query($sql); + $properties = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8'; + } + + return $this->is_sql_server_2000; + } } diff --git a/phpBB/phpbb/di/extension/config.php b/phpBB/phpbb/di/extension/config.php index 6c272a6588..2603e7b358 100644 --- a/phpBB/phpbb/di/extension/config.php +++ b/phpBB/phpbb/di/extension/config.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di\extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -23,7 +17,7 @@ use Symfony\Component\Config\FileLocator; /** * Container config extension */ -class phpbb_di_extension_config extends Extension +class config extends Extension { public function __construct($config_file) { @@ -76,7 +70,7 @@ class phpbb_di_extension_config extends Extension { if (preg_match('#^[a-z]+$#', $acm_type)) { - return 'phpbb_cache_driver_'.$acm_type; + return 'phpbb\\cache\\driver\\' . $acm_type; } return $acm_type; diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 9d59a24b7e..455dfa7ecd 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di\extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -23,7 +17,7 @@ use Symfony\Component\Config\FileLocator; /** * Container core extension */ -class phpbb_di_extension_core extends Extension +class core extends Extension { /** * Config path diff --git a/phpBB/phpbb/di/extension/ext.php b/phpBB/phpbb/di/extension/ext.php index 7d9b433751..4f2f24cb1a 100644 --- a/phpBB/phpbb/di/extension/ext.php +++ b/phpBB/phpbb/di/extension/ext.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di\extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -23,7 +17,7 @@ use Symfony\Component\Config\FileLocator; /** * Container ext extension */ -class phpbb_di_extension_ext extends Extension +class ext extends Extension { protected $paths = array(); diff --git a/phpBB/phpbb/di/pass/collection_pass.php b/phpBB/phpbb/di/pass/collection_pass.php index 63a5c7dfc4..507271de3e 100644 --- a/phpBB/phpbb/di/pass/collection_pass.php +++ b/phpBB/phpbb/di/pass/collection_pass.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di\pass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -23,7 +17,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; * the services tagged with the appropriate name defined in the collection's * service_collection tag. */ -class phpbb_di_pass_collection_pass implements CompilerPassInterface +class collection_pass implements CompilerPassInterface { /** * Modify the container before it is passed to the rest of the code diff --git a/phpBB/phpbb/di/pass/kernel_pass.php b/phpBB/phpbb/di/pass/kernel_pass.php index a701ebcfa6..9c2b193361 100644 --- a/phpBB/phpbb/di/pass/kernel_pass.php +++ b/phpBB/phpbb/di/pass/kernel_pass.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di\pass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -class phpbb_di_pass_kernel_pass implements CompilerPassInterface +class kernel_pass implements CompilerPassInterface { /** * Modify the container before it is passed to the rest of the code @@ -38,12 +32,12 @@ class phpbb_di_pass_kernel_pass implements CompilerPassInterface if (!isset($event['event'])) { - throw new InvalidArgumentException(sprintf('Service "%1$s" must define the "event" attribute on "kernel.event_listener" tags.', $id)); + throw new \InvalidArgumentException(sprintf('Service "%1$s" must define the "event" attribute on "kernel.event_listener" tags.', $id)); } if (!isset($event['method'])) { - throw new InvalidArgumentException(sprintf('Service "%1$s" must define the "method" attribute on "kernel.event_listener" tags.', $id)); + throw new \InvalidArgumentException(sprintf('Service "%1$s" must define the "method" attribute on "kernel.event_listener" tags.', $id)); } $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); @@ -55,11 +49,11 @@ class phpbb_di_pass_kernel_pass implements CompilerPassInterface // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $container->getDefinition($id)->getClass(); - $refClass = new ReflectionClass($class); + $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; if (!$refClass->implementsInterface($interface)) { - throw new InvalidArgumentException(sprintf('Service "%1$s" must implement interface "%2$s".', $id, $interface)); + throw new \InvalidArgumentException(sprintf('Service "%1$s" must implement interface "%2$s".', $id, $interface)); } $definition->addMethodCall('addSubscriberService', array($id, $class)); diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php index 880cb46d4d..65df9ab1d1 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\di; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -22,7 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * * @package phpBB3 */ -class phpbb_di_service_collection extends ArrayObject +class service_collection extends \ArrayObject { /** * Constructor diff --git a/phpBB/phpbb/error_collector.php b/phpBB/phpbb/error_collector.php index 358da747b8..297972c6b8 100644 --- a/phpBB/phpbb/error_collector.php +++ b/phpBB/phpbb/error_collector.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; -class phpbb_error_collector +class error_collector { var $errors; - function phpbb_error_collector() + function __construct() { $this->errors = array(); } diff --git a/phpBB/phpbb/event/data.php b/phpBB/phpbb/event/data.php index 70718ff0ae..fbb16574ed 100644 --- a/phpBB/phpbb/event/data.php +++ b/phpBB/phpbb/event/data.php @@ -7,62 +7,56 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\Event; -class phpbb_event_data extends Event implements ArrayAccess +class data extends Event implements \ArrayAccess { - private $data; - - public function __construct(array $data = array()) - { - $this->set_data($data); - } - - public function set_data(array $data = array()) - { - $this->data = $data; - } - - public function get_data() - { - return $this->data; - } - - /** - * Returns data filtered to only include specified keys. - * - * This effectively discards any keys added to data by hooks. - */ - public function get_data_filtered($keys) - { - return array_intersect_key($this->data, array_flip($keys)); - } - - public function offsetExists($offset) - { - return isset($this->data[$offset]); - } - - public function offsetGet($offset) - { - return isset($this->data[$offset]) ? $this->data[$offset] : null; - } - - public function offsetSet($offset, $value) - { - $this->data[$offset] = $value; - } - - public function offsetUnset($offset) - { - unset($this->data[$offset]); - } + private $data; + + public function __construct(array $data = array()) + { + $this->set_data($data); + } + + public function set_data(array $data = array()) + { + $this->data = $data; + } + + public function get_data() + { + return $this->data; + } + + /** + * Returns data filtered to only include specified keys. + * + * This effectively discards any keys added to data by hooks. + */ + public function get_data_filtered($keys) + { + return array_intersect_key($this->data, array_flip($keys)); + } + + public function offsetExists($offset) + { + return isset($this->data[$offset]); + } + + public function offsetGet($offset) + { + return isset($this->data[$offset]) ? $this->data[$offset] : null; + } + + public function offsetSet($offset, $value) + { + $this->data[$offset] = $value; + } + + public function offsetUnset($offset) + { + unset($this->data[$offset]); + } } diff --git a/phpBB/phpbb/event/dispatcher.php b/phpBB/phpbb/event/dispatcher.php index 4f637ce3bb..74b35eb78d 100644 --- a/phpBB/phpbb/event/dispatcher.php +++ b/phpBB/phpbb/event/dispatcher.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; @@ -31,11 +25,11 @@ use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; * extract($phpbb_dispatcher->trigger_event('core.index', compact($vars))); * */ -class phpbb_event_dispatcher extends ContainerAwareEventDispatcher +class dispatcher extends ContainerAwareEventDispatcher { public function trigger_event($eventName, $data = array()) { - $event = new phpbb_event_data($data); + $event = new \phpbb\event\data($data); $this->dispatch($eventName, $event); return $event->get_data_filtered(array_keys($data)); } diff --git a/phpBB/phpbb/event/extension_subscriber_loader.php b/phpBB/phpbb/event/extension_subscriber_loader.php index d6284a52fb..6408f93e2a 100644 --- a/phpBB/phpbb/event/extension_subscriber_loader.php +++ b/phpBB/phpbb/event/extension_subscriber_loader.php @@ -7,39 +7,29 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -class phpbb_event_extension_subscriber_loader +class extension_subscriber_loader { private $dispatcher; - private $extension_manager; + private $listener_collection; - public function __construct(EventDispatcherInterface $dispatcher, phpbb_extension_manager $extension_manager) + public function __construct(EventDispatcherInterface $dispatcher, \phpbb\di\service_collection $listener_collection) { $this->dispatcher = $dispatcher; - $this->extension_manager = $extension_manager; + $this->listener_collection = $listener_collection; } public function load() { - $finder = $this->extension_manager->get_finder(); - $subscriber_classes = $finder - ->extension_directory('/event') - ->core_path('event/') - ->get_classes(); - - foreach ($subscriber_classes as $class) + if (!empty($this->listener_collection)) { - $subscriber = new $class(); - $this->dispatcher->addSubscriber($subscriber); + foreach ($this->listener_collection as $listener) + { + $this->dispatcher->addSubscriber($listener); + } } } } diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php index f90989a74c..8a4de1fbad 100644 --- a/phpBB/phpbb/event/kernel_exception_subscriber.php +++ b/phpBB/phpbb/event/kernel_exception_subscriber.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; @@ -21,27 +15,27 @@ use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpFoundation\Response; -class phpbb_event_kernel_exception_subscriber implements EventSubscriberInterface +class kernel_exception_subscriber implements EventSubscriberInterface { /** * Template object - * @var phpbb_template + * @var \phpbb\template\template */ protected $template; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Construct method * - * @param phpbb_template $template Template object - * @param phpbb_user $user User object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object */ - public function __construct(phpbb_template $template, phpbb_user $user) + public function __construct(\phpbb\template\template $template, \phpbb\user $user) { $this->template = $template; $this->user = $user; @@ -70,7 +64,6 @@ class phpbb_event_kernel_exception_subscriber implements EventSubscriberInterfac page_footer(true, false, false); - $status_code = $exception instanceof HttpException ? $exception->getStatusCode() : 500; $response = new Response($this->template->assign_display('body'), $status_code); $event->setResponse($response); diff --git a/phpBB/phpbb/event/kernel_request_subscriber.php b/phpBB/phpbb/event/kernel_request_subscriber.php index afb8464f80..7d5418498b 100644 --- a/phpBB/phpbb/event/kernel_request_subscriber.php +++ b/phpBB/phpbb/event/kernel_request_subscriber.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; @@ -21,11 +15,11 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\EventListener\RouterListener; use Symfony\Component\Routing\RequestContext; -class phpbb_event_kernel_request_subscriber implements EventSubscriberInterface +class kernel_request_subscriber implements EventSubscriberInterface { /** * Extension finder object - * @var phpbb_extension_finder + * @var \phpbb\extension\finder */ protected $finder; @@ -44,11 +38,11 @@ class phpbb_event_kernel_request_subscriber implements EventSubscriberInterface /** * Construct method * - * @param phpbb_extension_finder $finder Extension finder object + * @param \phpbb\extension\finder $finder Extension finder object * @param string $root_path Root path * @param string $php_ext PHP extension */ - public function __construct(phpbb_extension_finder $finder, $root_path, $php_ext) + public function __construct(\phpbb\extension\finder $finder, $root_path, $php_ext) { $this->finder = $finder; $this->root_path = $root_path; diff --git a/phpBB/phpbb/event/kernel_terminate_subscriber.php b/phpBB/phpbb/event/kernel_terminate_subscriber.php index 1eaf890e42..32dba322d1 100644 --- a/phpBB/phpbb/event/kernel_terminate_subscriber.php +++ b/phpBB/phpbb/event/kernel_terminate_subscriber.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\PostResponseEvent; -class phpbb_event_kernel_terminate_subscriber implements EventSubscriberInterface +class kernel_terminate_subscriber implements EventSubscriberInterface { /** * This listener is run when the KernelEvents::TERMINATE event is triggered diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php new file mode 100644 index 0000000000..af86882885 --- /dev/null +++ b/phpBB/phpbb/event/md_exporter.php @@ -0,0 +1,439 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\event; + +/** +* Class md_exporter +* Crawls through a markdown file and grabs all events +* +* @package phpbb\event +*/ +class md_exporter +{ + /** @var string Path where we look for files*/ + protected $path; + + /** @var string phpBB Root Path */ + protected $root_path; + + /** @var string */ + protected $filter; + + /** @var string */ + protected $current_event; + + /** @var array */ + protected $events; + + /** + * @param string $phpbb_root_path + * @param mixed $extension String 'vendor/ext' to filter, null for phpBB core + */ + public function __construct($phpbb_root_path, $extension = null) + { + $this->root_path = $phpbb_root_path; + $this->path = $this->root_path; + if ($extension) + { + $this->path .= 'ext/' . $extension . '/'; + } + + $this->events = array(); + $this->events_by_file = array(); + $this->filter = $this->current_event = ''; + } + + /** + * Get the list of all events + * + * @return array Array with events: name => details + */ + public function get_events() + { + return $this->events; + } + + /** + * @param string $md_file Relative from phpBB root + * @return int Number of events found + * @throws \LogicException + */ + public function crawl_phpbb_directory_adm($md_file) + { + $this->crawl_eventsmd($md_file, 'adm'); + + $file_list = $this->get_recursive_file_list($this->path . 'adm/style/'); + foreach ($file_list as $file) + { + $file_name = 'adm/style/' . $file; + $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name)); + } + + return sizeof($this->events); + } + + /** + * @param string $md_file Relative from phpBB root + * @return int Number of events found + * @throws \LogicException + */ + public function crawl_phpbb_directory_styles($md_file) + { + $this->crawl_eventsmd($md_file, 'styles'); + + $styles = array('prosilver', 'subsilver2'); + foreach ($styles as $style) + { + $file_list = $this->get_recursive_file_list( + $this->path . 'styles/' . $style . '/template/' + ); + + foreach ($file_list as $file) + { + $file_name = 'styles/' . $style . '/template/' . $file; + $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name)); + } + } + + return sizeof($this->events); + } + + /** + * @param string $md_file Relative from phpBB root + * @param string $filter Should be 'styles' or 'adm' + * @return int Number of events found + * @throws \LogicException + */ + public function crawl_eventsmd($md_file, $filter) + { + if (!file_exists($this->path . $md_file)) + { + throw new \LogicException("The event docs file '{$md_file}' could not be found"); + } + + $file_content = file_get_contents($this->path . $md_file); + $this->filter = $filter; + + $events = explode("\n\n", $file_content); + foreach ($events as $event) + { + // Last row of the file + if (strpos($event, "\n===\n") === false) + { + continue; + } + + list($event_name, $details) = explode("\n===\n", $event, 2); + $this->validate_event_name($event_name); + $this->current_event = $event_name; + + if (isset($this->events[$this->current_event])) + { + throw new \LogicException("The event '{$this->current_event}' is defined multiple times"); + } + + if (($this->filter == 'adm' && strpos($this->current_event, 'acp_') !== 0) + || ($this->filter == 'styles' && strpos($this->current_event, 'acp_') === 0)) + { + continue; + } + + list($file_details, $details) = explode("\n* Since: ", $details, 2); + list($since, $description) = explode("\n* Purpose: ", $details, 2); + + $files = $this->validate_file_list($file_details); + $since = $this->validate_since($since); + + $this->events[$event_name] = array( + 'event' => $this->current_event, + 'files' => $files, + 'since' => $since, + 'description' => $description, + ); + } + + return sizeof($this->events); + } + + /** + * Format the php events as a wiki table + * @return string Number of events found + */ + public function export_events_for_wiki() + { + if ($this->filter === 'adm') + { + $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"; + $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"; + } + + foreach ($this->events as $event_name => $event) + { + $wiki_page .= "|- id=\"{$event_name}\"\n"; + $wiki_page .= "| [[#{$event_name}|{$event_name}]] || "; + + if ($this->filter === 'adm') + { + $wiki_page .= implode(', ', $event['files']['adm']); + } + else + { + $wiki_page .= implode(', ', $event['files']['prosilver']) . ' || ' . implode(', ', $event['files']['subsilver2']); + } + + $wiki_page .= " || {$event['since']} || " . str_replace("\n", ' ', $event['description']) . "\n"; + } + $wiki_page .= '|}' . "\n"; + + return $wiki_page; + } + + /** + * Validates a template event name + * + * @param $event_name + * @return null + * @throws \LogicException + */ + public function validate_event_name($event_name) + { + if (!preg_match('#^([a-z][a-z0-9]*(?:_[a-z][a-z0-9]*)+)$#', $event_name)) + { + throw new \LogicException("Invalid event name '{$event_name}'"); + } + } + + /** + * Validate "Since" Information + * + * @param string $since + * @return string + * @throws \LogicException + */ + public function validate_since($since) + { + if (!preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?$#', $since)) + { + throw new \LogicException("Invalid since information found for event '{$this->current_event}'"); + } + + return $since; + } + + /** + * Validate the files list + * + * @param string $file_details + * @return array + * @throws \LogicException + */ + public function validate_file_list($file_details) + { + $files_list = array( + 'prosilver' => array(), + 'subsilver2' => array(), + 'adm' => array(), + ); + + // Multi file list + if (strpos($file_details, "* Locations:\n + ") === 0) + { + $file_details = substr($file_details, strlen("* Locations:\n + ")); + $files = explode("\n + ", $file_details); + foreach ($files as $file) + { + if (!file_exists($this->path . $file) || substr($file, -5) !== '.html') + { + throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1); + } + + if (($this->filter !== 'adm') && strpos($file, 'styles/prosilver/template/') === 0) + { + $files_list['prosilver'][] = substr($file, strlen('styles/prosilver/template/')); + } + else if (($this->filter !== 'adm') && strpos($file, 'styles/subsilver2/template/') === 0) + { + $files_list['subsilver2'][] = substr($file, strlen('styles/subsilver2/template/')); + } + else if (($this->filter === 'adm') && strpos($file, 'adm/style/') === 0) + { + $files_list['adm'][] = substr($file, strlen('adm/style/')); + } + else + { + throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 2); + } + + $this->events_by_file[$file][] = $this->current_event; + } + } + else if ($this->filter == 'adm') + { + $file = substr($file_details, strlen('* Location: ')); + if (!file_exists($this->path . $file) || substr($file, -5) !== '.html') + { + throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1); + } + + $files_list['adm'][] = substr($file, strlen('adm/style/')); + + $this->events_by_file[$file][] = $this->current_event; + } + else + { + throw new \LogicException("Invalid file list found for event '{$this->current_event}'", 2); + } + + return $files_list; + } + + /** + * Get all template events in a template file + * + * @param string $file + * @return array + * @throws \LogicException + */ + public function crawl_file_for_events($file) + { + if (!file_exists($this->path . $file)) + { + throw new \LogicException("File '{$file}' does not exist", 1); + } + + $event_list = array(); + $file_content = file_get_contents($this->path . $file); + + $events = explode('<!-- EVENT ', $file_content); + // Remove the code before the first event + array_shift($events); + foreach ($events as $event) + { + $event = explode(' -->', $event, 2); + $event_list[] = array_shift($event); + } + + return $event_list; + } + + /** + * Validates whether all events from $file are in the md file and vice-versa + * + * @param string $file + * @param array $events + * @return true + * @throws \LogicException + */ + public function validate_events_from_file($file, array $events) + { + if (empty($this->events_by_file[$file]) && empty($events)) + { + return true; + } + else if (empty($this->events_by_file[$file])) + { + $event_list = implode("', '", $events); + throw new \LogicException("File '{$file}' should not contain events, but contains: " + . "'{$event_list}'", 1); + } + else if (empty($events)) + { + $event_list = implode("', '", $this->events_by_file[$file]); + throw new \LogicException("File '{$file}' contains no events, but should contain: " + . "'{$event_list}'", 1); + } + + $missing_events_from_file = array(); + foreach ($this->events_by_file[$file] as $event) + { + if (!in_array($event, $events)) + { + $missing_events_from_file[] = $event; + } + } + + if (!empty($missing_events_from_file)) + { + $event_list = implode("', '", $missing_events_from_file); + throw new \LogicException("File '{$file}' does not contain events: '{$event_list}'", 2); + } + + $missing_events_from_md = array(); + foreach ($events as $event) + { + if (!in_array($event, $this->events_by_file[$file])) + { + $missing_events_from_md[] = $event; + } + } + + if (!empty($missing_events_from_md)) + { + $event_list = implode("', '", $missing_events_from_md); + throw new \LogicException("File '{$file}' contains additional events: '{$event_list}'", 3); + } + + return true; + } + + /** + * Returns a list of files in $dir + * + * Works recursive with any depth + * + * @param string $dir Directory to go through + * @return array List of files (including directories) + */ + public function get_recursive_file_list($dir) + { + try + { + $iterator = new \RecursiveIteratorIterator( + new \phpbb\recursive_dot_prefix_filter_iterator( + new \RecursiveDirectoryIterator( + $dir, + \FilesystemIterator::SKIP_DOTS + ) + ), + \RecursiveIteratorIterator::SELF_FIRST + ); + } + catch (\Exception $e) + { + return array(); + } + + $files = array(); + foreach ($iterator as $file_info) + { + /** @var \RecursiveDirectoryIterator $file_info */ + if ($file_info->isDir()) + { + continue; + } + + $relative_path = $iterator->getInnerIterator()->getSubPathname(); + + if (substr($relative_path, -5) == '.html') + { + $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path); + } + } + + return $files; + } +} diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php new file mode 100644 index 0000000000..d86ee3c045 --- /dev/null +++ b/phpBB/phpbb/event/php_exporter.php @@ -0,0 +1,608 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\event; + +/** +* Class php_exporter +* Crawls through a list of files and grabs all php-events +* +* @package phpbb\event +*/ +class php_exporter +{ + /** @var string Path where we look for files*/ + protected $path; + + /** @var string phpBB Root Path */ + protected $root_path; + + /** @var string */ + protected $current_file; + + /** @var string */ + protected $current_event; + + /** @var int */ + protected $current_event_line; + + /** @var array */ + protected $events; + + /** @var array */ + protected $file_lines; + + /** + * @param string $phpbb_root_path + * @param mixed $extension String 'vendor/ext' to filter, null for phpBB core + */ + public function __construct($phpbb_root_path, $extension = 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->path = $this->root_path; + if ($extension) + { + $this->path .= 'ext/' . $extension . '/'; + } + } + + /** + * Get the list of all events + * + * @return array Array with events: name => details + */ + public function get_events() + { + return $this->events; + } + + /** + * Set current event data + * + * @param string $name Name of the current event (used for error messages) + * @param int $line Line where the current event is placed in + * @return null + */ + public function set_current_event($name, $line) + { + $this->current_event = $name; + $this->current_event_line = $line; + } + + /** + * Set the content of this file + * + * @param array $content Array with the lines of the file + * @return null + */ + public function set_content($content) + { + $this->file_lines = $content; + } + + /** + * Crawl the phpBB/ directory for php events + * @return int The number of events found + */ + public function crawl_phpbb_directory_php() + { + $files = $this->get_recursive_file_list(); + $this->events = array(); + foreach ($files as $file) + { + $this->crawl_php_file($file); + } + ksort($this->events); + + return sizeof($this->events); + } + + /** + * Returns a list of files in $dir + * + * @return array List of files (including the path) + */ + public function get_recursive_file_list() + { + try + { + $iterator = new \RecursiveIteratorIterator( + new \phpbb\event\recursive_event_filter_iterator( + new \RecursiveDirectoryIterator( + $this->path, + \FilesystemIterator::SKIP_DOTS + ), + $this->path + ), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + } + catch (\Exception $e) + { + return array(); + } + + $files = array(); + foreach ($iterator as $file_info) + { + /** @var \RecursiveDirectoryIterator $file_info */ + $relative_path = $iterator->getInnerIterator()->getSubPathname(); + $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path); + } + + return $files; + } + + /** + * Format the php events as a wiki table + * @return string + */ + public function export_events_for_wiki() + { + $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) + { + $wiki_page .= '|- id="' . $event['event'] . '"' . "\n"; + $wiki_page .= '| [[#' . $event['event'] . '|' . $event['event'] . ']] || ' . $event['file'] . ' || ' . implode(', ', $event['arguments']) . ' || ' . $event['since'] . ' || ' . $event['description'] . "\n"; + } + $wiki_page .= '|}' . "\n"; + + return $wiki_page; + } + + /** + * @param string $file + * @return int Number of events found in this file + * @throws \LogicException + */ + public function crawl_php_file($file) + { + $this->current_file = $file; + $this->file_lines = array(); + $content = file_get_contents($this->path . $this->current_file); + $num_events_found = 0; + + if (strpos($content, "dispatcher->trigger_event('") || strpos($content, "dispatcher->dispatch('")) + { + $this->set_content(explode("\n", $content)); + for ($i = 0, $num_lines = sizeof($this->file_lines); $i < $num_lines; $i++) + { + $event_line = false; + $found_trigger_event = strpos($this->file_lines[$i], "dispatcher->trigger_event('"); + $arguments = array(); + if ($found_trigger_event !== false) + { + $event_line = $i; + $this->set_current_event($this->get_event_name($event_line, false), $event_line); + + // Find variables of the event + $arguments = $this->get_vars_from_array(); + $doc_vars = $this->get_vars_from_docblock(); + $this->validate_vars_docblock_array($arguments, $doc_vars); + } + else + { + $found_dispatch = strpos($this->file_lines[$i], "dispatcher->dispatch('"); + if ($found_dispatch !== false) + { + $event_line = $i; + $this->set_current_event($this->get_event_name($event_line, true), $event_line); + } + } + + if ($event_line) + { + // Validate @event + $event_line_num = $this->find_event(); + $this->validate_event($this->current_event, $this->file_lines[$event_line_num]); + + // Validate @since + $since_line_num = $this->find_since(); + $since = $this->validate_since($this->file_lines[$since_line_num]); + + // Find event description line + $description_line_num = $this->find_description(); + $description = substr(trim($this->file_lines[$description_line_num]), strlen('* ')); + + if (isset($this->events[$this->current_event])) + { + throw new \LogicException("The event '{$this->current_event}' from file " + . "'{$this->current_file}:{$event_line_num}' already exists in file " + . "'{$this->events[$this->current_event]['file']}'", 10); + } + + sort($arguments); + $this->events[$this->current_event] = array( + 'event' => $this->current_event, + 'file' => $this->current_file, + 'arguments' => $arguments, + 'since' => $since, + 'description' => $description, + ); + $num_events_found++; + } + } + } + + return $num_events_found; + } + + /** + * Find the name of the event inside the dispatch() line + * + * @param int $event_line + * @param bool $is_dispatch Do we look for dispatch() or trigger_event() ? + * @return string Name of the event + * @throws \LogicException + */ + public function get_event_name($event_line, $is_dispatch) + { + $event_text_line = $this->file_lines[$event_line]; + $event_text_line = ltrim($event_text_line, "\t"); + + if ($is_dispatch) + { + $regex = '#\$([a-z](?:[a-z0-9_]|->)*)'; + $regex .= '->dispatch\('; + $regex .= '\'' . $this->preg_match_event_name() . '\''; + $regex .= '\);#'; + } + else + { + $regex = '#extract\(\$([a-z](?:[a-z0-9_]|->)*)'; + $regex .= '->trigger_event\('; + $regex .= '\'' . $this->preg_match_event_name() . '\''; + $regex .= ', compact\(\$vars\)\)\);#'; + } + + $match = array(); + preg_match($regex, $event_text_line, $match); + if (!isset($match[2])) + { + throw new \LogicException("Can not find event name in line '{$event_text_line}' " + . "in file '{$this->current_file}:{$event_line}'", 1); + } + + return $match[2]; + } + + /** + * Returns a regex match for the event name + * + * @return string + */ + protected function preg_match_event_name() + { + return '([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+)'; + } + + /** + * Find the $vars array + * + * @return array List of variables + * @throws \LogicException + */ + public function get_vars_from_array() + { + $line = ltrim($this->file_lines[$this->current_event_line - 1], "\t"); + if ($line === ');') + { + $vars_array = $this->get_vars_from_multi_line_array(); + } + else + { + $vars_array = $this->get_vars_from_single_line_array($line); + } + + foreach ($vars_array as $var) + { + if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var)) + { + throw new \LogicException("Found invalid var '{$var}' in array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); + } + } + + sort($vars_array); + return $vars_array; + } + + /** + * Find the variables in single line array + * + * @param string $line + * @param bool $throw_multiline Throw an exception when there are too + * many arguments in one line. + * @return array List of variables + * @throws \LogicException + */ + public function get_vars_from_single_line_array($line, $throw_multiline = true) + { + $match = array(); + preg_match('#^\$vars = array\(\'([a-zA-Z0-9_\' ,]+)\'\);$#', $line, $match); + + if (isset($match[1])) + { + $vars_array = explode("', '", $match[1]); + if ($throw_multiline && sizeof($vars_array) > 6) + { + throw new \LogicException('Should use multiple lines for $vars definition ' + . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + return $vars_array; + } + else + { + throw new \LogicException("Can not find '\$vars = array();'-line for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); + } + } + + /** + * Find the variables in single line array + * + * @return array List of variables + * @throws \LogicException + */ + public function get_vars_from_multi_line_array() + { + $current_vars_line = 2; + $var_lines = array(); + while (ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t") !== '$vars = array(') + { + $var_lines[] = substr(trim($this->file_lines[$this->current_event_line - $current_vars_line]), 0, -1); + + $current_vars_line++; + if ($current_vars_line > $this->current_event_line) + { + // Reached the start of the file + throw new \LogicException("Can not find end of \$vars array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + } + + return $this->get_vars_from_single_line_array('$vars = array(' . implode(", ", $var_lines) . ');', false); + } + + /** + * Find the $vars array + * + * @return array List of variables + * @throws \LogicException + */ + public function get_vars_from_docblock() + { + $doc_vars = array(); + $current_doc_line = 1; + $found_comment_end = false; + while (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") !== '/**') + { + if (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") === '*/') + { + $found_comment_end = true; + } + + if ($found_comment_end) + { + $var_line = trim($this->file_lines[$this->current_event_line - $current_doc_line]); + $var_line = preg_replace('!\s+!', ' ', $var_line); + if (strpos($var_line, '* @var ') === 0) + { + $doc_line = explode(' ', $var_line, 5); + if (sizeof($doc_line) !== 5) + { + throw new \LogicException("Found invalid line '{$this->file_lines[$this->current_event_line - $current_doc_line]}' " + . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); + } + $doc_vars[] = $doc_line[3]; + } + } + + $current_doc_line++; + if ($current_doc_line > $this->current_event_line) + { + // Reached the start of the file + throw new \LogicException("Can not find end of docblock for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + } + + if (empty($doc_vars)) + { + // Reached the start of the file + throw new \LogicException("Can not find @var lines for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); + } + + foreach ($doc_vars as $var) + { + if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var)) + { + throw new \LogicException("Found invalid @var '{$var}' in docblock for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 4); + } + } + + sort($doc_vars); + return $doc_vars; + } + + /** + * Find the "@since" Information line + * + * @return int Absolute line number + * @throws \LogicException + */ + public function find_since() + { + return $this->find_tag('since', array('event', 'var')); + } + + /** + * Find the "@event" Information line + * + * @return int Absolute line number + */ + public function find_event() + { + return $this->find_tag('event', array()); + } + + /** + * Find a "@*" Information line + * + * @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 + * @return int Absolute line number + * @throws \LogicException + */ + public function find_tag($find_tag, $disallowed_tags) + { + $find_tag_line = 0; + $found_comment_end = 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") === '/**') + { + // Reached the start of this doc block + throw new \LogicException("Can not find '@{$find_tag}' information for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); + } + + foreach ($disallowed_tags as $disallowed_tag) + { + if ($found_comment_end && strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t"), '* @' . $disallowed_tag) === 0) + { + // Found @var after the @since + throw new \LogicException("Found '@{$disallowed_tag}' information after '@{$find_tag}' for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); + } + } + + if (ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '*/') + { + $found_comment_end = true; + } + + $find_tag_line++; + if ($find_tag_line >= $this->current_event_line) + { + // Reached the start of the file + throw new \LogicException("Can not find '@{$find_tag}' information for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + } + + return $this->current_event_line - $find_tag_line; + } + + /** + * Find a "@*" Information line + * + * @return int Absolute line number + * @throws \LogicException + */ + public function find_description() + { + $find_desc_line = 0; + while (ltrim($this->file_lines[$this->current_event_line - $find_desc_line], "\t") !== '/**') + { + $find_desc_line++; + if ($find_desc_line > $this->current_event_line) + { + // Reached the start of the file + throw new \LogicException("Can not find a description for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); + } + } + + $find_desc_line = $this->current_event_line - $find_desc_line + 1; + + $desc = trim($this->file_lines[$find_desc_line]); + if (strpos($desc, '* @') === 0 || $desc[0] !== '*' || substr($desc, 1) == '') + { + // First line of the doc block is a @-line, empty or only contains "*" + throw new \LogicException("Can not find a description for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + + return $find_desc_line; + } + + /** + * Validate "@since" Information + * + * @param string $line + * @return string + * @throws \LogicException + */ + public function validate_since($line) + { + $match = array(); + preg_match('#^\* @since (\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?)$#', ltrim($line, "\t"), $match); + if (!isset($match[1])) + { + throw new \LogicException("Invalid '@since' information for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); + } + + return $match[1]; + } + + /** + * Validate "@event" Information + * + * @param string $event_name + * @param string $line + * @return string + * @throws \LogicException + */ + public function validate_event($event_name, $line) + { + $event = substr(ltrim($line, "\t"), strlen('* @event ')); + + if ($event !== trim($event)) + { + throw new \LogicException("Invalid '@event' information for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); + } + + if ($event !== $event_name) + { + throw new \LogicException("Event name does not match '@event' tag for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); + } + + return $event; + } + + /** + * Validates that two arrays contain the same strings + * + * @param array $vars_array Variables found in the array line + * @param array $vars_docblock Variables found in the doc block + * @return null + * @throws \LogicException + */ + public function validate_vars_docblock_array($vars_array, $vars_docblock) + { + $vars_array = array_unique($vars_array); + $vars_docblock = array_unique($vars_docblock); + $sizeof_vars_array = sizeof($vars_array); + + if ($sizeof_vars_array !== sizeof($vars_docblock) || $sizeof_vars_array !== sizeof(array_intersect($vars_array, $vars_docblock))) + { + throw new \LogicException("\$vars array does not match the list of '@var' tags for event " + . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); + } + } +} diff --git a/phpBB/phpbb/event/recursive_event_filter_iterator.php b/phpBB/phpbb/event/recursive_event_filter_iterator.php new file mode 100644 index 0000000000..ef2f2ec0ed --- /dev/null +++ b/phpBB/phpbb/event/recursive_event_filter_iterator.php @@ -0,0 +1,70 @@ +<?php +/** +* +* @package event +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\event; + +/** +* Class recursive_event_filter_iterator +* +* This filter ignores directories and files starting with a dot. +* It also skips some directories that do not contain events anyway, +* such as e.g. files/, store/ and vendor/ +* +* @package phpbb\event +*/ +class recursive_event_filter_iterator extends \RecursiveFilterIterator +{ + protected $root_path; + + /** + * Construct + * + * @param \RecursiveIterator $iterator + * @param string $root_path + */ + public function __construct(\RecursiveIterator $iterator, $root_path) + { + $this->root_path = str_replace(DIRECTORY_SEPARATOR, '/', $root_path); + parent::__construct($iterator); + } + + /** + * Return the inner iterator's children contained in a recursive_event_filter_iterator + * + * @return recursive_event_filter_iterator + */ + public function getChildren() { + return new self($this->getInnerIterator()->getChildren(), $this->root_path); + } + + /** + * {@inheritDoc} + */ + public function accept() + { + $relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $this->current()); + $filename = $this->current()->getFilename(); + + return (substr($relative_path, -4) === '.php' || $this->current()->isDir()) + && $filename[0] !== '.' + && strpos($relative_path, $this->root_path . 'cache/') !== 0 + && strpos($relative_path, $this->root_path . 'develop/') !== 0 + && strpos($relative_path, $this->root_path . 'docs/') !== 0 + && strpos($relative_path, $this->root_path . 'ext/') !== 0 + && strpos($relative_path, $this->root_path . 'files/') !== 0 + && strpos($relative_path, $this->root_path . 'includes/utf/') !== 0 + && strpos($relative_path, $this->root_path . 'language/') !== 0 + && strpos($relative_path, $this->root_path . 'phpbb/db/migration/data/') !== 0 + && strpos($relative_path, $this->root_path . 'phpbb/event/') !== 0 + && strpos($relative_path, $this->root_path . 'store/') !== 0 + && strpos($relative_path, $this->root_path . 'tests/') !== 0 + && strpos($relative_path, $this->root_path . 'vendor/') !== 0 + ; + } +} diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index c4462b64d8..1f871750e0 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -22,15 +16,15 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * * @package extension */ -class phpbb_extension_base implements phpbb_extension_interface +class base implements \phpbb\extension\extension_interface { /** @var ContainerInterface */ protected $container; - /** @var phpbb_extension_finder */ + /** @var \phpbb\extension\finder */ protected $finder; - /** @var phpbb_db_migrator */ + /** @var \phpbb\db\migrator */ protected $migrator; /** @var string */ @@ -43,11 +37,11 @@ class phpbb_extension_base implements phpbb_extension_interface * Constructor * * @param ContainerInterface $container Container object - * @param phpbb_extension_finder $extension_finder + * @param \phpbb\extension\finder $extension_finder * @param string $extension_name Name of this extension (from ext.manager) * @param string $extension_path Relative path to this extension */ - public function __construct(ContainerInterface $container, phpbb_extension_finder $extension_finder, phpbb_db_migrator $migrator, $extension_name, $extension_path) + public function __construct(ContainerInterface $container, \phpbb\extension\finder $extension_finder, \phpbb\db\migrator $migrator, $extension_name, $extension_path) { $this->container = $container; $this->extension_finder = $extension_finder; diff --git a/phpBB/phpbb/extension/exception.php b/phpBB/phpbb/extension/exception.php index e08a8912ea..82327c9d5e 100644 --- a/phpBB/phpbb/extension/exception.php +++ b/phpBB/phpbb/extension/exception.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; /** * Exception class for metadata */ -class phpbb_extension_exception extends UnexpectedValueException +class exception extends \UnexpectedValueException { public function __toString() { return $this->getMessage(); } -}
\ No newline at end of file +} diff --git a/phpBB/phpbb/extension/interface.php b/phpBB/phpbb/extension/extension_interface.php index 7b36a12bf6..bddff51b5a 100644 --- a/phpBB/phpbb/extension/interface.php +++ b/phpBB/phpbb/extension/extension_interface.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; /** * The interface extension meta classes have to implement to run custom code @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package extension */ -interface phpbb_extension_interface +interface extension_interface { /** * enable_step is executed on enabling an extension until it returns false. diff --git a/phpBB/phpbb/extension/finder.php b/phpBB/phpbb/extension/finder.php index 155a41cda5..6cc6e1808a 100644 --- a/phpBB/phpbb/extension/finder.php +++ b/phpBB/phpbb/extension/finder.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; /** * The extension finder provides a simple way to locate files in active extensions * * @package extension */ -class phpbb_extension_finder +class finder { protected $extension_manager; protected $filesystem; @@ -52,17 +46,17 @@ class phpbb_extension_finder /** * Creates a new finder instance with its dependencies * - * @param phpbb_extension_manager $extension_manager An extension manager + * @param \phpbb\extension\manager $extension_manager An extension manager * instance that provides the finder with a list of active * extensions and their locations - * @param phpbb_filesystem $filesystem Filesystem instance + * @param \phpbb\filesystem $filesystem Filesystem instance * @param string $phpbb_root_path Path to the phpbb root directory - * @param phpbb_cache_driver_interface $cache A cache instance or null + * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $php_ext php file extension * @param string $cache_name The name of the cache variable, defaults to * _ext_finder */ - public function __construct(phpbb_extension_manager $extension_manager, phpbb_filesystem $filesystem, $phpbb_root_path = '', phpbb_cache_driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') + public function __construct(\phpbb\extension\manager $extension_manager, \phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') { $this->extension_manager = $extension_manager; $this->filesystem = $filesystem; @@ -88,7 +82,7 @@ class phpbb_extension_finder * Sets a core path to be searched in addition to extensions * * @param string $core_path The path relative to phpbb_root_path - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function core_path($core_path) { @@ -104,7 +98,7 @@ class phpbb_extension_finder * file extension is automatically added to suffixes. * * @param string $suffix A filename suffix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function suffix($suffix) { @@ -121,7 +115,7 @@ class phpbb_extension_finder * file extension is automatically added to suffixes. * * @param string $extension_suffix A filename suffix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function extension_suffix($extension_suffix) { @@ -137,7 +131,7 @@ class phpbb_extension_finder * file extension is automatically added to suffixes. * * @param string $core_suffix A filename suffix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function core_suffix($core_suffix) { @@ -149,7 +143,7 @@ class phpbb_extension_finder * Sets the prefix all files found in extensions and core must match * * @param string $prefix A filename prefix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function prefix($prefix) { @@ -162,7 +156,7 @@ class phpbb_extension_finder * Sets a prefix all files found in extensions must match * * @param string $extension_prefix A filename prefix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function extension_prefix($extension_prefix) { @@ -174,7 +168,7 @@ class phpbb_extension_finder * Sets a prefix all files found in the core path must match * * @param string $core_prefix A filename prefix - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function core_prefix($core_prefix) { @@ -189,7 +183,7 @@ class phpbb_extension_finder * the current directory. * * @param string $directory - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function directory($directory) { @@ -202,7 +196,7 @@ class phpbb_extension_finder * Sets a directory all files found in extensions must be contained in * * @param string $extension_directory - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function extension_directory($extension_directory) { @@ -214,7 +208,7 @@ class phpbb_extension_finder * Sets a directory all files found in the core path must be contained in * * @param string $core_directory - * @return phpbb_extension_finder This object for chaining calls + * @return \phpbb\extension\finder This object for chaining calls */ public function core_directory($core_directory) { @@ -275,9 +269,17 @@ class phpbb_extension_finder $classes = array(); foreach ($files as $file => $ext_name) { - $file = preg_replace('#^(phpbb|includes)/#', '', $file); - - $classes[] = 'phpbb_' . str_replace('/', '_', substr($file, 0, -strlen('.' . $this->php_ext))); + $class = substr($file, 0, -strlen('.' . $this->php_ext)); + if ($ext_name === '/' && preg_match('#^includes/#', $file)) + { + $class = preg_replace('#^includes/#', '', $class); + $classes[] = 'phpbb_' . str_replace('/', '_', $class); + } + else + { + $class = preg_replace('#^ext/#', '', $class); + $classes[] = '\\' . str_replace('/', '\\', $class); + } } return $classes; } @@ -473,14 +475,19 @@ class phpbb_extension_finder } $directory_pattern = '#' . $directory_pattern . '#'; - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); + $iterator = new \RecursiveIteratorIterator( + new \phpbb\recursive_dot_prefix_filter_iterator( + new \RecursiveDirectoryIterator( + $path, + \FilesystemIterator::SKIP_DOTS + ) + ), + \RecursiveIteratorIterator::SELF_FIRST + ); + foreach ($iterator as $file_info) { $filename = $file_info->getFilename(); - if ($filename == '.' || $filename == '..') - { - continue; - } if ($file_info->isDir() == $is_dir) { diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 4451049d04..b22fbf07a6 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -22,7 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * * @package extension */ -class phpbb_extension_manager +class manager { /** @var ContainerInterface */ protected $container; @@ -40,16 +34,16 @@ class phpbb_extension_manager * Creates a manager and loads information from database * * @param ContainerInterface $container A container - * @param phpbb_db_driver $db A database connection - * @param phpbb_config $config phpbb_config - * @param phpbb_filesystem $filesystem + * @param \phpbb\db\driver\driver_interface $db A database connection + * @param \phpbb\config\config $config \phpbb\config\config + * @param \phpbb\filesystem $filesystem * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $php_ext php file extension - * @param phpbb_cache_driver_interface $cache A cache instance or null + * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $cache_name The name of the cache variable, defaults to _ext */ - public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') + public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') { $this->container = $container; $this->phpbb_root_path = $phpbb_root_path; @@ -126,12 +120,12 @@ class phpbb_extension_manager * Instantiates the extension meta class for the extension with the given name * * @param string $name The extension name - * @return phpbb_extension_interface Instance of the extension meta class or - * phpbb_extension_base if the class does not exist + * @return \phpbb\extension\extension_interface Instance of the extension meta class or + * \phpbb\extension\base if the class does not exist */ public function get_extension($name) { - $extension_class_name = 'phpbb_ext_' . str_replace('/', '_', $name) . '_ext'; + $extension_class_name = str_replace('/', '\\', $name) . '\\ext'; $migrator = $this->container->get('migrator'); @@ -141,7 +135,7 @@ class phpbb_extension_manager } else { - return new phpbb_extension_base($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true)); + return new \phpbb\extension\base($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true)); } } @@ -150,11 +144,11 @@ class phpbb_extension_manager * * @param string $name The extension name * @param string $template The template manager - * @return phpbb_extension_metadata_manager Instance of the metadata manager + * @return \phpbb\extension\metadata_manager Instance of the metadata manager */ - public function create_extension_metadata_manager($name, phpbb_template $template) + public function create_extension_metadata_manager($name, \phpbb\template\template $template) { - return new phpbb_extension_metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path); + return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path); } /** @@ -218,6 +212,11 @@ class phpbb_extension_manager $this->cache->purge(); } + if ($active) + { + $this->config->increment('assets_version', 1); + } + return !$active; } @@ -232,7 +231,9 @@ class phpbb_extension_manager */ public function enable($name) { + // @codingStandardsIgnoreStart while ($this->enable_step($name)); + // @codingStandardsIgnoreEnd } /** @@ -309,7 +310,9 @@ class phpbb_extension_manager */ public function disable($name) { + // @codingStandardsIgnoreStart while ($this->disable_step($name)); + // @codingStandardsIgnoreEnd } /** @@ -386,7 +389,9 @@ class phpbb_extension_manager */ public function purge($name) { + // @codingStandardsIgnoreStart while ($this->purge_step($name)); + // @codingStandardsIgnoreEnd } /** @@ -403,17 +408,32 @@ class phpbb_extension_manager return $available; } - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/', FilesystemIterator::NEW_CURRENT_AND_KEY | FilesystemIterator::FOLLOW_SYMLINKS), - RecursiveIteratorIterator::SELF_FIRST); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/', \FilesystemIterator::NEW_CURRENT_AND_KEY | \FilesystemIterator::FOLLOW_SYMLINKS), + \RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file_info) { if ($file_info->isFile() && $file_info->getFilename() == 'ext.' . $this->php_ext) { $ext_name = $iterator->getInnerIterator()->getSubPath(); + $composer_file = $iterator->getPath() . '/composer.json'; + // Ignore the extension if there is no composer.json. + if (!is_readable($composer_file) || !($ext_info = file_get_contents($composer_file))) + { + continue; + } + + $ext_info = json_decode($ext_info, true); $ext_name = str_replace(DIRECTORY_SEPARATOR, '/', $ext_name); + // Ignore the extension if directory depth is not correct or if the directory structure + // does not match the name value specified in composer.json. + if (substr_count($ext_name, '/') !== 1 || !isset($ext_info['name']) || $ext_name != $ext_info['name']) + { + continue; + } + $available[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/'; } } @@ -502,12 +522,12 @@ class phpbb_extension_manager } /** - * Instantiates a phpbb_extension_finder. + * Instantiates a \phpbb\extension\finder. * - * @return phpbb_extension_finder An extension finder instance + * @return \phpbb\extension\finder An extension finder instance */ public function get_finder() { - return new phpbb_extension_finder($this, $this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder'); + return new \phpbb\extension\finder($this, $this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder'); } } diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 14b77c085b..c90445ee09 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -7,36 +7,30 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; /** * The extension metadata manager validates and gets meta-data for extensions * * @package extension */ -class phpbb_extension_metadata_manager +class metadata_manager { /** * phpBB Config instance - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * phpBB Extension Manager - * @var phpbb_extension_manager + * @var \phpbb\extension\manager */ protected $extension_manager; /** * phpBB Template instance - * @var phpbb_template + * @var \phpbb\template\template */ protected $template; @@ -68,12 +62,12 @@ class phpbb_extension_metadata_manager * Creates the metadata manager * * @param string $ext_name Name (including vendor) of the extension - * @param phpbb_config $config phpBB Config instance - * @param phpbb_extension_manager $extension_manager An instance of the phpBBb extension manager - * @param phpbb_template $template phpBB Template instance + * @param \phpbb\config\config $config phpBB Config instance + * @param \phpbb\extension\manager $extension_manager An instance of the phpBBb extension manager + * @param \phpbb\template\template $template phpBB Template instance * @param string $phpbb_root_path Path to the phpbb includes directory. */ - public function __construct($ext_name, phpbb_config $config, phpbb_extension_manager $extension_manager, phpbb_template $template, $phpbb_root_path) + public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, $phpbb_root_path) { $this->config = $config; $this->extension_manager = $extension_manager; @@ -145,7 +139,7 @@ class phpbb_extension_metadata_manager if (!file_exists($this->metadata_file)) { - throw new phpbb_extension_exception('The required file does not exist: ' . $this->metadata_file); + throw new \phpbb\extension\exception('The required file does not exist: ' . $this->metadata_file); } } @@ -158,18 +152,18 @@ class phpbb_extension_metadata_manager { if (!file_exists($this->metadata_file)) { - throw new phpbb_extension_exception('The required file does not exist: ' . $this->metadata_file); + throw new \phpbb\extension\exception('The required file does not exist: ' . $this->metadata_file); } else { if (!($file_contents = file_get_contents($this->metadata_file))) { - throw new phpbb_extension_exception('file_get_contents failed on ' . $this->metadata_file); + throw new \phpbb\extension\exception('file_get_contents failed on ' . $this->metadata_file); } - if (($metadata = json_decode($file_contents, true)) === NULL) + if (($metadata = json_decode($file_contents, true)) === null) { - throw new phpbb_extension_exception('json_decode failed on ' . $this->metadata_file); + throw new \phpbb\extension\exception('json_decode failed on ' . $this->metadata_file); } $this->metadata = $metadata; @@ -197,50 +191,50 @@ class phpbb_extension_metadata_manager * @return Bool True if valid, throws an exception if invalid */ public function validate($name = 'display') - { - // Basic fields - $fields = array( - 'name' => '#^[a-zA-Z0-9_\x7f-\xff]{2,}/[a-zA-Z0-9_\x7f-\xff]{2,}$#', - 'type' => '#^phpbb3-extension$#', - 'licence' => '#.+#', - 'version' => '#.+#', - ); - - switch ($name) - { - case 'all': - $this->validate('display'); + { + // Basic fields + $fields = array( + 'name' => '#^[a-zA-Z0-9_\x7f-\xff]{2,}/[a-zA-Z0-9_\x7f-\xff]{2,}$#', + 'type' => '#^phpbb-extension$#', + 'license' => '#.+#', + 'version' => '#.+#', + ); + + switch ($name) + { + case 'all': + $this->validate('display'); $this->validate_enable(); - break; + break; - case 'display': - foreach ($fields as $field => $data) + case 'display': + foreach ($fields as $field => $data) { $this->validate($field); } $this->validate_authors(); - break; - - default: - if (isset($fields[$name])) - { - if (!isset($this->metadata[$name])) - { - throw new phpbb_extension_exception("Required meta field '$name' has not been set."); + break; + + default: + if (isset($fields[$name])) + { + if (!isset($this->metadata[$name])) + { + throw new \phpbb\extension\exception("Required meta field '$name' has not been set."); } if (!preg_match($fields[$name], $this->metadata[$name])) { - throw new phpbb_extension_exception("Meta field '$name' is invalid."); + throw new \phpbb\extension\exception("Meta field '$name' is invalid."); } } break; } return true; - } + } /** * Validates the contents of the authors field @@ -251,14 +245,14 @@ class phpbb_extension_metadata_manager { if (empty($this->metadata['authors'])) { - throw new phpbb_extension_exception("Required meta field 'authors' has not been set."); + throw new \phpbb\extension\exception("Required meta field 'authors' has not been set."); } foreach ($this->metadata['authors'] as $author) { if (!isset($author['name'])) { - throw new phpbb_extension_exception("Required meta field 'author name' has not been set."); + throw new \phpbb\extension\exception("Required meta field 'author name' has not been set."); } } @@ -272,8 +266,8 @@ class phpbb_extension_metadata_manager */ public function validate_enable() { - // Check for phpBB, PHP versions - if (!$this->validate_require_phpbb() || !$this->validate_require_php()) + // Check for valid directory & phpBB, PHP versions + if (!$this->validate_dir() || !$this->validate_require_phpbb() || !$this->validate_require_php()) { return false; } @@ -281,6 +275,16 @@ class phpbb_extension_metadata_manager return true; } + /** + * Validates the most basic directory structure to ensure it follows <vendor>/<ext> convention. + * + * @return boolean True when passes validation + */ + public function validate_dir() + { + return (substr_count($this->ext_name, '/') === 1 && $this->ext_name == $this->get_metadata('name')); + } + /** * Validates the contents of the phpbb requirement field @@ -289,12 +293,12 @@ class phpbb_extension_metadata_manager */ public function validate_require_phpbb() { - if (!isset($this->metadata['require']['phpbb'])) + if (!isset($this->metadata['require']['phpbb/phpbb'])) { - return true; + return false; } - return $this->_validate_version($this->metadata['require']['phpbb'], $this->config['version']); + return true; } /** @@ -306,10 +310,10 @@ class phpbb_extension_metadata_manager { if (!isset($this->metadata['require']['php'])) { - return true; + return false; } - return $this->_validate_version($this->metadata['require']['php'], phpversion()); + return true; } /** @@ -347,12 +351,12 @@ class phpbb_extension_metadata_manager 'META_HOMEPAGE' => (isset($this->metadata['homepage'])) ? $this->metadata['homepage'] : '', 'META_VERSION' => (isset($this->metadata['version'])) ? htmlspecialchars($this->metadata['version']) : '', 'META_TIME' => (isset($this->metadata['time'])) ? htmlspecialchars($this->metadata['time']) : '', - 'META_LICENCE' => htmlspecialchars($this->metadata['licence']), + 'META_LICENSE' => htmlspecialchars($this->metadata['license']), 'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? htmlspecialchars($this->metadata['require']['php']) : '', 'META_REQUIRE_PHP_FAIL' => !$this->validate_require_php(), - 'META_REQUIRE_PHPBB' => (isset($this->metadata['require']['phpbb'])) ? htmlspecialchars($this->metadata['require']['phpbb']) : '', + 'META_REQUIRE_PHPBB' => (isset($this->metadata['require']['phpbb/phpbb'])) ? htmlspecialchars($this->metadata['require']['phpbb/phpbb']) : '', 'META_REQUIRE_PHPBB_FAIL' => !$this->validate_require_phpbb(), 'META_DISPLAY_NAME' => (isset($this->metadata['extra']['display-name'])) ? htmlspecialchars($this->metadata['extra']['display-name']) : '', diff --git a/phpBB/phpbb/extension/provider.php b/phpBB/phpbb/extension/provider.php index 45b55e5cab..bfdc2b66b9 100644 --- a/phpBB/phpbb/extension/provider.php +++ b/phpBB/phpbb/extension/provider.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\extension; /** * Provides a set of items found in extensions. @@ -28,7 +22,7 @@ if (!defined('IN_PHPBB')) * * @package extension */ -abstract class phpbb_extension_provider implements IteratorAggregate +abstract class provider implements \IteratorAggregate { /** * Array holding all found items @@ -38,16 +32,16 @@ abstract class phpbb_extension_provider implements IteratorAggregate /** * An extension manager to search for items in extensions - * @var phpbb_extension_manager + * @var \phpbb\extension\manager */ protected $extension_manager; /** * Constructor. Loads all available items. * - * @param phpbb_extension_manager $extension_manager phpBB extension manager + * @param \phpbb\extension\manager $extension_manager phpBB extension manager */ - public function __construct(phpbb_extension_manager $extension_manager) + public function __construct(\phpbb\extension\manager $extension_manager) { $this->extension_manager = $extension_manager; } @@ -71,6 +65,6 @@ abstract class phpbb_extension_provider implements IteratorAggregate $this->items = $this->find(); } - return new ArrayIterator($this->items); + return new \ArrayIterator($this->items); } } diff --git a/phpBB/phpbb/feed/attachments_base.php b/phpBB/phpbb/feed/attachments_base.php new file mode 100644 index 0000000000..a9a8175928 --- /dev/null +++ b/phpBB/phpbb/feed/attachments_base.php @@ -0,0 +1,83 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\feed; + +/** +* Abstract class for feeds displaying attachments +* +* @package phpBB3 +*/ +abstract class attachments_base extends \phpbb\feed\base +{ + /** + * Attachments that may be displayed + */ + protected $attachments = array(); + + /** + * Retrieve the list of attachments that may be displayed + */ + protected function fetch_attachments() + { + $sql_array = array( + 'SELECT' => 'a.*', + 'FROM' => array( + ATTACHMENTS_TABLE => 'a' + ), + 'WHERE' => 'a.in_message = 0 ', + 'ORDER_BY' => 'a.filetime DESC, a.post_msg_id ASC', + ); + + if (isset($this->topic_id)) + { + $sql_array['WHERE'] .= 'AND a.topic_id = ' . (int) $this->topic_id; + } + else if (isset($this->forum_id)) + { + $sql_array['LEFT_JOIN'] = array( + array( + 'FROM' => array(TOPICS_TABLE => 't'), + 'ON' => 'a.topic_id = t.topic_id', + ) + ); + $sql_array['WHERE'] .= 'AND t.forum_id = ' . (int) $this->forum_id; + } + + $sql = $this->db->sql_build_query('SELECT', $sql_array); + $result = $this->db->sql_query($sql); + + // Set attachments in feed items + while ($row = $this->db->sql_fetchrow($result)) + { + $this->attachments[$row['post_msg_id']][] = $row; + } + $this->db->sql_freeresult($result); + } + + /** + * {@inheritDoc} + */ + public function open() + { + parent::open(); + $this->fetch_attachments(); + } + + /** + * Get attachments related to a given post + * + * @param $post_id int Post id + * @return mixed Attachments related to $post_id + */ + public function get_attachments($post_id) + { + return $this->attachments[$post_id]; + } +} diff --git a/phpBB/phpbb/feed/base.php b/phpBB/phpbb/feed/base.php index 296d830932..0e3a80ebb8 100644 --- a/phpBB/phpbb/feed/base.php +++ b/phpBB/phpbb/feed/base.php @@ -7,40 +7,34 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Base class with some generic functions and settings. * * @package phpBB3 */ -abstract class phpbb_feed_base +abstract class base { /** * Feed helper object - * @var phpbb_feed_helper + * @var \phpbb\feed\helper */ protected $helper; - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_cache_driver_interface */ + /** @var \phpbb\cache\driver\driver_interface */ protected $cache; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; - /** @var phpbb_auth */ + /** @var \phpbb\auth\auth */ protected $auth; /** @var string */ @@ -74,17 +68,17 @@ abstract class phpbb_feed_base /** * Constructor * - * @param phpbb_feed_helper $helper Feed helper - * @param phpbb_config $config Config object - * @param phpbb_db_driver $db Database connection - * @param phpbb_cache_driver_interface $cache Cache object - * @param phpbb_user $user User object - * @param phpbb_auth $auth Auth object - * @param phpbb_content_visibility $content_visibility Auth object + * @param \phpbb\feed\helper $helper Feed helper + * @param \phpbb\config\config $config Config object + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\cache\driver\driver_interface $cache Cache object + * @param \phpbb\user $user User object + * @param \phpbb\auth\auth $auth Auth object + * @param \phpbb\content_visibility $content_visibility Auth object * @param string $phpEx php file extension * @return null */ - function __construct(phpbb_feed_helper $helper, phpbb_config $config, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, phpbb_user $user, phpbb_auth $auth, phpbb_content_visibility $content_visibility, $phpEx) + function __construct(\phpbb\feed\helper $helper, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\auth\auth $auth, \phpbb\content_visibility $content_visibility, $phpEx) { $this->config = $config; $this->helper = $helper; @@ -148,7 +142,7 @@ abstract class phpbb_feed_base */ function get($key) { - return (isset($this->keys[$key])) ? $this->keys[$key] : NULL; + return (isset($this->keys[$key])) ? $this->keys[$key] : null; } function get_readable_forums() diff --git a/phpBB/phpbb/feed/factory.php b/phpBB/phpbb/feed/factory.php index 63a1eb8ef0..742b279ef4 100644 --- a/phpBB/phpbb/feed/factory.php +++ b/phpBB/phpbb/feed/factory.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Factory class to return correct object * @package phpBB3 */ -class phpbb_feed_factory +class factory { /** * Service container object @@ -27,21 +21,21 @@ class phpbb_feed_factory */ protected $container; - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; /** * Constructor * * @param objec $container Container object - * @param phpbb_config $config Config object - * @param phpbb_db_driver $db Database connection + * @param \phpbb\config\config $config Config object + * @param \phpbb\db\driver\driver_interface $db Database connection * @return null */ - public function __construct($container, phpbb_config $config, phpbb_db_driver $db) + public function __construct($container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db) { $this->container = $container; $this->config = $config; diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php index b5f0dd0f8f..8e6490923d 100644 --- a/phpBB/phpbb/feed/forum.php +++ b/phpBB/phpbb/feed/forum.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Forum feed @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_forum extends phpbb_feed_post_base +class forum extends \phpbb\feed\post_base { var $forum_id = 0; var $forum_data = array(); @@ -32,9 +26,9 @@ class phpbb_feed_forum extends phpbb_feed_post_base * Set the Forum ID * * @param int $forum_id Forum ID - * @return phpbb_feed_forum + * @return \phpbb\feed\forum */ - public function set_forum_id($topic_id) + public function set_forum_id($forum_id) { $this->forum_id = (int) $forum_id; @@ -86,6 +80,8 @@ class phpbb_feed_forum extends phpbb_feed_post_base unset($forum_ids_passworded); } + + parent::open(); } function get_sql() @@ -115,7 +111,7 @@ class phpbb_feed_forum extends phpbb_feed_post_base } $this->sql = array( - 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . 'u.username, u.user_id', 'FROM' => array( POSTS_TABLE => 'p', diff --git a/phpBB/phpbb/feed/forums.php b/phpBB/phpbb/feed/forums.php index 409097a9f3..ddbb0bf7b3 100644 --- a/phpBB/phpbb/feed/forums.php +++ b/phpBB/phpbb/feed/forums.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * 'All Forums' feed @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_forums extends phpbb_feed_base +class forums extends \phpbb\feed\base { var $num_items = 0; diff --git a/phpBB/phpbb/feed/helper.php b/phpBB/phpbb/feed/helper.php index 93330aa2ad..12acf997ac 100644 --- a/phpBB/phpbb/feed/helper.php +++ b/phpBB/phpbb/feed/helper.php @@ -7,42 +7,40 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Class with some helpful functions used in feeds * @package phpBB3 */ -class phpbb_feed_helper +class helper { - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; /** @var string */ protected $phpbb_root_path; + /** @var string */ + protected $phpEx; + /** * Constructor * - * @param phpbb_config $config Config object - * @param phpbb_user $user User object + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object * @param string $phpbb_root_path Root path * @return null */ - public function __construct(phpbb_config $config, phpbb_user $user, $phpbb_root_path) + public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; + $this->phpEx = $phpEx; } /** @@ -87,8 +85,16 @@ class phpbb_feed_helper /** * Generate text content + * + * @param string $content is feed text content + * @param string $uid is bbcode_uid + * @param string $bitfield is bbcode bitfield + * @param int $options bbcode flag options + * @param int $forum_id is the forum id + * @param array $post_attachments is an array containing the attachments and their respective info + * @return string the html content to be printed for the feed */ - public function generate_content($content, $uid, $bitfield, $options) + public function generate_content($content, $uid, $bitfield, $options, $forum_id, $post_attachments) { if (empty($content)) { @@ -135,8 +141,21 @@ class phpbb_feed_helper // Remove some specials html tag, because somewhere there are a mod to allow html tags ;) $content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', ' <strong>$1</strong> ', $content); + // Parse inline images to display with the feed + if (!empty($post_attachments)) + { + $update_count = array(); + parse_attachments($forum_id, $content, $post_attachments, $update_count); + $post_attachments = implode('<br />', $post_attachments); + + // Convert attachments' relative path to absolute path + $post_attachments = str_replace($this->phpbb_root_path . 'download/file.' . $this->phpEx, $this->get_board_url() . '/download/file.' . $this->phpEx, $post_attachments); + + $content .= $post_attachments; + } + // Remove Comments from inline attachments [ia] - $content = preg_replace('#<div class="(inline-attachment|attachtitle)">(.*?)<!-- ia(.*?) -->(.*?)<!-- ia(.*?) -->(.*?)</div>#si','$4',$content); + $content = preg_replace('#<dd>(.*?)</dd>#','',$content); // Replace some entities with their unicode counterpart $entities = array( diff --git a/phpBB/phpbb/feed/news.php b/phpBB/phpbb/feed/news.php index f2d45b5165..1b7c452a92 100644 --- a/phpBB/phpbb/feed/news.php +++ b/phpBB/phpbb/feed/news.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * News feed @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_news extends phpbb_feed_topic_base +class news extends \phpbb\feed\topic_base { function get_news_forums() { @@ -91,7 +85,7 @@ class phpbb_feed_news extends phpbb_feed_topic_base $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time, - p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', diff --git a/phpBB/phpbb/feed/overall.php b/phpBB/phpbb/feed/overall.php index 224d97ec03..d99200475e 100644 --- a/phpBB/phpbb/feed/overall.php +++ b/phpBB/phpbb/feed/overall.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Board wide feed (aka overall feed) @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_overall extends phpbb_feed_post_base +class overall extends \phpbb\feed\post_base { function get_sql() { @@ -59,7 +53,7 @@ class phpbb_feed_overall extends phpbb_feed_post_base // Get the actual data $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, ' . - 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . 'u.username, u.user_id', 'FROM' => array( USERS_TABLE => 'u', diff --git a/phpBB/phpbb/feed/post_base.php b/phpBB/phpbb/feed/post_base.php index 1f4cb4b5ef..de98f446f3 100644 --- a/phpBB/phpbb/feed/post_base.php +++ b/phpBB/phpbb/feed/post_base.php @@ -7,22 +7,17 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Abstract class for post based feeds * * @package phpBB3 */ -abstract class phpbb_feed_post_base extends phpbb_feed_base +abstract class post_base extends \phpbb\feed\attachments_base { var $num_items = 'feed_limit_post'; + var $attachments = array(); function set_keys() { diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php index bb1753d823..fb49aa65cc 100644 --- a/phpBB/phpbb/feed/topic.php +++ b/phpBB/phpbb/feed/topic.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Topic feed for a specific topic @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_topic extends phpbb_feed_post_base +class topic extends \phpbb\feed\post_base { var $topic_id = 0; var $forum_id = 0; @@ -32,7 +26,7 @@ class phpbb_feed_topic extends phpbb_feed_post_base * Set the Topic ID * * @param int $topic_id Topic ID - * @return phpbb_feed_topic + * @return \phpbb\feed\topic */ public function set_topic_id($topic_id) { @@ -89,12 +83,14 @@ class phpbb_feed_topic extends phpbb_feed_post_base unset($forum_ids_passworded); } + + parent::open(); } function get_sql() { $this->sql = array( - 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . 'u.username, u.user_id', 'FROM' => array( POSTS_TABLE => 'p', diff --git a/phpBB/phpbb/feed/topic_base.php b/phpBB/phpbb/feed/topic_base.php index b104a46631..e8639a6fa6 100644 --- a/phpBB/phpbb/feed/topic_base.php +++ b/phpBB/phpbb/feed/topic_base.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Abstract class for topic based feeds * * @package phpBB3 */ -abstract class phpbb_feed_topic_base extends phpbb_feed_base +abstract class topic_base extends \phpbb\feed\attachments_base { var $num_items = 'feed_limit_topic'; diff --git a/phpBB/phpbb/feed/topics.php b/phpBB/phpbb/feed/topics.php index 31f5177773..e8b9f6de6c 100644 --- a/phpBB/phpbb/feed/topics.php +++ b/phpBB/phpbb/feed/topics.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * New Topics feed @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_topics extends phpbb_feed_topic_base +class topics extends \phpbb\feed\topic_base { function get_sql() { @@ -63,7 +57,7 @@ class phpbb_feed_topics extends phpbb_feed_topic_base $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time, - p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', diff --git a/phpBB/phpbb/feed/topics_active.php b/phpBB/phpbb/feed/topics_active.php index 249dd1d66a..809a536c2a 100644 --- a/phpBB/phpbb/feed/topics_active.php +++ b/phpBB/phpbb/feed/topics_active.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\feed; /** * Active Topics feed @@ -24,7 +18,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_feed_topics_active extends phpbb_feed_topic_base +class topics_active extends \phpbb\feed\topic_base { var $sort_days = 7; @@ -80,7 +74,7 @@ class phpbb_feed_topics_active extends phpbb_feed_topic_base 'SELECT' => 'f.forum_id, f.forum_name, t.topic_id, t.topic_title, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time, - p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', diff --git a/phpBB/phpbb/filesystem.php b/phpBB/phpbb/filesystem.php index 27cab48fb0..7878be0a5e 100644 --- a/phpBB/phpbb/filesystem.php +++ b/phpBB/phpbb/filesystem.php @@ -6,19 +6,14 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} + +namespace phpbb; /** * A class with various functions that are related to paths, files and the filesystem * @package phpBB3 */ -class phpbb_filesystem +class filesystem { /** * Eliminates useless . and .. components from specified path. diff --git a/phpBB/phpbb/groupposition/exception.php b/phpBB/phpbb/groupposition/exception.php index e4ff09c703..9b55669524 100644 --- a/phpBB/phpbb/groupposition/exception.php +++ b/phpBB/phpbb/groupposition/exception.php @@ -3,21 +3,15 @@ * * @package groupposition * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\groupposition; /** * @package groupposition */ -class phpbb_groupposition_exception extends \Exception +class exception extends \Exception { } diff --git a/phpBB/phpbb/groupposition/interface.php b/phpBB/phpbb/groupposition/groupposition_interface.php index eacc04e1a4..9785172a00 100644 --- a/phpBB/phpbb/groupposition/interface.php +++ b/phpBB/phpbb/groupposition/groupposition_interface.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\groupposition; /** * Interface to manage group positions in various places of phpbb @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -interface phpbb_groupposition_interface +interface groupposition_interface { /** * Returns the value for a given group, if the group exists. @@ -32,7 +26,7 @@ interface phpbb_groupposition_interface public function get_group_value($group_id); /** - * Get number of groups displayed + * Get number of groups displayed * * @return int value of the last item displayed */ diff --git a/phpBB/phpbb/groupposition/legend.php b/phpBB/phpbb/groupposition/legend.php index 7fddadde99..42af005622 100644 --- a/phpBB/phpbb/groupposition/legend.php +++ b/phpBB/phpbb/groupposition/legend.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\groupposition; /** * Legend group position class @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_groupposition_legend implements phpbb_groupposition_interface +class legend implements \phpbb\groupposition\groupposition_interface { /** * Group is not displayed @@ -32,23 +26,23 @@ class phpbb_groupposition_legend implements phpbb_groupposition_interface /** * Database object - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Constructor * - * @param phpbb_db_driver $db Database object - * @param phpbb_user $user User object + * @param \phpbb\db\driver\driver_interface $db Database object + * @param \phpbb\user $user User object */ - public function __construct(phpbb_db_driver $db, phpbb_user $user) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user) { $this->db = $db; $this->user = $user; @@ -71,7 +65,7 @@ class phpbb_groupposition_legend implements phpbb_groupposition_interface if ($current_value === false) { // Group not found. - throw new phpbb_groupposition_exception('NO_GROUP'); + throw new \phpbb\groupposition\exception('NO_GROUP'); } return (int) $current_value; diff --git a/phpBB/phpbb/groupposition/teampage.php b/phpBB/phpbb/groupposition/teampage.php index 7c758199e7..4f1b102720 100644 --- a/phpBB/phpbb/groupposition/teampage.php +++ b/phpBB/phpbb/groupposition/teampage.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\groupposition; /** * Teampage group position class @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_groupposition_teampage implements phpbb_groupposition_interface +class teampage implements \phpbb\groupposition\groupposition_interface { /** * Group is not displayed @@ -36,30 +30,30 @@ class phpbb_groupposition_teampage implements phpbb_groupposition_interface /** * Database object - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Cache object - * @var phpbb_cache_driver_interface + * @var \phpbb\cache\driver\driver_interface */ protected $cache; /** * Constructor * - * @param phpbb_db_driver $db Database object - * @param phpbb_user $user User object - * @param phpbb_cache_driver_interface $cache Cache object + * @param \phpbb\db\driver\driver_interface $db Database object + * @param \phpbb\user $user User object + * @param \phpbb\cache\driver\driver_interface $cache Cache object */ - public function __construct(phpbb_db_driver $db, phpbb_user $user, phpbb_cache_driver_interface $cache) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\cache\driver\driver_interface $cache) { $this->db = $db; $this->user = $user; @@ -86,7 +80,7 @@ class phpbb_groupposition_teampage implements phpbb_groupposition_interface if ($row === false) { // Group not found. - throw new phpbb_groupposition_exception('NO_GROUP'); + throw new \phpbb\groupposition\exception('NO_GROUP'); } return (int) $row['teampage_position']; @@ -113,7 +107,7 @@ class phpbb_groupposition_teampage implements phpbb_groupposition_interface if ($row === false) { // Group not found. - throw new phpbb_groupposition_exception('NO_GROUP'); + throw new \phpbb\groupposition\exception('NO_GROUP'); } return $row; @@ -137,7 +131,7 @@ class phpbb_groupposition_teampage implements phpbb_groupposition_interface if ($current_value === false) { // Group not found. - throw new phpbb_groupposition_exception('NO_GROUP'); + throw new \phpbb\groupposition\exception('NO_GROUP'); } return (int) $current_value; @@ -161,7 +155,7 @@ class phpbb_groupposition_teampage implements phpbb_groupposition_interface if ($row === false) { // Group not found. - throw new phpbb_groupposition_exception('NO_GROUP'); + throw new \phpbb\groupposition\exception('NO_GROUP'); } return $row; diff --git a/phpBB/phpbb/hook/finder.php b/phpBB/phpbb/hook/finder.php index 7b0412f733..c8f71861d9 100644 --- a/phpBB/phpbb/hook/finder.php +++ b/phpBB/phpbb/hook/finder.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\hook; /** * The hook finder locates installed hooks. * * @package phpBB3 */ -class phpbb_hook_finder +class finder { protected $phpbb_root_path; protected $cache; @@ -31,9 +25,9 @@ class phpbb_hook_finder * * @param string $phpbb_root_path Path to the phpbb root directory * @param string $php_ext php file extension - * @param phpbb_cache_driver_interface $cache A cache instance or null + * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null */ - public function __construct($phpbb_root_path, $php_ext, phpbb_cache_driver_interface $cache = null) + public function __construct($phpbb_root_path, $php_ext, \phpbb\cache\driver\driver_interface $cache = null) { $this->phpbb_root_path = $phpbb_root_path; $this->cache = $cache; diff --git a/phpBB/phpbb/json_response.php b/phpBB/phpbb/json_response.php index 5dd904da09..e17525519a 100644 --- a/phpBB/phpbb/json_response.php +++ b/phpBB/phpbb/json_response.php @@ -3,23 +3,17 @@ * * @package phpBB3 * @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * JSON class * @package phpBB3 */ -class phpbb_json_response +class json_response { /** * Send the data to the client and exit the script. diff --git a/phpBB/phpbb/lock/db.php b/phpBB/phpbb/lock/db.php index 5cc0821aa0..2b437ef899 100644 --- a/phpBB/phpbb/lock/db.php +++ b/phpBB/phpbb/lock/db.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\lock; /** * Database locking class * @package phpBB3 */ -class phpbb_lock_db +class db { /** * Name of the config variable this lock uses @@ -42,13 +36,13 @@ class phpbb_lock_db /** * The phpBB configuration - * @var phpbb_config + * @var \phpbb\config\config */ private $config; /** * A database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ private $db; @@ -59,9 +53,9 @@ class phpbb_lock_db * * @param string $config_name A config variable to be used for locking * @param array $config The phpBB configuration - * @param phpbb_db_driver $db A database connection + * @param \phpbb\db\driver\driver_interface $db A database connection */ - public function __construct($config_name, phpbb_config $config, phpbb_db_driver $db) + public function __construct($config_name, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db) { $this->config_name = $config_name; $this->config = $config; diff --git a/phpBB/phpbb/lock/flock.php b/phpBB/phpbb/lock/flock.php index 17de0847c0..94a5895440 100644 --- a/phpBB/phpbb/lock/flock.php +++ b/phpBB/phpbb/lock/flock.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\lock; /** * File locking class * @package phpBB3 */ -class phpbb_lock_flock +class flock { /** * Path to the file to which access is controlled diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 7a26858348..e4c5ce47d9 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -1,26 +1,20 @@ <?php /** * -* @package phpbb_log +* @package \phpbb\log\log * @copyright (c) 2012 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\log; /** * This class is used to add entries into the log table. * -* @package phpbb_log +* @package \phpbb\log\log */ -class phpbb_log implements phpbb_log_interface +class log implements \phpbb\log\log_interface { /** * If set, administrative user profile links will be returned and messages @@ -56,19 +50,19 @@ class phpbb_log implements phpbb_log_interface /** * Database object - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Auth object - * @var phpbb_auth + * @var \phpbb\auth\auth */ protected $auth; @@ -99,10 +93,10 @@ class phpbb_log implements phpbb_log_interface /** * Constructor * - * @param phpbb_db_driver $db Database object - * @param phpbb_user $user User object - * @param phpbb_auth $auth Auth object - * @param phpbb_dispatcher $phpbb_dispatcher Event dispatcher + * @param \phpbb\db\driver\driver_interface $db Database object + * @param \phpbb\user $user User object + * @param \phpbb\auth\auth $auth Auth object + * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher * @param string $phpbb_root_path Root path * @param string $relative_admin_path Relative admin root path * @param string $php_ext PHP Extension @@ -123,7 +117,7 @@ class phpbb_log implements phpbb_log_interface /* * IN_ADMIN is set after the session is created, * so we need to take ADMIN_START into account as well, otherwise - * it will not work for the phpbb_log object we create in common.php + * it will not work for the \phpbb\log\log object we create in common.php */ $this->set_is_admin((defined('ADMIN_START') && ADMIN_START) || (defined('IN_ADMIN') && IN_ADMIN)); $this->enable(); @@ -311,10 +305,18 @@ class phpbb_log implements phpbb_log_interface * @var array sql_ary Array with log data we insert into the * database. If sql_ary[log_type] is not set, * we won't add the entry to the database. - * @since 3.1-A1 + * @since 3.1.0-a1 */ - $vars = array('mode', 'user_id', 'log_ip', 'log_operation', 'log_time', 'additional_data', 'sql_ary'); - extract($this->dispatcher->trigger_event('core.add_log', $vars)); + $vars = array( + 'mode', + 'user_id', + 'log_ip', + 'log_operation', + 'log_time', + 'additional_data', + 'sql_ary', + ); + extract($this->dispatcher->trigger_event('core.add_log', compact($vars))); // We didn't find a log_type, so we don't save it in the database. if (!isset($sql_ary['log_type'])) @@ -409,10 +411,24 @@ class phpbb_log implements phpbb_log_interface * 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-A1 + * @since 3.1.0-a1 */ - $vars = array('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_modify_type', $vars)); + $vars = array( + '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_modify_type', compact($vars))); if ($log_type === false) { @@ -430,7 +446,7 @@ class phpbb_log implements phpbb_log_interface if ($count_logs) { $sql = 'SELECT COUNT(l.log_id) AS total_entries - FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u + FROM ' . $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 . " @@ -455,7 +471,7 @@ class phpbb_log implements phpbb_log_interface } $sql = 'SELECT l.*, u.username, u.username_clean, u.user_colour - FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u + 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 : '') . " @@ -496,7 +512,7 @@ class phpbb_log implements phpbb_log_interface 'topic_id' => (int) $row['topic_id'], 'viewforum' => ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false, - 'action' => (isset($this->user->lang[$row['log_operation']])) ? $this->user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', + 'action' => (isset($this->user->lang[$row['log_operation']])) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', ); /** @@ -505,10 +521,10 @@ class phpbb_log implements phpbb_log_interface * @event core.get_logs_modify_entry_data * @var array row Entry data from the database * @var array log_entry_data Entry's data which is returned - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('row', 'log_entry_data'); - extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', $vars)); + extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars))); $log[$i] = $log_entry_data; @@ -523,12 +539,26 @@ class phpbb_log implements phpbb_log_interface // arguments, if there are we fill out the arguments // array. It doesn't matter if we add more arguments than // placeholders. - if ((substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) > 0) + $num_args = 0; + if (!is_array($this->user->lang[$row['log_operation']])) + { + $num_args = substr_count($this->user->lang[$row['log_operation']], '%'); + } + else { - $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), '')); + foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string) + { + $num_args = max($num_args, substr_count($plural_string, '%')); + } } - $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); + if (($num_args - sizeof($log_data_ary)) > 0) + { + $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), '')); + } + + $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary); + $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments); // If within the admin panel we do not censor text out if ($this->get_is_admin()) @@ -550,6 +580,10 @@ class phpbb_log implements phpbb_log_interface $log[$i]['action'] = make_clickable($log[$i]['action']); */ } + else + { + $log[$i]['action'] = $this->user->lang($log[$i]['action']); + } $i++; } @@ -564,10 +598,10 @@ class phpbb_log implements phpbb_log_interface * get the permission data * @var array reportee_id_list Array of additional user IDs we * get the username strings for - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('log', 'topic_id_list', 'reportee_id_list'); - extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', $vars)); + extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars))); if (sizeof($topic_id_list)) { @@ -631,9 +665,23 @@ class phpbb_log implements phpbb_log_interface $operations = array(); foreach ($this->user->lang as $key => $value) { - if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value)) + if (substr($key, 0, 4) == 'LOG_') { - $operations[] = $key; + if (is_array($value)) + { + foreach ($value as $plural_value) + { + if (preg_match($keywords_pattern, $plural_value)) + { + $operations[] = $key; + break; + } + } + } + else if (preg_match($keywords_pattern, $value)) + { + $operations[] = $key; + } } } diff --git a/phpBB/phpbb/log/interface.php b/phpBB/phpbb/log/log_interface.php index 3b459c9bdf..420ba79691 100644 --- a/phpBB/phpbb/log/interface.php +++ b/phpBB/phpbb/log/log_interface.php @@ -1,26 +1,20 @@ <?php /** * -* @package phpbb_log +* @package \phpbb\log\log * @copyright (c) 2012 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\log; /** * The interface for the log-system. * -* @package phpbb_log +* @package \phpbb\log\log */ -interface phpbb_log_interface +interface log_interface { /** * This function returns the state of the log system. diff --git a/phpBB/phpbb/log/null.php b/phpBB/phpbb/log/null.php new file mode 100644 index 0000000000..77d0fbe2d7 --- /dev/null +++ b/phpBB/phpbb/log/null.php @@ -0,0 +1,72 @@ +<?php +/** +* +* @package phpbb_log +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\log; + +/** +* Null logger +* +* @package phpbb_log +*/ +class null implements log_interface +{ + /** + * {@inheritdoc} + */ + public function is_enabled($type = '') + { + return false; + } + + /** + * {@inheritdoc} + */ + public function disable($type = '') + { + } + + /** + * {@inheritdoc} + */ + public function enable($type = '') + { + } + + /** + * {@inheritdoc} + */ + public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array()) + { + return false; + } + + /** + * {@inheritdoc} + */ + public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '') + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function get_log_count() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function get_valid_offset() + { + return 0; + } +} diff --git a/phpBB/phpbb/mimetype/content_guesser.php b/phpBB/phpbb/mimetype/content_guesser.php new file mode 100644 index 0000000000..2d74582a21 --- /dev/null +++ b/phpBB/phpbb/mimetype/content_guesser.php @@ -0,0 +1,33 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\mimetype; + +/** +* @package mimetype +*/ + +class content_guesser extends guesser_base +{ + /** + * @inheritdoc + */ + public function is_supported() + { + return function_exists('mime_content_type'); + } + + /** + * @inheritdoc + */ + public function guess($file, $file_name = '') + { + return mime_content_type($file); + } +} diff --git a/phpBB/phpbb/mimetype/extension_guesser.php b/phpBB/phpbb/mimetype/extension_guesser.php new file mode 100644 index 0000000000..f6f4ae0138 --- /dev/null +++ b/phpBB/phpbb/mimetype/extension_guesser.php @@ -0,0 +1,509 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\mimetype; + +/** +* @package mimetype +*/ + +class extension_guesser extends guesser_base +{ + /** + * @var file extension map + */ + protected $extension_map = array( + '3dm' => 'x-world/x-3dmf', + '3dmf' => 'x-world/x-3dmf', + 'a' => 'application/octet-stream', + 'aab' => 'application/x-authorware-bin', + 'aam' => 'application/x-authorware-map', + 'aas' => 'application/x-authorware-seg', + 'abc' => 'text/vnd.abc', + 'acgi' => 'text/html', + 'afl' => 'video/animaflex', + 'ai' => 'application/postscript', + 'aif' => 'audio/aiff', + 'aifc' => 'audio/aiff', + 'aiff' => 'audio/aiff', + 'aim' => 'application/x-aim', + 'aip' => 'text/x-audiosoft-intra', + 'ani' => 'application/x-navi-animation', + 'aos' => 'application/x-nokia-9000-communicator-add-on-software', + 'aps' => 'application/mime', + 'arc' => 'application/octet-stream', + 'arj' => 'application/arj', + 'art' => 'image/x-jg', + 'asf' => 'video/x-ms-asf', + 'asm' => 'text/x-asm', + 'asp' => 'text/asp', + 'asx' => 'video/x-ms-asf', + 'au' => 'audio/x-au', + 'avi' => 'video/avi', + 'avs' => 'video/avs-video', + 'bcpio' => 'application/x-bcpio', + 'bin' => 'application/x-binary', + 'bm' => 'image/bmp', + 'bmp' => 'image/bmp', + 'boo' => 'application/book', + 'book' => 'application/book', + 'boz' => 'application/x-bzip2', + 'bsh' => 'application/x-bsh', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'c' => 'text/x-c', + 'c++' => 'text/x-c', + 'cat' => 'application/vnd.ms-pki.seccat', + 'cc' => 'text/plain', + 'ccad' => 'application/clariscad', + 'cco' => 'application/x-cocoa', + 'cdf' => 'application/cdf', + 'cer' => 'application/x-x509-ca-cert', + 'cha' => 'application/x-chat', + 'chat' => 'application/x-chat', + 'class' => 'application/java', + 'com' => 'application/octet-stream', + 'conf' => 'text/plain', + 'cpio' => 'application/x-cpio', + 'cpp' => 'text/x-c', + 'cpt' => 'application/x-cpt', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'csh' => 'application/x-csh', + 'css' => 'text/css', + 'cxx' => 'text/plain', + 'dcr' => 'application/x-director', + 'deepv' => 'application/x-deepv', + 'def' => 'text/plain', + 'der' => 'application/x-x509-ca-cert', + 'dif' => 'video/x-dv', + 'dir' => 'application/x-director', + 'dl' => 'video/dl', + 'doc' => 'application/msword', + 'dot' => 'application/msword', + 'dp' => 'application/commonground', + 'drw' => 'application/drafting', + 'dump' => 'application/octet-stream', + 'dv' => 'video/x-dv', + 'dvi' => 'application/x-dvi', + 'dwf' => 'model/vnd.dwf', + 'dwg' => 'image/x-dwg', + 'dxf' => 'image/x-dwg', + 'dxr' => 'application/x-director', + 'el' => 'text/x-script.elisp', + 'elc' => 'application/x-elc', + 'env' => 'application/x-envoy', + 'eps' => 'application/postscript', + 'es' => 'application/x-esrehber', + 'etx' => 'text/x-setext', + 'evy' => 'application/x-envoy', + 'exe' => 'application/octet-stream', + 'f' => 'text/x-fortran', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'fdf' => 'application/vnd.fdf', + 'fif' => 'image/fif', + 'fli' => 'video/x-fli', + 'flo' => 'image/florian', + 'flx' => 'text/vnd.fmi.flexstor', + 'fmf' => 'video/x-atomic3d-feature', + 'for' => 'text/x-fortran', + 'fpx' => 'image/vnd.fpx', + 'frl' => 'application/freeloader', + 'funk' => 'audio/make', + 'g' => 'text/plain', + 'g3' => 'image/g3fax', + 'gif' => 'image/gif', + 'gl' => 'video/x-gl', + 'gsd' => 'audio/x-gsm', + 'gsm' => 'audio/x-gsm', + 'gsp' => 'application/x-gsp', + 'gss' => 'application/x-gss', + 'gtar' => 'application/x-gtar', + 'gz' => 'application/x-gzip', + 'gzip' => 'application/x-gzip', + 'h' => 'text/x-h', + 'hdf' => 'application/x-hdf', + 'help' => 'application/x-helpfile', + 'hgl' => 'application/vnd.hp-hpgl', + 'hh' => 'text/x-h', + 'hlb' => 'text/x-script', + 'hlp' => 'application/hlp', + 'hpg' => 'application/vnd.hp-hpgl', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hqx' => 'application/x-binhex40', + 'hta' => 'application/hta', + 'htc' => 'text/x-component', + 'htm' => 'text/html', + 'html' => 'text/html', + 'htmls' => 'text/html', + 'htt' => 'text/webviewhtml', + 'htx' => 'text/html', + 'ice' => 'x-conference/x-cooltalk', + 'ico' => 'image/x-icon', + 'idc' => 'text/plain', + 'ief' => 'image/ief', + 'iefs' => 'image/ief', + 'iges' => 'application/iges', + 'igs' => 'application/iges', + 'ima' => 'application/x-ima', + 'imap' => 'application/x-httpd-imap', + 'inf' => 'application/inf', + 'ins' => 'application/x-internett-signup', + 'ip' => 'application/x-ip2', + 'isu' => 'video/x-isvideo', + 'it' => 'audio/it', + 'iv' => 'application/x-inventor', + 'ivr' => 'i-world/i-vrml', + 'ivy' => 'application/x-livescreen', + 'jam' => 'audio/x-jam', + 'jav' => 'text/plain', + 'jav' => 'text/x-java-source', + 'java' => 'text/x-java-source', + 'jcm' => 'application/x-java-commerce', + 'jfif' => 'image/jpeg', + 'jfif-tbnl' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jps' => 'image/x-jps', + 'js' => 'application/x-javascript', + 'jut' => 'image/jutvision', + 'kar' => 'audio/midi', + 'ksh' => 'text/x-script.ksh', + 'la' => 'audio/x-nspaudio', + 'lam' => 'audio/x-liveaudio', + 'latex' => 'application/x-latex', + 'lha' => 'application/x-lha', + 'lhx' => 'application/octet-stream', + 'list' => 'text/plain', + 'lma' => 'audio/x-nspaudio', + 'log' => 'text/plain', + 'lsp' => 'text/x-script.lisp', + 'lst' => 'text/plain', + 'lsx' => 'text/x-la-asf', + 'ltx' => 'application/x-latex', + 'lzh' => 'application/x-lzh', + 'lzx' => 'application/x-lzx', + 'm' => 'text/x-m', + 'm1v' => 'video/mpeg', + 'm2a' => 'audio/mpeg', + 'm2v' => 'video/mpeg', + 'm3u' => 'audio/x-mpequrl', + 'man' => 'application/x-troff-man', + 'map' => 'application/x-navimap', + 'mar' => 'text/plain', + 'mbd' => 'application/mbedlet', + 'mc$' => 'application/x-magic-cap-package-1.0', + 'mcd' => 'application/x-mathcad', + 'mcf' => 'text/mcf', + 'mcp' => 'application/netmc', + 'me' => 'application/x-troff-me', + 'mht' => 'message/rfc822', + 'mhtml' => 'message/rfc822', + 'mid' => 'audio/x-midi', + 'midi' => 'audio/x-midi', + 'mif' => 'application/x-mif', + 'mime' => 'www/mime', + 'mjf' => 'audio/x-vnd.audioexplosion.mjuicemediafile', + 'mjpg' => 'video/x-motion-jpeg', + 'mm' => 'application/x-meme', + 'mme' => 'application/base64', + 'mod' => 'audio/x-mod', + 'moov' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/x-mpeg', + 'mp3' => 'audio/x-mpeg-3', + 'mpa' => 'audio/mpeg', + 'mpc' => 'application/x-project', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpga' => 'audio/mpeg', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/x-project', + 'mpv' => 'application/x-project', + 'mpx' => 'application/x-project', + 'mrc' => 'application/marc', + 'ms' => 'application/x-troff-ms', + 'mv' => 'video/x-sgi-movie', + 'my' => 'audio/make', + 'mzz' => 'application/x-vnd.audioexplosion.mzz', + 'nap' => 'image/naplps', + 'naplps' => 'image/naplps', + 'nc' => 'application/x-netcdf', + 'ncm' => 'application/vnd.nokia.configuration-message', + 'nif' => 'image/x-niff', + 'niff' => 'image/x-niff', + 'nix' => 'application/x-mix-transfer', + 'nsc' => 'application/x-conference', + 'nvd' => 'application/x-navidoc', + 'o' => 'application/octet-stream', + 'oda' => 'application/oda', + 'omc' => 'application/x-omc', + 'omcd' => 'application/x-omcdatamaker', + 'omcr' => 'application/x-omcregerator', + 'p' => 'text/x-pascal', + 'p10' => 'application/x-pkcs10', + 'p12' => 'application/x-pkcs12', + 'p7a' => 'application/x-pkcs7-signature', + 'p7c' => 'application/x-pkcs7-mime', + 'p7m' => 'application/x-pkcs7-mime', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'part' => 'application/pro_eng', + 'pas' => 'text/pascal', + 'pbm' => 'image/x-portable-bitmap', + 'pcl' => 'application/x-pcl', + 'pct' => 'image/x-pict', + 'pcx' => 'image/x-pcx', + 'pdb' => 'chemical/x-pdb', + 'pdf' => 'application/pdf', + 'pfunk' => 'audio/make.my.funk', + 'pgm' => 'image/x-portable-greymap', + 'pic' => 'image/pict', + 'pict' => 'image/pict', + 'pkg' => 'application/x-newton-compatible-pkg', + 'pko' => 'application/vnd.ms-pki.pko', + 'pl' => 'text/x-script.perl', + 'plx' => 'application/x-pixclscript', + 'pm' => 'text/x-script.perl-module', + 'pm4' => 'application/x-pagemaker', + 'pm5' => 'application/x-pagemaker', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'pot' => 'application/mspowerpoint', + 'pov' => 'model/x-pov', + 'ppa' => 'application/vnd.ms-powerpoint', + 'ppm' => 'image/x-portable-pixmap', + 'pps' => 'application/mspowerpoint', + 'ppt' => 'application/mspowerpoint', + 'ppz' => 'application/mspowerpoint', + 'pre' => 'application/x-freelance', + 'prt' => 'application/pro_eng', + 'ps' => 'application/postscript', + 'psd' => 'application/octet-stream', + 'pvu' => 'paleovu/x-pv', + 'pwz' => 'application/vnd.ms-powerpoint', + 'py' => 'text/x-script.phyton', + 'pyc' => 'applicaiton/x-bytecode.python', + 'qcp' => 'audio/vnd.qcelp', + 'qd3' => 'x-world/x-3dmf', + 'qd3d' => 'x-world/x-3dmf', + 'qif' => 'image/x-quicktime', + 'qt' => 'video/quicktime', + 'qtc' => 'video/x-qtc', + 'qti' => 'image/x-quicktime', + 'qtif' => 'image/x-quicktime', + 'ra' => 'audio/x-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'ras' => 'image/x-cmu-raster', + 'rast' => 'image/cmu-raster', + 'rexx' => 'text/x-script.rexx', + 'rf' => 'image/vnd.rn-realflash', + 'rgb' => 'image/x-rgb', + 'rm' => 'audio/x-pn-realaudio', + 'rmi' => 'audio/mid', + 'rmm' => 'audio/x-pn-realaudio', + 'rmp' => 'audio/x-pn-realaudio', + 'rng' => 'application/vnd.nokia.ringing-tone', + 'rnx' => 'application/vnd.rn-realplayer', + 'roff' => 'application/x-troff', + 'rp' => 'image/vnd.rn-realpix', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'rt' => 'text/richtext', + 'rtf' => 'text/richtext', + 'rtx' => 'text/richtext', + 'rv' => 'video/vnd.rn-realvideo', + 's' => 'text/x-asm', + 's3m' => 'audio/s3m', + 'saveme' => 'application/octet-stream', + 'sbk' => 'application/x-tbook', + 'scm' => 'video/x-scm', + 'sdml' => 'text/plain', + 'sdp' => 'application/x-sdp', + 'sdr' => 'application/sounder', + 'sea' => 'application/x-sea', + 'set' => 'application/set', + 'sgm' => 'text/x-sgml', + 'sgml' => 'text/x-sgml', + 'sh' => 'text/x-script.sh', + 'shar' => 'application/x-shar', + 'shtml' => 'text/x-server-parsed-html', + 'sid' => 'audio/x-psid', + 'sit' => 'application/x-stuffit', + 'skd' => 'application/x-koan', + 'skm' => 'application/x-koan', + 'skp' => 'application/x-koan', + 'skt' => 'application/x-koan', + 'sl' => 'application/x-seelogo', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'snd' => 'audio/x-adpcm', + 'sol' => 'application/solids', + 'spc' => 'text/x-speech', + 'spl' => 'application/futuresplash', + 'spr' => 'application/x-sprite', + 'sprite' => 'application/x-sprite', + 'src' => 'application/x-wais-source', + 'ssi' => 'text/x-server-parsed-html', + 'ssm' => 'application/streamingmedia', + 'sst' => 'application/vnd.ms-pki.certstore', + 'step' => 'application/step', + 'stl' => 'application/vnd.ms-pki.stl', + 'stp' => 'application/step', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'svf' => 'image/x-dwg', + 'svr' => 'application/x-world', + 'swf' => 'application/x-shockwave-flash', + 't' => 'application/x-troff', + 'talk' => 'text/x-speech', + 'tar' => 'application/x-tar', + 'tbk' => 'application/x-tbook', + 'tcl' => 'text/x-script.tcl', + 'tcsh' => 'text/x-script.tcsh', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'text' => 'text/plain', + 'tgz' => 'application/x-compressed', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'tr' => 'application/x-troff', + 'tsi' => 'audio/tsp-audio', + 'tsp' => 'audio/tsplayer', + 'tsv' => 'text/tab-separated-values', + 'turbot' => 'image/florian', + 'txt' => 'text/plain', + 'uil' => 'text/x-uil', + 'uni' => 'text/uri-list', + 'unis' => 'text/uri-list', + 'unv' => 'application/i-deas', + 'uri' => 'text/uri-list', + 'uris' => 'text/uri-list', + 'ustar' => 'multipart/x-ustar', + 'uu' => 'text/x-uuencode', + 'uue' => 'text/x-uuencode', + 'vcd' => 'application/x-cdlink', + 'vcs' => 'text/x-vcalendar', + 'vda' => 'application/vda', + 'vdo' => 'video/vdo', + 'vew' => 'application/groupwise', + 'viv' => 'video/vivo', + 'vivo' => 'video/vivo', + 'vmd' => 'application/vocaltec-media-desc', + 'vmf' => 'application/vocaltec-media-file', + 'voc' => 'audio/voc', + 'vos' => 'video/vosaic', + 'vox' => 'audio/voxware', + 'vqe' => 'audio/x-twinvq-plugin', + 'vqf' => 'audio/x-twinvq', + 'vql' => 'audio/x-twinvq-plugin', + 'vrml' => 'application/x-vrml', + 'vrt' => 'x-world/x-vrt', + 'vsd' => 'application/x-visio', + 'vst' => 'application/x-visio', + 'vsw' => 'application/x-visio', + 'w60' => 'application/wordperfect6.0', + 'w61' => 'application/wordperfect6.1', + 'w6w' => 'application/msword', + 'wav' => 'audio/wav', + 'wb1' => 'application/x-qpro', + 'wbmp' => 'image/vnd.wap.wbmp', + 'web' => 'application/vnd.xara', + 'wiz' => 'application/msword', + 'wk1' => 'application/x-123', + 'wmf' => 'windows/metafile', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'word' => 'application/msword', + 'wp' => 'application/wordperfect', + 'wp5' => 'application/wordperfect', + 'wp6' => 'application/wordperfect', + 'wpd' => 'application/wordperfect', + 'wq1' => 'application/x-lotus', + 'wri' => 'application/mswrite', + 'wrl' => 'model/vrml', + 'wrz' => 'model/vrml', + 'wsc' => 'text/scriplet', + 'wsrc' => 'application/x-wais-source', + 'wtk' => 'application/x-wintalk', + 'xbm' => 'image/xbm', + 'xdr' => 'video/x-amt-demorun', + 'xgz' => 'xgl/drawing', + 'xif' => 'image/vnd.xiff', + 'xl' => 'application/excel', + 'xla' => 'application/excel', + 'xlb' => 'application/excel', + 'xlc' => 'application/excel', + 'xld' => 'application/excel', + 'xlk' => 'application/excel', + 'xll' => 'application/excel', + 'xlm' => 'application/excel', + 'xls' => 'application/excel', + 'xlt' => 'application/excel', + 'xlv' => 'application/excel', + 'xlw' => 'application/excel', + 'xm' => 'audio/xm', + 'xml' => 'text/xml', + 'xmz' => 'xgl/movie', + 'xpix' => 'application/x-vnd.ls-xpix', + 'xpm' => 'image/xpm', + 'x-png' => 'image/png', + 'xsr' => 'video/x-amt-showrun', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-pdb', + 'z' => 'application/x-compressed', + 'zip' => 'application/x-zip-compressed', + 'zoo' => 'application/octet-stream', + 'zsh' => 'text/x-script.zsh', + ); + + /** + * @inheritdoc + */ + public function is_supported() + { + return true; + } + + /** + * @inheritdoc + */ + public function guess($file, $file_name = '') + { + $file_name = (empty($file_name)) ? $file : $file_name; + return $this->map_extension_to_type($file_name); + } + + /** + * Map extension of supplied file_name to mime type + * + * @param string $file_name Path to file or filename + * + * @return string|null Mimetype if known or null if not + */ + protected function map_extension_to_type($file_name) + { + $extension = pathinfo($file_name, PATHINFO_EXTENSION); + + if (isset($this->extension_map[$extension])) + { + return $this->extension_map[$extension]; + } + else + { + return null; + } + } +} diff --git a/phpBB/phpbb/mimetype/guesser.php b/phpBB/phpbb/mimetype/guesser.php new file mode 100644 index 0000000000..3499b3b0f7 --- /dev/null +++ b/phpBB/phpbb/mimetype/guesser.php @@ -0,0 +1,130 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\mimetype; + +/** +* @package mimetype +*/ + +class guesser +{ + /** + * @const Default priority for mimetype guessers + */ + const PRIORITY_DEFAULT = 0; + + /** + * @var mimetype guessers + */ + protected $guessers; + + /** + * Construct a mimetype guesser object + * + * @param array $mimetype_guessers Mimetype guesser service collection + */ + public function __construct($mimetype_guessers) + { + $this->register_guessers($mimetype_guessers); + } + + /** + * Register MimeTypeGuessers and sort them by priority + * + * @param array $mimetype_guessers Mimetype guesser service collection + * + * @throws \LogicException If incorrect or not mimetype guessers have + * been supplied to class + */ + protected function register_guessers($mimetype_guessers) + { + foreach ($mimetype_guessers as $guesser) + { + $is_supported = (method_exists($guesser, 'is_supported')) ? 'is_supported' : ''; + $is_supported = (method_exists($guesser, 'isSupported')) ? 'isSupported' : $is_supported; + + if (empty($is_supported)) + { + throw new \LogicException('Incorrect mimetype guesser supplied.'); + } + + if ($guesser->$is_supported()) + { + $this->guessers[] = $guesser; + } + } + + if (empty($this->guessers)) + { + throw new \LogicException('No mimetype guesser supplied.'); + } + + // Sort guessers by priority + usort($this->guessers, array($this, 'sort_priority')); + } + + /** + * Sort the priority of supplied guessers + * This is a compare function for usort. A guesser with higher priority + * should be used first and vice versa. usort() orders the array values + * from low to high depending on what the comparison function returns + * to it. Return value should be smaller than 0 if value a is smaller + * than value b. This has been reversed in the comparision function in + * order to sort the guessers from high to low. + * Method has been set to public in order to allow proper testing. + * + * @param object $guesser_a Mimetype guesser a + * @param object $guesser_b Mimetype guesser b + * + * @return int If both guessers have the same priority 0, bigger + * than 0 if first guesser has lower priority, and lower + * than 0 if first guesser has higher priority + */ + public function sort_priority($guesser_a, $guesser_b) + { + $priority_a = (int) (method_exists($guesser_a, 'get_priority')) ? $guesser_a->get_priority() : self::PRIORITY_DEFAULT; + $priority_b = (int) (method_exists($guesser_b, 'get_priority')) ? $guesser_b->get_priority() : self::PRIORITY_DEFAULT; + + return $priority_b - $priority_a; + } + + /** + * Guess mimetype of supplied file + * + * @param string $file Path to file + * + * @return string Guess for mimetype of file + */ + public function guess($file, $file_name = '') + { + if (!is_file($file)) + { + return false; + } + + if (!is_readable($file)) + { + return false; + } + + foreach ($this->guessers as $guesser) + { + $mimetype = $guesser->guess($file, $file_name); + + // Try to guess something that is not the fallback application/octet-stream + if ($mimetype !== null && $mimetype !== 'application/octet-stream') + { + return $mimetype; + } + } + // Return any mimetype if we got a result or the fallback value + return (!empty($mimetype)) ? $mimetype : 'application/octet-stream'; + } +} diff --git a/phpBB/phpbb/mimetype/guesser_base.php b/phpBB/phpbb/mimetype/guesser_base.php new file mode 100644 index 0000000000..082b098028 --- /dev/null +++ b/phpBB/phpbb/mimetype/guesser_base.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\mimetype; + +/** +* @package mimetype +*/ + +abstract class guesser_base implements guesser_interface +{ + /** + * @var int Guesser Priority + */ + protected $priority; + + /** + * @inheritdoc + */ + public function get_priority() + { + return $this->priority; + } + + /** + * @inheritdoc + */ + public function set_priority($priority) + { + $this->priority = $priority; + } +} diff --git a/phpBB/phpbb/mimetype/guesser_interface.php b/phpBB/phpbb/mimetype/guesser_interface.php new file mode 100644 index 0000000000..103689765e --- /dev/null +++ b/phpBB/phpbb/mimetype/guesser_interface.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\mimetype; + +/** +* @package mimetype +*/ + +interface guesser_interface +{ + /** + * Returns whether this guesser is supported on the current OS + * + * @return bool True if guesser is supported, false if not + */ + public function is_supported(); + + /** + * Guess mimetype of supplied file + * + * @param string $file Path to file + * + * @return string Guess for mimetype of file + */ + public function guess($file, $file_name = ''); + + /** + * Get the guesser priority + * + * @return int Guesser priority + */ + public function get_priority(); + + /** + * Set the guesser priority + * + * @param int Guesser priority + * + * @return void + */ + public function set_priority($priority); +} diff --git a/phpBB/phpbb/notification/exception.php b/phpBB/phpbb/notification/exception.php index a52d6fdc57..1b4cc89fc9 100644 --- a/phpBB/phpbb/notification/exception.php +++ b/phpBB/phpbb/notification/exception.php @@ -3,24 +3,18 @@ * * @package notifications * @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification; /** * Notifications exception * * @package notifications */ -class phpbb_notification_exception extends \Exception +class exception extends \Exception { public function __toString() { diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 97833710c0..09d9677ccd 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification; /** * Notifications service class * @package notifications */ -class phpbb_notification_manager +class manager { /** @var array */ protected $notification_types; @@ -30,16 +24,19 @@ class phpbb_notification_manager /** @var ContainerBuilder */ protected $phpbb_container; - /** @var phpbb_user_loader */ + /** @var \phpbb\user_loader */ protected $user_loader; - /** @var phpbb_db_driver */ + /** @var \phpbb\config\config */ + protected $config; + + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_cache_service */ + /** @var \phpbb\cache\service */ protected $cache; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; /** @var string */ @@ -59,27 +56,29 @@ class phpbb_notification_manager /** * Notification Constructor - * + * * @param array $notification_types * @param array $notification_methods * @param ContainerBuilder $phpbb_container - * @param phpbb_user_loader $user_loader - * @param phpbb_db_driver $db - * @param phpbb_user $user + * @param \phpbb\user_loader $user_loader + * @param \phpbb\config\config $config + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\user $user * @param string $phpbb_root_path * @param string $php_ext * @param string $notification_types_table * @param string $notifications_table * @param string $user_notifications_table - * @return phpbb_notification_manager + * @return \phpbb\notification\manager */ - public function __construct($notification_types, $notification_methods, $phpbb_container, phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct($notification_types, $notification_methods, $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) { $this->notification_types = $notification_types; $this->notification_methods = $notification_methods; $this->phpbb_container = $phpbb_container; $this->user_loader = $user_loader; + $this->config = $config; $this->db = $db; $this->cache = $cache; $this->user = $user; @@ -152,7 +151,7 @@ class phpbb_notification_manager AND nt.notification_type_id = n.notification_type_id AND nt.notification_type_enabled = 1'; $result = $this->db->sql_query($sql); - $unread_count = (int) $this->db->sql_fetchfield('unread_count', $result); + $unread_count = (int) $this->db->sql_fetchfield('unread_count'); $this->db->sql_freeresult($result); } @@ -165,7 +164,7 @@ class phpbb_notification_manager AND nt.notification_type_id = n.notification_type_id AND nt.notification_type_enabled = 1'; $result = $this->db->sql_query($sql); - $total_count = (int) $this->db->sql_fetchfield('total_count', $result); + $total_count = (int) $this->db->sql_fetchfield('total_count'); $this->db->sql_freeresult($result); } @@ -260,8 +259,7 @@ class phpbb_notification_manager SET notification_read = 1 WHERE notification_time <= " . (int) $time . (($notification_type_name !== false) ? ' AND ' . - (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) - : '') . + (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) : '') . (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); $this->db->sql_query($sql); @@ -283,8 +281,7 @@ class phpbb_notification_manager SET notification_read = 1 WHERE notification_time <= " . (int) $time . (($notification_type_name !== false) ? ' AND ' . - (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) - : '') . + (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) : '') . (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id) : 'item_parent_id = ' . (int) $item_parent_id) : '') . (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : ''); $this->db->sql_query($sql); @@ -402,7 +399,7 @@ class phpbb_notification_manager $pre_create_data = $notification->pre_create_insert_array($data, $notify_users); unset($notification); - $insert_buffer = new phpbb_db_sql_insert_buffer($this->db, $this->notifications_table); + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table); // Go through each user so we can insert a row in the DB and then notify them by their desired means foreach ($notify_users as $user => $methods) @@ -490,15 +487,15 @@ class phpbb_notification_manager * * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types) * @param int|array $item_id Identifier within the type (or array of ids) - * @param array $data Data specific for this type that will be updated + * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked) */ - public function delete_notifications($notification_type_name, $item_id) + public function delete_notifications($notification_type_name, $item_id, $parent_id = false) { if (is_array($notification_type_name)) { foreach ($notification_type_name as $type) { - $this->delete_notifications($type, $item_id); + $this->delete_notifications($type, $item_id, $parent_id); } return; @@ -508,7 +505,8 @@ class phpbb_notification_manager $sql = 'DELETE FROM ' . $this->notifications_table . ' WHERE notification_type_id = ' . (int) $notification_type_id . ' - AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id); + AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) . + (($parent_id !== false) ? ' AND ' . ((is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id)) : ''); $this->db->sql_query($sql); } @@ -525,7 +523,7 @@ class phpbb_notification_manager { $type = $this->get_item_type_class($type_name); - if ($type instanceof phpbb_notification_type_interface && $type->is_available()) + if ($type instanceof \phpbb\notification\type\type_interface && $type->is_available()) { $options = array_merge(array( 'id' => $type->get_type(), @@ -561,7 +559,7 @@ class phpbb_notification_manager { $method = $this->get_method_class($method_name); - if ($method instanceof phpbb_notification_method_interface && $method->is_available()) + if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available()) { $subscription_methods[$method_name] = array( 'id' => $method->get_type(), @@ -796,12 +794,16 @@ class phpbb_notification_manager * Delete all notifications older than a certain time * * @param int $timestamp Unix timestamp to delete all notifications that were created before + * @param bool $only_unread True (default) to only prune read notifications */ - public function prune_notifications($timestamp) + public function prune_notifications($timestamp, $only_read = true) { $sql = 'DELETE FROM ' . $this->notifications_table . ' - WHERE notification_time < ' . (int) $timestamp; + WHERE notification_time < ' . (int) $timestamp . + (($only_read) ? ' AND notification_read = 1' : ''); $this->db->sql_query($sql); + + $this->config->set('read_notification_last_gc', time(), false); } /** @@ -834,12 +836,12 @@ class phpbb_notification_manager protected function load_object($object_name) { $object = $this->phpbb_container->get($object_name); - + if (method_exists($object, 'set_notification_manager')) { $object->set_notification_manager($this); } - + return $object; } @@ -873,7 +875,7 @@ class phpbb_notification_manager { if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name])) { - throw new phpbb_notification_exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name)); + throw new \phpbb\notification\exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name)); } $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array( diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php index b633956d01..2e6507d30f 100644 --- a/phpBB/phpbb/notification/method/base.php +++ b/phpBB/phpbb/notification/method/base.php @@ -7,45 +7,39 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\method; /** * Base notifications method class * @package notifications */ -abstract class phpbb_notification_method_base implements phpbb_notification_method_interface +abstract class base implements \phpbb\notification\method\method_interface { - /** @var phpbb_notification_manager */ + /** @var \phpbb\notification\manager */ protected $notification_manager; - /** @var phpbb_user_loader */ + /** @var \phpbb\user_loader */ protected $user_loader; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_cache_driver_interface */ + /** @var \phpbb\cache\driver\driver_interface */ protected $cache; - /** @var phpbb_template */ + /** @var \phpbb\template\template */ protected $template; - /** @var phpbb_extension_manager */ + /** @var \phpbb\extension\manager */ protected $extension_manager; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; - /** @var phpbb_auth */ + /** @var \phpbb\auth\auth */ protected $auth; - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; /** @var string */ @@ -64,17 +58,17 @@ abstract class phpbb_notification_method_base implements phpbb_notification_meth /** * Notification Method Base Constructor * - * @param phpbb_user_loader $user_loader - * @param phpbb_db_driver $db - * @param phpbb_cache_driver_interface $cache - * @param phpbb_user $user - * @param phpbb_auth $auth - * @param phpbb_config $config + * @param \phpbb\user_loader $user_loader + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\cache\driver\driver_interface $cache + * @param \phpbb\user $user + * @param \phpbb\auth\auth $auth + * @param \phpbb\config\config $config * @param string $phpbb_root_path * @param string $php_ext - * @return phpbb_notification_method_base + * @return \phpbb\notification\method\base */ - public function __construct(phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext) { $this->user_loader = $user_loader; $this->db = $db; @@ -89,9 +83,9 @@ abstract class phpbb_notification_method_base implements phpbb_notification_meth /** * Set notification manager (required) * - * @param phpbb_notification_manager $notification_manager + * @param \phpbb\notification\manager $notification_manager */ - public function set_notification_manager(phpbb_notification_manager $notification_manager) + public function set_notification_manager(\phpbb\notification\manager $notification_manager) { $this->notification_manager = $notification_manager; } @@ -99,9 +93,9 @@ abstract class phpbb_notification_method_base implements phpbb_notification_meth /** * Add a notification to the queue * - * @param phpbb_notification_type_interface $notification + * @param \phpbb\notification\type\type_interface $notification */ - public function add_to_queue(phpbb_notification_type_interface $notification) + public function add_to_queue(\phpbb\notification\type\type_interface $notification) { $this->queue[] = $notification; } diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index 571b0ec656..e039fae8de 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\method; /** * Email notification method class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_method_email extends phpbb_notification_method_messenger_base +class email extends \phpbb\notification\method\messenger_base { /** * Get notification method name diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index d3b756d020..bdfaf5a6fc 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\method; /** * Jabber notification method class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_method_jabber extends phpbb_notification_method_messenger_base +class jabber extends \phpbb\notification\method\messenger_base { /** * Get notification method name diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 4966aa94bc..7cb38eb59d 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\method; /** * Abstract notification method handling email and jabber notifications @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -abstract class phpbb_notification_method_messenger_base extends phpbb_notification_method_base +abstract class messenger_base extends \phpbb\notification\method\base { /** * Notify using phpBB messenger @@ -60,7 +54,7 @@ abstract class phpbb_notification_method_messenger_base extends phpbb_notificati { include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); } - $messenger = new messenger(); + $messenger = new \messenger(); $board_url = generate_board_url(); // Time to go through the queue and send emails diff --git a/phpBB/phpbb/notification/method/interface.php b/phpBB/phpbb/notification/method/method_interface.php index ef875942cc..4830d06b86 100644 --- a/phpBB/phpbb/notification/method/interface.php +++ b/phpBB/phpbb/notification/method/method_interface.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\method; /** * Base notifications method interface * @package notifications */ -interface phpbb_notification_method_interface +interface method_interface { /** * Get notification method name @@ -37,9 +31,9 @@ interface phpbb_notification_method_interface /** * Add a notification to the queue * - * @param phpbb_notification_type_interface $notification + * @param \phpbb\notification\type\type_interface $notification */ - public function add_to_queue(phpbb_notification_type_interface $notification); + public function add_to_queue(\phpbb\notification\type\type_interface $notification); /** * Parse the queue and notify the users diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php new file mode 100644 index 0000000000..62ea759a98 --- /dev/null +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -0,0 +1,166 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\notification\type; + +/** +* Admin activation notifications class +* This class handles notifications for users requiring admin activation +* +* @package notifications +*/ +class admin_activate_user extends \phpbb\notification\type\base +{ + /** + * {@inheritdoc} + */ + public function get_type() + { + return 'admin_activate_user'; + } + + /** + * {@inheritdoc} + */ + protected $language_key = 'NOTIFICATION_ADMIN_ACTIVATE_USER'; + + /** + * {@inheritdoc} + */ + public static $notification_option = array( + 'lang' => 'NOTIFICATION_TYPE_ADMIN_ACTIVATE_USER', + 'group' => 'NOTIFICATION_GROUP_ADMINISTRATION', + ); + + /** + * {@inheritdoc} + */ + public function is_available() + { + return ($this->auth->acl_get('a_user') && $this->config['require_activation'] == USER_ACTIVATION_ADMIN); + } + + /** + * {@inheritdoc} + */ + public static function get_item_id($user) + { + return (int) $user['user_id']; + } + + /** + * {@inheritdoc} + */ + public static function get_item_parent_id($post) + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function find_users_for_notification($user, $options = array()) + { + $options = array_merge(array( + 'ignore_users' => array(), + ), $options); + + // Grab admins that have permission to administer users. + $admin_ary = $this->auth->acl_get_list(false, 'a_user', false); + $users = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); + + // Grab founders + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_FOUNDER; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $users[] = (int) $row['user_id']; + } + $this->db->sql_freeresult($result); + + if (empty($users)) + { + return array(); + } + $users = array_unique($users); + + return $this->check_user_notification_options($users, $options); + } + + /** + * {@inheritdoc} + */ + public function get_avatar() + { + return $this->user_loader->get_avatar($this->item_id); + } + + /** + * {@inheritdoc} + */ + public function get_title() + { + $username = $this->user_loader->get_username($this->item_id, 'no_profile'); + + return $this->user->lang($this->language_key, $username); + } + + /** + * {@inheritdoc} + */ + public function get_email_template() + { + return 'admin_activate'; + } + + /** + * {@inheritdoc} + */ + public function get_email_template_variables() + { + $board_url = generate_board_url(); + $username = $this->user_loader->get_username($this->item_id, 'no_profile'); + + return array( + 'USERNAME' => htmlspecialchars_decode($username), + 'U_USER_DETAILS' => "{$board_url}/memberlist.{$this->php_ext}?mode=viewprofile&u={$this->item_id}", + 'U_ACTIVATE' => "{$board_url}/ucp.{$this->php_ext}?mode=activate&u={$this->item_id}&k={$this->get_data('user_actkey')}", + ); + } + + /** + * {@inheritdoc} + */ + public function get_url() + { + return $this->user_loader->get_username($this->item_id, 'profile'); + } + + /** + * {@inheritdoc} + */ + public function users_to_query() + { + return array($this->item_id); + } + + /** + * {@inheritdoc} + */ + public function create_insert_array($user, $pre_create_data) + { + $this->set_data('user_actkey', $user['user_actkey']); + $this->notification_time = $user['user_regdate']; + + return parent::create_insert_array($user, $pre_create_data); + } +} diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php index 1a30781c35..5912ad62b4 100644 --- a/phpBB/phpbb/notification/type/approve_post.php +++ b/phpBB/phpbb/notification/type/approve_post.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post approved notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_approve_post extends phpbb_notification_type_post +class approve_post extends \phpbb\notification\type\post { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_approve_post extends phpbb_notification_type_post protected $language_key = 'NOTIFICATION_POST_APPROVED'; /** + * Inherit notification read status from post. + * + * @var bool + */ + protected $inherit_read_status = false; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data @@ -137,4 +138,12 @@ class phpbb_notification_type_approve_post extends phpbb_notification_type_post { return 'post_approved'; } + + /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return $this->get_url(); + } } diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php index e728e9ac30..11a240e03d 100644 --- a/phpBB/phpbb/notification/type/approve_topic.php +++ b/phpBB/phpbb/notification/type/approve_topic.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Topic approved notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_approve_topic extends phpbb_notification_type_topic +class approve_topic extends \phpbb\notification\type\topic { /** * Get notification type name @@ -32,7 +26,7 @@ class phpbb_notification_type_approve_topic extends phpbb_notification_type_topi { return 'approve_topic'; } - + /** * Language key used to output the text * @@ -41,6 +35,13 @@ class phpbb_notification_type_approve_topic extends phpbb_notification_type_topi protected $language_key = 'NOTIFICATION_TOPIC_APPROVED'; /** + * Inherit notification read status from topic. + * + * @var bool + */ + protected $inherit_read_status = false; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 46517f1c9b..7d08521d40 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -7,42 +7,36 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Base notifications class * @package notifications */ -abstract class phpbb_notification_type_base implements phpbb_notification_type_interface +abstract class base implements \phpbb\notification\type\type_interface { - /** @var phpbb_notification_manager */ + /** @var \phpbb\notification\manager */ protected $notification_manager; - /** @var phpbb_user_loader */ + /** @var \phpbb\user_loader */ protected $user_loader; - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_cache_driver_interface */ + /** @var \phpbb\cache\driver\driver_interface */ protected $cache; - /** @var phpbb_template */ + /** @var \phpbb\template\template */ protected $template; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; - /** @var phpbb_auth */ + /** @var \phpbb\auth\auth */ protected $auth; - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $config; /** @var string */ @@ -93,21 +87,21 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Notification Type Base Constructor - * - * @param phpbb_user_loader $user_loader - * @param phpbb_db_driver $db - * @param phpbb_cache_driver_interface $cache - * @param phpbb_user $user - * @param phpbb_auth $auth - * @param phpbb_config $config + * + * @param \phpbb\user_loader $user_loader + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\cache\driver\driver_interface $cache + * @param \phpbb\user $user + * @param \phpbb\auth\auth $auth + * @param \phpbb\config\config $config * @param string $phpbb_root_path * @param string $php_ext * @param string $notification_types_table * @param string $notifications_table * @param string $user_notifications_table - * @return phpbb_notification_type_base + * @return \phpbb\notification\type\base */ - public function __construct(phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) { $this->user_loader = $user_loader; $this->db = $db; @@ -126,10 +120,10 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Set notification manager (required) - * - * @param phpbb_notification_manager $notification_manager + * + * @param \phpbb\notification\manager $notification_manager */ - public function set_notification_manager(phpbb_notification_manager $notification_manager) + public function set_notification_manager(\phpbb\notification\manager $notification_manager) { $this->notification_manager = $notification_manager; @@ -150,7 +144,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Magic method to get data from this notification - * + * * @param mixed $name * @return mixed */ @@ -162,7 +156,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Magic method to set data on this notification - * + * * @param mixed $name * @return null */ @@ -174,9 +168,9 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Magic method to get a string of this notification - * + * * Primarily for testing - * + * * @param string $name * @return mixed */ @@ -282,21 +276,31 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i } /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return $this->get_url(); + } + + /** * Prepare to output the notification to the template - * + * * @return array Template variables */ public function prepare_for_display() { + $mark_hash = generate_link_hash('mark_notification_read'); + if ($this->get_url()) { - $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id); + $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&hash=' . $mark_hash); } else { $redirect = (($this->user->page['page_dir']) ? $this->user->page['page_dir'] . '/' : '') . $this->user->page['page_name'] . (($this->user->page['query_string']) ? '?' . $this->user->page['query_string'] : ''); - $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&redirect=' . urlencode($redirect)); + $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&hash=' . $mark_hash . '&redirect=' . urlencode($redirect)); } return array( @@ -331,7 +335,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Get the user's avatar (fall back) - * + * * @return string */ public function get_avatar() @@ -341,7 +345,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Get the special items to load (fall back) - * + * * @return array */ public function get_load_special() @@ -359,7 +363,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Is available (fall back) - * + * * @return bool */ public function is_available() @@ -369,7 +373,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i /** * Pre create insert array function (fall back) - * + * * @return array */ public function pre_create_insert_array($type_data, $notify_users) diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php index ae2e75d3eb..c981695f74 100644 --- a/phpBB/phpbb/notification/type/bookmark.php +++ b/phpBB/phpbb/notification/type/bookmark.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Bookmark updating notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_bookmark extends phpbb_notification_type_post +class bookmark extends \phpbb\notification\type\post { /** * Get notification type name @@ -81,7 +75,7 @@ class phpbb_notification_type_bookmark extends phpbb_notification_type_post $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $users[] = $row['user_id']; + $users[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); @@ -116,10 +110,14 @@ class phpbb_notification_type_bookmark extends phpbb_notification_type_post unset($notify_users[$row['user_id']]); $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row); - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . ' - WHERE notification_id = ' . $row['notification_id']; - $this->db->sql_query($sql); + $update_responders = $notification->add_responders($post); + if (!empty($update_responders)) + { + $sql = 'UPDATE ' . $this->notifications_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . ' + WHERE notification_id = ' . $row['notification_id']; + $this->db->sql_query($sql); + } } $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php index 951c7e0254..70de2a3e10 100644 --- a/phpBB/phpbb/notification/type/disapprove_post.php +++ b/phpBB/phpbb/notification/type/disapprove_post.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post disapproved notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_disapprove_post extends phpbb_notification_type_approve_post +class disapprove_post extends \phpbb\notification\type\approve_post { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_disapprove_post extends phpbb_notification_type_ap protected $language_key = 'NOTIFICATION_POST_DISAPPROVED'; /** + * Inherit notification read status from post. + * + * @var bool + */ + protected $inherit_read_status = false; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php index 038e528797..d39201d928 100644 --- a/phpBB/phpbb/notification/type/disapprove_topic.php +++ b/phpBB/phpbb/notification/type/disapprove_topic.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Topic disapproved notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_disapprove_topic extends phpbb_notification_type_approve_topic +class disapprove_topic extends \phpbb\notification\type\approve_topic { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_disapprove_topic extends phpbb_notification_type_a protected $language_key = 'NOTIFICATION_TOPIC_DISAPPROVED'; /** + * Inherit notification read status from topic. + * + * @var bool + */ + protected $inherit_read_status = false; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php new file mode 100644 index 0000000000..e0527fe220 --- /dev/null +++ b/phpBB/phpbb/notification/type/group_request.php @@ -0,0 +1,157 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\notification\type; + +class group_request extends \phpbb\notification\type\base +{ + /** + * {@inheritdoc} + */ + public function get_type() + { + return 'group_request'; + } + + /** + * {@inheritdoc} + */ + public static $notification_option = array( + 'lang' => 'NOTIFICATION_TYPE_GROUP_REQUEST', + ); + + /** + * {@inheritdoc} + */ + public function is_available() + { + // Leader of any groups? + $sql = 'SELECT group_id + FROM ' . USER_GROUP_TABLE . ' + WHERE user_id = ' . (int) $this->user->data['user_id'] . ' + AND group_leader = 1'; + $result = $this->db->sql_query_limit($sql, 1); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + return (!empty($row)) ? true : false; + } + + /** + * {@inheritdoc} + */ + public static function get_item_id($group) + { + return (int) $group['user_id']; + } + + /** + * {@inheritdoc} + */ + public static function get_item_parent_id($group) + { + // Group id is the parent + return (int) $group['group_id']; + } + + /** + * {@inheritdoc} + */ + public function find_users_for_notification($group, $options = array()) + { + $options = array_merge(array( + 'ignore_users' => array(), + ), $options); + + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . ' + WHERE group_leader = 1 + AND group_id = ' . (int) $group['group_id']; + $result = $this->db->sql_query($sql); + + $user_ids = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $user_ids[] = (int) $row['user_id']; + } + $this->db->sql_freeresult($result); + + $this->user_loader->load_users($user_ids); + + return $this->check_user_notification_options($user_ids, $options); + } + + /** + * {@inheritdoc} + */ + public function get_avatar() + { + return $this->user_loader->get_avatar($this->item_id); + } + + /** + * {@inheritdoc} + */ + public function get_title() + { + $username = $this->user_loader->get_username($this->item_id, 'no_profile'); + + return $this->user->lang('NOTIFICATION_GROUP_REQUEST', $username, $this->get_data('group_name')); + } + + /** + * {@inheritdoc} + */ + public function get_email_template() + { + return 'group_request'; + } + + /** + * {@inheritdoc} + */ + public function get_email_template_variables() + { + $user_data = $this->user_loader->get_user($this->item_id); + + return array( + 'GROUP_NAME' => htmlspecialchars_decode($this->get_data('group_name')), + 'REQUEST_USERNAME' => htmlspecialchars_decode($user_data['username']), + + 'U_PENDING' => generate_board_url() . "/ucp.{$this->php_ext}?i=groups&mode=manage&action=list&g={$this->item_parent_id}", + 'U_GROUP' => generate_board_url() . "/memberlist.{$this->php_ext}?mode=group&g={$this->item_parent_id}", + ); + } + + /** + * {@inheritdoc} + */ + public function get_url() + { + return append_sid($this->phpbb_root_path . 'ucp.' . $this->php_ext, "i=groups&mode=manage&action=list&g={$this->item_parent_id}"); + } + + /** + * {@inheritdoc} + */ + public function users_to_query() + { + return array($this->item_id); + } + + /** + * {@inheritdoc} + */ + public function create_insert_array($group, $pre_create_data = array()) + { + $this->set_data('group_name', $group['group_name']); + + return parent::create_insert_array($group, $pre_create_data); + } +} diff --git a/phpBB/phpbb/notification/type/group_request_approved.php b/phpBB/phpbb/notification/type/group_request_approved.php new file mode 100644 index 0000000000..448f049412 --- /dev/null +++ b/phpBB/phpbb/notification/type/group_request_approved.php @@ -0,0 +1,112 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\notification\type; + +class group_request_approved extends \phpbb\notification\type\base +{ + /** + * {@inheritdoc} + */ + public function get_type() + { + return 'group_request_approved'; + } + + /** + * {@inheritdoc} + */ + public function is_available() + { + return false; + } + + /** + * {@inheritdoc} + */ + public static function get_item_id($group) + { + return (int) $group['group_id']; + } + + /** + * {@inheritdoc} + */ + public static function get_item_parent_id($group) + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function find_users_for_notification($group, $options = array()) + { + $users = array(); + + $group['user_ids'] = (!is_array($group['user_ids'])) ? array($group['user_ids']) : $group['user_ids']; + + foreach ($group['user_ids'] as $user_id) + { + $users[$user_id] = array(''); + } + + return $users; + } + + /** + * {@inheritdoc} + */ + public function get_title() + { + return $this->user->lang('NOTIFICATION_GROUP_REQUEST_APPROVED', $this->get_data('group_name')); + } + + /** + * {@inheritdoc} + */ + public function get_url() + { + return append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, "mode=group&g={$this->item_id}"); + } + + /** + * {@inheritdoc} + */ + public function create_insert_array($group, $pre_create_data = array()) + { + $this->set_data('group_name', $group['group_name']); + + return parent::create_insert_array($group, $pre_create_data); + } + + /** + * {@inheritdoc} + */ + public function users_to_query() + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function get_email_template() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function get_email_template_variables() + { + return array(); + } +} diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index b3db7ad5ad..584a30efa6 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Private message notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_pm extends phpbb_notification_type_base +class pm extends \phpbb\notification\type\base { /** * Get notification type name diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index 9207fd866e..93fbcbde22 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_post extends phpbb_notification_type_base +class post extends \phpbb\notification\type\base { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_post extends phpbb_notification_type_base protected $language_key = 'NOTIFICATION_POST'; /** + * Inherit notification read status from post. + * + * @var bool + */ + protected $inherit_read_status = true; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data @@ -102,7 +103,7 @@ class phpbb_notification_type_post extends phpbb_notification_type_base $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $users[] = $row['user_id']; + $users[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); @@ -114,7 +115,7 @@ class phpbb_notification_type_post extends phpbb_notification_type_base $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $users[] = $row['user_id']; + $users[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); @@ -151,10 +152,14 @@ class phpbb_notification_type_post extends phpbb_notification_type_base unset($notify_users[$row['user_id']]); $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row); - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . ' - WHERE notification_id = ' . $row['notification_id']; - $this->db->sql_query($sql); + $update_responders = $notification->add_responders($post); + if (!empty($update_responders)) + { + $sql = 'UPDATE ' . $this->notifications_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . ' + WHERE notification_id = ' . $row['notification_id']; + $this->db->sql_query($sql); + } } $this->db->sql_freeresult($result); @@ -189,6 +194,10 @@ class phpbb_notification_type_post extends phpbb_notification_type_base 'username' => $this->get_data('post_username'), )), $responders); + $responders_cnt = sizeof($responders); + $responders = $this->trim_user_ary($responders); + $trimmed_responders_cnt = $responders_cnt - sizeof($responders); + foreach ($responders as $responder) { if ($responder['username']) @@ -201,10 +210,20 @@ class phpbb_notification_type_post extends phpbb_notification_type_base } } + if ($trimmed_responders_cnt > 20) + { + $usernames[] = $this->user->lang('NOTIFICATION_MANY_OTHERS'); + } + else if ($trimmed_responders_cnt) + { + $usernames[] = $this->user->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt); + } + return $this->user->lang( $this->language_key, - implode(', ', $usernames), - censor_text($this->get_data('topic_title')) + phpbb_generate_string_list($usernames, $this->user), + censor_text($this->get_data('topic_title')), + $responders_cnt ); } @@ -240,7 +259,7 @@ class phpbb_notification_type_post extends phpbb_notification_type_base 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))), 'U_VIEW_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}", - 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&view=unread#unread", + 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&e=1&view=unread#unread", 'U_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}", 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}", 'U_FORUM' => generate_board_url() . "/viewforum.{$this->php_ext}?f={$this->get_data('forum_id')}", @@ -259,6 +278,14 @@ class phpbb_notification_type_post extends phpbb_notification_type_base } /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "t={$this->item_parent_id}&view=unread#unread"); + } + + /** * Users needed to query before this notification can be displayed * * @return array Array of user_ids @@ -278,6 +305,22 @@ class phpbb_notification_type_post extends phpbb_notification_type_base } } + return $this->trim_user_ary($users); + } + + /** + * Trim the user array passed down to 3 users if the array contains + * more than 4 users. + * + * @param array $users Array of users + * @return array Trimmed array of user_ids + */ + public function trim_user_ary($users) + { + if (sizeof($users) > 4) + { + array_splice($users, 3); + } return $users; } @@ -294,7 +337,7 @@ class phpbb_notification_type_post extends phpbb_notification_type_base */ public function pre_create_insert_array($post, $notify_users) { - if (!sizeof($notify_users)) + if (!sizeof($notify_users) || !$this->inherit_read_status) { return array(); } @@ -339,7 +382,7 @@ class phpbb_notification_type_post extends phpbb_notification_type_base // Topics can be "read" before they are public (while awaiting approval). // Make sure that if the user has read the topic, it's marked as read in the notification - if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time) + if ($this->inherit_read_status && isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time) { $this->notification_read = true; } @@ -357,19 +400,27 @@ class phpbb_notification_type_post extends phpbb_notification_type_base // Do not add them as a responder if they were the original poster that created the notification if ($this->get_data('poster_id') == $post['poster_id']) { - return array('notification_data' => serialize($this->get_data(false))); + return array(); } $responders = $this->get_data('responders'); $responders = ($responders === null) ? array() : $responders; + // Do not add more than 25 responders, + // we trim the username list to "a, b, c and x others" anyway + // so there is no use to add all of them anyway. + if (sizeof($responders) > 25) + { + return array(); + } + foreach ($responders as $responder) { // Do not add them as a responder multiple times if ($responder['poster_id'] == $post['poster_id']) { - return array('notification_data' => serialize($this->get_data(false))); + return array(); } } @@ -380,6 +431,15 @@ class phpbb_notification_type_post extends phpbb_notification_type_base $this->set_data('responders', $responders); - return array('notification_data' => serialize($this->get_data(false))); + $serialized_data = serialize($this->get_data(false)); + + // If the data is longer then 4000 characters, it would cause a SQL error. + // We don't add the username to the list if this is the case. + if (utf8_strlen($serialized_data) >= 4000) + { + return array(); + } + + return array('notification_data' => $serialized_data); } } diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php index bc4b15cdc3..56dfcce588 100644 --- a/phpBB/phpbb/notification/type/post_in_queue.php +++ b/phpBB/phpbb/notification/type/post_in_queue.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post in queue notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post +class post_in_queue extends \phpbb\notification\type\post { /** * Get notification type name @@ -125,6 +119,14 @@ class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post } /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return parent::get_url(); + } + + /** * Function for preparing the data for insertion in an SQL query * (The service handles insertion) * diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php index 0ed13f36fb..f4b4d763eb 100644 --- a/phpBB/phpbb/notification/type/quote.php +++ b/phpBB/phpbb/notification/type/quote.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post quoting notifications class -* This class handles notifications for quoting users in a post +* This class handles notifying users when they have been quoted in a post * * @package notifications */ -class phpbb_notification_type_quote extends phpbb_notification_type_post +class quote extends \phpbb\notification\type\post { /** * Get notification type name @@ -100,7 +94,7 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $users[] = $row['user_id']; + $users[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); @@ -119,29 +113,6 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post $notify_users = $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], $options); - // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications - $update_notifications = array(); - $sql = 'SELECT n.* - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.notification_type_id = ' . (int) $this->notification_type_id . ' - AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . ' - AND n.notification_read = 0 - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Do not create a new notification - unset($notify_users[$row['user_id']]); - - $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row); - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . ' - WHERE notification_id = ' . $row['notification_id']; - $this->db->sql_query($sql); - } - $this->db->sql_freeresult($result); - return $notify_users; } @@ -197,6 +168,14 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post } /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return $this->get_url(); + } + + /** * Get email template * * @return string|bool diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index 3fa73bab41..55f6bf946d 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** -* Private message reproted notifications class +* Private message reported notifications class * This class handles notifications for private messages when they are reported * * @package notifications */ -class phpbb_notification_type_report_pm extends phpbb_notification_type_pm +class report_pm extends \phpbb\notification\type\pm { /** * Get notification type name diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php index 63dfa92064..56485f5d37 100644 --- a/phpBB/phpbb/notification/type/report_pm_closed.php +++ b/phpBB/phpbb/notification/type/report_pm_closed.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * PM report closed notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_report_pm_closed extends phpbb_notification_type_pm +class report_pm_closed extends \phpbb\notification\type\pm { /** * Get notification type name @@ -120,7 +114,7 @@ class phpbb_notification_type_report_pm_closed extends phpbb_notification_type_p */ public function get_avatar() { - return $this->get_user_avatar($this->get_data('closer_id')); + return $this->user_loader->get_avatar($this->get_data('closer_id')); } /** diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php index de5c54a291..9bf035b91e 100644 --- a/phpBB/phpbb/notification/type/report_post.php +++ b/phpBB/phpbb/notification/type/report_post.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Reported post notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_report_post extends phpbb_notification_type_post_in_queue +class report_post extends \phpbb\notification\type\post_in_queue { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_report_post extends phpbb_notification_type_post_i protected $language_key = 'NOTIFICATION_REPORT_POST'; /** + * Inherit notification read status from post. + * + * @var bool + */ + protected $inherit_read_status = false; + + /** * Permission to check for (in find_users_for_notification) * * @var string Permission name diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php index 3916cd8db7..fff45612b3 100644 --- a/phpBB/phpbb/notification/type/report_post_closed.php +++ b/phpBB/phpbb/notification/type/report_post_closed.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Post report closed notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_report_post_closed extends phpbb_notification_type_post +class report_post_closed extends \phpbb\notification\type\post { /** * Get notification type name @@ -47,6 +41,13 @@ class phpbb_notification_type_report_post_closed extends phpbb_notification_type */ protected $language_key = 'NOTIFICATION_REPORT_CLOSED'; + /** + * Inherit notification read status from post. + * + * @var bool + */ + protected $inherit_read_status = false; + public function is_available() { return false; diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 22436d3fb1..635d05bccd 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Topic notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_topic extends phpbb_notification_type_base +class topic extends \phpbb\notification\type\base { /** * Get notification type name @@ -41,6 +35,13 @@ class phpbb_notification_type_topic extends phpbb_notification_type_base protected $language_key = 'NOTIFICATION_TOPIC'; /** + * Inherit notification read status from topic. + * + * @var bool + */ + protected $inherit_read_status = true; + + /** * Notification option data (for outputting to the user) * * @var bool|array False if the service should use it's default data @@ -102,7 +103,7 @@ class phpbb_notification_type_topic extends phpbb_notification_type_base $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $users[] = $row['user_id']; + $users[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); @@ -226,7 +227,7 @@ class phpbb_notification_type_topic extends phpbb_notification_type_base */ public function pre_create_insert_array($post, $notify_users) { - if (!sizeof($notify_users)) + if (!sizeof($notify_users) || !$this->inherit_read_status) { return array(); } @@ -267,7 +268,7 @@ class phpbb_notification_type_topic extends phpbb_notification_type_base // Topics can be "read" before they are public (while awaiting approval). // Make sure that if the user has read the topic, it's marked as read in the notification - if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time) + if ($this->inherit_read_status && isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time) { $this->notification_read = true; } diff --git a/phpBB/phpbb/notification/type/topic_in_queue.php b/phpBB/phpbb/notification/type/topic_in_queue.php index f735e10c00..c8c1b5b7e2 100644 --- a/phpBB/phpbb/notification/type/topic_in_queue.php +++ b/phpBB/phpbb/notification/type/topic_in_queue.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Topic in queue notifications class @@ -21,7 +15,7 @@ if (!defined('IN_PHPBB')) * * @package notifications */ -class phpbb_notification_type_topic_in_queue extends phpbb_notification_type_topic +class topic_in_queue extends \phpbb\notification\type\topic { /** * Get notification type name diff --git a/phpBB/phpbb/notification/type/interface.php b/phpBB/phpbb/notification/type/type_interface.php index a40fdafd09..2f465aae2b 100644 --- a/phpBB/phpbb/notification/type/interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\notification\type; /** * Base notifications interface * @package notifications */ -interface phpbb_notification_type_interface +interface type_interface { /** * Get notification type name @@ -27,7 +21,7 @@ interface phpbb_notification_type_interface * @return string */ public function get_type(); - + /** * Set initial data from the database * @@ -105,6 +99,13 @@ interface phpbb_notification_type_interface public function get_url(); /** + * Get the url to redirect after the item has been marked as read + * + * @return string URL + */ + public function get_redirect_url(); + + /** * URL to unsubscribe to this notification * * @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item diff --git a/phpBB/phpbb/pagination.php b/phpBB/phpbb/pagination.php new file mode 100644 index 0000000000..6a7631c89d --- /dev/null +++ b/phpBB/phpbb/pagination.php @@ -0,0 +1,315 @@ +<?php +/** +* +* @package phpbb +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb; + +class pagination +{ + /** @var \phpbb\template\template */ + protected $template; + + /** @var \phpbb\user */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\template\template $template + * @param \phpbb\user $user + * @param \phpbb\controller\helper $helper + */ + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\controller\helper $helper) + { + $this->template = $template; + $this->user = $user; + $this->helper = $helper; + } + + /** + * Generate a pagination link based on the url and the page information + * + * @param string $base_url is url prepended to all links generated within the function + * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) + * for the page. Also be sure to specify the pagination path information into the start_name argument + * @param string $on_page is the page for which we want to generate the link + * @param string $start_name is the name of the parameter containing the first item of the given page (example: start=20) + * If you use page numbers inside your controller route, start name should be the string + * that should be removed for the first page (example: /page/%d) + * @param int $per_page the number of items, posts, etc. to display per page, used to determine the number of pages to produce + * @return URL for the requested page + */ + protected function generate_page_link($base_url, $on_page, $start_name, $per_page) + { + if (!is_string($base_url)) + { + if (is_array($base_url['routes'])) + { + $route = ($on_page > 1) ? $base_url['routes'][1] : $base_url['routes'][0]; + } + else + { + $route = $base_url['routes']; + } + $params = (isset($base_url['params'])) ? $base_url['params'] : array(); + $is_amp = (isset($base_url['is_amp'])) ? $base_url['is_amp'] : true; + $session_id = (isset($base_url['session_id'])) ? $base_url['session_id'] : false; + + if ($on_page > 1 || !is_array($base_url['routes'])) + { + $params[$start_name] = (int) $on_page; + } + + return $this->helper->route($route, $params, $is_amp, $session_id); + } + else + { + $url_delim = (strpos($base_url, '?') === false) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&'); + return ($on_page > 1) ? $base_url . $url_delim . $start_name . '=' . (($on_page - 1) * $per_page) : $base_url; + } + } + + /** + * Generate template rendered pagination + * Allows full control of rendering of pagination with the template + * + * @param string $base_url is url prepended to all links generated within the function + * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) + * for the page. Also be sure to specify the pagination path information into the start_name argument + * @param string $block_var_name is the name assigned to the pagination data block within the template (example: <!-- BEGIN pagination -->) + * @param string $start_name is the name of the parameter containing the first item of the given page (example: start=20) + * If you use page numbers inside your controller route, start name should be the string + * that should be removed for the first page (example: /page/%d) + * @param int $num_items the total number of items, posts, etc., used to determine the number of pages to produce + * @param int $per_page the number of items, posts, etc. to display per page, used to determine the number of pages to produce + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @param bool $reverse_count determines whether we weight display of the list towards the start (false) or end (true) of the list + * @param bool $ignore_on_page decides whether we enable an active (unlinked) item, used primarily for embedded lists + * @return null + */ + public function generate_template_pagination($base_url, $block_var_name, $start_name, $num_items, $per_page, $start = 1, $reverse_count = false, $ignore_on_page = false) + { + $total_pages = ceil($num_items / $per_page); + $on_page = $this->get_on_page($per_page, $start); + $u_previous_page = $u_next_page = ''; + + if ($total_pages > 1) + { + if ($reverse_count) + { + $start_page = ($total_pages > 5) ? $total_pages - 4 : 1; + $end_page = $total_pages; + } + else + { + // What we're doing here is calculating what the "start" and "end" pages should be. We + // do this by assuming pagination is "centered" around the currently active page with + // the three previous and three next page links displayed. Anything more than that and + // we display the ellipsis, likewise anything less. + // + // $start_page is the page at which we start creating the list. When we have five or less + // pages we start at page 1 since there will be no ellipsis displayed. Anymore than that + // and we calculate the start based on the active page. This is the min/max calculation. + // First (max) would we end up starting on a page less than 1? Next (min) would we end + // up starting so close to the end that we'd not display our minimum number of pages. + // + // $end_page is the last page in the list to display. Like $start_page we use a min/max to + // determine this number. Again at most five pages? Then just display them all. More than + // five and we first (min) determine whether we'd end up listing more pages than exist. + // We then (max) ensure we're displaying the minimum number of pages. + $start_page = ($total_pages > 5) ? min(max(1, $on_page - 3), $total_pages - 4) : 1; + $end_page = ($total_pages > 5) ? max(min($total_pages, $on_page + 3), 5) : $total_pages; + } + + if ($on_page != 1) + { + $u_previous_page = $this->generate_page_link($base_url, $on_page - 1, $start_name, $per_page); + + $this->template->assign_block_vars($block_var_name, array( + 'PAGE_NUMBER' => '', + 'PAGE_URL' => $u_previous_page, + 'S_IS_CURRENT' => false, + 'S_IS_PREV' => true, + 'S_IS_NEXT' => false, + 'S_IS_ELLIPSIS' => false, + )); + } + + // This do...while exists purely to negate the need for start and end assign_block_vars, i.e. + // to display the first and last page in the list plus any ellipsis. We use this loop to jump + // around a little within the list depending on where we're starting (and ending). + $at_page = 1; + do + { + // We decide whether to display the ellipsis during the loop. The ellipsis is always + // displayed as either the second or penultimate item in the list. So are we at either + // of those points and of course do we even need to display it, i.e. is the list starting + // on at least page 3 and ending three pages before the final item. + $this->template->assign_block_vars($block_var_name, array( + 'PAGE_NUMBER' => $at_page, + 'PAGE_URL' => $this->generate_page_link($base_url, $at_page, $start_name, $per_page), + 'S_IS_CURRENT' => (!$ignore_on_page && $at_page == $on_page), + 'S_IS_NEXT' => false, + 'S_IS_PREV' => false, + 'S_IS_ELLIPSIS' => ($at_page == 2 && $start_page > 2) || ($at_page == $total_pages - 1 && $end_page < $total_pages - 1), + )); + + // We may need to jump around in the list depending on whether we have or need to display + // the ellipsis. Are we on page 2 and are we more than one page away from the start + // of the list? Yes? Then we jump to the start of the list. Likewise are we at the end of + // the list and are there more than two pages left in total? Yes? Then jump to the penultimate + // page (so we can display the ellipsis next pass). Else, increment the counter and keep + // going + if ($at_page == 2 && $at_page < $start_page - 1) + { + $at_page = $start_page; + } + else if ($at_page == $end_page && $end_page < $total_pages - 1) + { + $at_page = $total_pages - 1; + } + else + { + $at_page++; + } + } + while ($at_page <= $total_pages); + + if ($on_page != $total_pages) + { + $u_next_page = $this->generate_page_link($base_url, $on_page + 1, $start_name, $per_page); + + $this->template->assign_block_vars($block_var_name, array( + 'PAGE_NUMBER' => '', + 'PAGE_URL' => $u_next_page, + 'S_IS_CURRENT' => false, + 'S_IS_PREV' => false, + 'S_IS_NEXT' => true, + 'S_IS_ELLIPSIS' => false, + )); + } + } + + // If the block_var_name is a nested block, we will use the last (most + // inner) block as a prefix for the template variables. If the last block + // name is pagination, the prefix is empty. If the rest of the + // block_var_name is not empty, we will modify the last row of that block + // and add our pagination items. + $tpl_block_name = $tpl_prefix = ''; + if (strrpos($block_var_name, '.') !== false) + { + $tpl_block_name = substr($block_var_name, 0, strrpos($block_var_name, '.')); + $tpl_prefix = strtoupper(substr($block_var_name, strrpos($block_var_name, '.') + 1)); + } + else + { + $tpl_prefix = strtoupper($block_var_name); + } + $tpl_prefix = ($tpl_prefix == 'PAGINATION') ? '' : $tpl_prefix . '_'; + + $template_array = array( + $tpl_prefix . 'BASE_URL' => is_string($base_url) ? $base_url : '',//@todo: Fix this for routes + $tpl_prefix . 'START_NAME' => $start_name, + $tpl_prefix . 'PER_PAGE' => $per_page, + 'U_' . $tpl_prefix . 'PREVIOUS_PAGE' => ($on_page != 1) ? $u_previous_page : '', + 'U_' . $tpl_prefix . 'NEXT_PAGE' => ($on_page != $total_pages) ? $u_next_page : '', + $tpl_prefix . 'TOTAL_PAGES' => $total_pages, + $tpl_prefix . 'CURRENT_PAGE' => $on_page, + $tpl_prefix . 'PAGE_NUMBER' => $this->on_page($num_items, $per_page, $start), + ); + + if ($tpl_block_name) + { + $this->template->alter_block_array($tpl_block_name, $template_array, true, 'change'); + } + else + { + $this->template->assign_vars($template_array); + } + } + + /** + * Get current page number + * + * @param int $per_page the number of items, posts, etc. per page + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @return int Current page number + */ + public function get_on_page($per_page, $start) + { + return floor($start / $per_page) + 1; + } + + /** + * Return current page + * + * @param int $num_items the total number of items, posts, topics, etc. + * @param int $per_page the number of items, posts, etc. per page + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @return string Descriptive pagination string (e.g. "page 1 of 10") + */ + public function on_page($num_items, $per_page, $start) + { + $on_page = $this->get_on_page($per_page, $start); + return $this->user->lang('PAGE_OF', $on_page, max(ceil($num_items / $per_page), 1)); + } + + /** + * Get current page number + * + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @param int $per_page the number of items, posts, etc. per page + * @param int $num_items the total number of items, posts, topics, etc. + * @return int Current page number + */ + public function validate_start($start, $per_page, $num_items) + { + if ($start < 0 || $start >= $num_items) + { + return ($start < 0 || $num_items <= 0) ? 0 : floor(($num_items - 1) / $per_page) * $per_page; + } + + return $start; + } + + /** + * Get new start when searching from the end + * + * If the user is trying to reach late pages, start searching from the end. + * + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @param int $limit the number of items, posts, etc. to display + * @param int $num_items the total number of items, posts, topics, etc. + * @return int Current page number + */ + public function reverse_start($start, $limit, $num_items) + { + return max(0, $num_items - $limit - $start); + } + + /** + * Get new item limit when searching from the end + * + * If the user is trying to reach late pages, start searching from the end. + * In this case the items to display might be lower then the actual per_page setting. + * + * @param int $start the item which should be considered currently active, used to determine the page we're on + * @param int $per_page the number of items, posts, etc. per page + * @param int $num_items the total number of items, posts, topics, etc. + * @return int Current page number + */ + public function reverse_limit($start, $per_page, $num_items) + { + if ($start + $per_page > $num_items) + { + return min($per_page, max(1, $num_items - $start)); + } + + return $per_page; + } +} diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php new file mode 100644 index 0000000000..8256fd721c --- /dev/null +++ b/phpBB/phpbb/passwords/driver/base.php @@ -0,0 +1,45 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +abstract class base implements driver_interface +{ + /** @var phpbb\config\config */ + protected $config; + + /** @var phpbb\passwords\driver\helper */ + protected $helper; + + /** @var driver name */ + protected $name; + + /** + * Constructor of passwords driver object + * + * @param \phpbb\config\config $config phpBB config + * @param \phpbb\passwords\driver\helper $helper Password driver helper + */ + public function __construct(\phpbb\config\config $config, helper $helper) + { + $this->config = $config; + $this->helper = $helper; + } + + /** + * @inheritdoc + */ + public function is_supported() + { + return true; + } +} diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php new file mode 100644 index 0000000000..1d1b1e267d --- /dev/null +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -0,0 +1,104 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +class bcrypt extends base +{ + const PREFIX = '$2a$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function hash($password, $salt = '') + { + // The 2x and 2y prefixes of bcrypt might not be supported + // Revert to 2a if this is the case + $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix(); + + // Do not support 8-bit characters with $2a$ bcrypt + // Also see http://www.php.net/security/crypt_blowfish.php + if ($prefix === self::PREFIX) + { + if (ord($password[strlen($password)-1]) & 128) + { + return false; + } + } + + if ($salt == '') + { + $salt = $prefix . '10$' . $this->get_random_salt(); + } + + $hash = crypt($password, $salt); + if (strlen($hash) < 60) + { + return false; + } + return $hash; + } + + /** + * @inheritdoc + */ + public function check($password, $hash) + { + $salt = substr($hash, 0, 29); + if (strlen($salt) != 29) + { + return false; + } + + if ($hash == $this->hash($password, $salt)) + { + return true; + } + return false; + } + + /** + * Get a random salt value with a length of 22 characters + * + * @return string Salt for password hashing + */ + protected function get_random_salt() + { + return $this->helper->hash_encode64($this->helper->get_random_salt(22), 22); + } + + /** + * @inheritdoc + */ + public function get_settings_only($hash, $full = false) + { + if ($full) + { + $pos = stripos($hash, '$', 1) + 1; + $length = 22 + (strripos($hash, '$') + 1 - $pos); + } + else + { + $pos = strripos($hash, '$') + 1; + $length = 22; + } + return substr($hash, $pos, $length); + } +} diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php new file mode 100644 index 0000000000..11c3617e49 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -0,0 +1,34 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +class bcrypt_2y extends bcrypt +{ + const PREFIX = '$2y$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_supported() + { + return (version_compare(PHP_VERSION, '5.3.7', '<')) ? false : true; + } +} diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php new file mode 100644 index 0000000000..ebaf0626af --- /dev/null +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -0,0 +1,60 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +interface driver_interface +{ + /** + * Check if hash type is supported + * + * @return bool True if supported, false if not + */ + public function is_supported(); + + /** + * Returns the hash prefix + * + * @return string Hash prefix + */ + public function get_prefix(); + + /** + * Hash the password + * + * @param string $password The password that should be hashed + * + * @return bool|string Password hash or false if something went wrong + * during hashing + */ + public function hash($password); + + /** + * Check the password against the supplied hash + * + * @param string $password The password to check + * @param string $hash The password hash to check against + * + * @return bool True if password is correct, else false + */ + public function check($password, $hash); + + /** + * Get only the settings of the specified hash + * + * @param string $hash Password hash + * @param bool $full Return full settings or only settings + * related to the salt + * @return string String containing the hash settings + */ + public function get_settings_only($hash, $full = false); +} diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php new file mode 100644 index 0000000000..4b8dc9a123 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -0,0 +1,144 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +class helper +{ + /** + * @var phpbb\config\config + */ + protected $config; + + /** + * base64 alphabet + * @var string + */ + public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + /** + * Construct a driver helper object + * + * @param phpbb\config\config $config phpBB configuration + */ + public function __construct(\phpbb\config\config $config) + { + $this->config = $config; + } + + /** + * Base64 encode hash + * + * @param string $input Input string + * @param int $count Input string length + * + * @return string base64 encoded string + */ + public function hash_encode64($input, $count) + { + $output = ''; + $i = 0; + + do + { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + + if ($i < $count) + { + $value |= ord($input[$i]) << 8; + } + + $output .= $this->itoa64[($value >> 6) & 0x3f]; + + if ($i++ >= $count) + { + break; + } + + if ($i < $count) + { + $value |= ord($input[$i]) << 16; + } + + $output .= $this->itoa64[($value >> 12) & 0x3f]; + + if ($i++ >= $count) + { + break; + } + + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } + while ($i < $count); + + return $output; + } + + /** + * Return unique id + * + * @param string $extra Additional entropy + * + * @return string Unique id + */ + public function unique_id($extra = 'c') + { + static $dss_seeded = false; + + $val = $this->config['rand_seed'] . microtime(); + $val = md5($val); + $this->config['rand_seed'] = md5($this->config['rand_seed'] . $val . $extra); + + if ($dss_seeded !== true && ($this->config['rand_seed_last_update'] < time() - rand(1,10))) + { + $this->config->set('rand_seed_last_update', time(), true); + $this->config->set('rand_seed', $this->config['rand_seed'], true); + $dss_seeded = true; + } + + return substr($val, 4, 16); + } + + /** + * Get random salt with specified length + * + * @param int $length Salt length + * @param string $rand_seed Seed for random data (optional). For tests. + * + * @return string Random salt with specified length + */ + public function get_random_salt($length, $rand_seed = '/dev/urandom') + { + $random = ''; + + if (($fh = @fopen($rand_seed, 'rb'))) + { + $random = fread($fh, $length); + fclose($fh); + } + + if (strlen($random) < $length) + { + $random = ''; + $random_state = $this->unique_id(); + + for ($i = 0; $i < $length; $i += 16) + { + $random_state = md5($this->unique_id() . $random_state); + $random .= pack('H*', md5($random_state)); + } + $random = substr($random, 0, $length); + } + return $random; + } +} diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php new file mode 100644 index 0000000000..80c4d7a7f0 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -0,0 +1,26 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* @package passwords +*/ +class phpass extends salted_md5 +{ + const PREFIX = '$P$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } +} diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php new file mode 100644 index 0000000000..5c72726422 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -0,0 +1,160 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords\driver; + +/** +* +* @version Version 0.1 / slightly modified for phpBB 3.1.x (using $H$ as hash type identifier) +* +* Portable PHP password hashing framework. +* +* Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in +* the public domain. +* +* There's absolutely no warranty. +* +* The homepage URL for this framework is: +* +* http://www.openwall.com/phpass/ +* +* Please be sure to update the Version line if you edit this file in any way. +* It is suggested that you leave the main version number intact, but indicate +* your project name (after the slash) and add your own revision information. +* +* Please do not change the "private" password hashing method implemented in +* here, thereby making your hashes incompatible. However, if you must, please +* change the hash type identifier (the "$P$") to something different. +* +* Obviously, since this code is in the public domain, the above are not +* requirements (there can be none), but merely suggestions. +* +*/ + +/** +* @package passwords +*/ +class salted_md5 extends base +{ + const PREFIX = '$H$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function hash($password, $setting = '') + { + if ($setting) + { + if (($settings = $this->get_hash_settings($setting)) === false) + { + // Return md5 of password if settings do not + // comply with our standards. This will only + // happen if pre-determined settings are + // directly passed to the driver. The manager + // will not do this. Same as the old hashing + // implementatio in phpBB 3.0 + return md5($password); + } + } + else + { + $settings = $this->get_hash_settings($this->generate_salt()); + } + + $hash = md5($settings['salt'] . $password, true); + do + { + $hash = md5($hash . $password, true); + } + while (--$settings['count']); + + $output = $settings['full']; + $output .= $this->helper->hash_encode64($hash, 16); + + return $output; + } + + /** + * @inheritdoc + */ + public function check($password, $hash) + { + if (strlen($hash) !== 34) + { + return md5($password) === $hash; + } + + return $hash === $this->hash($password, $hash); + } + + /** + * Generate salt for hashing method + * + * @return string Salt for hashing method + */ + protected function generate_salt() + { + $count = 6; + + $random = $this->helper->get_random_salt($count); + + $salt = $this->get_prefix(); + $salt .= $this->helper->itoa64[min($count + 5, 30)]; + $salt .= $this->helper->hash_encode64($random, $count); + + return $salt; + } + + /** + * Get hash settings + * + * @param string $hash The hash that contains the settings + * + * @return bool|array Array containing the count_log2, salt, and full + * hash settings string or false if supplied hash is empty + * or contains incorrect settings + */ + public function get_hash_settings($hash) + { + if (empty($hash)) + { + return false; + } + + $count_log2 = strpos($this->helper->itoa64, $hash[3]); + $salt = substr($hash, 4, 8); + + if ($count_log2 < 7 || $count_log2 > 30 || strlen($salt) != 8) + { + return false; + } + + return array( + 'count' => 1 << $count_log2, + 'salt' => $salt, + 'full' => substr($hash, 0, 12), + ); + } + + /** + * @inheritdoc + */ + public function get_settings_only($hash, $full = false) + { + return substr($hash, 3, 9); + } +} diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php new file mode 100644 index 0000000000..95bad5805f --- /dev/null +++ b/phpBB/phpbb/passwords/helper.php @@ -0,0 +1,103 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords; + +/** +* @package passwords +*/ +class helper +{ + /** + * Get hash settings from combined hash + * + * @param string $hash Password hash of combined hash + * + * @return array An array containing the hash settings for the hash + * types in successive order as described by the combined + * password hash or an empty array if hash does not + * properly fit the combined hash format + */ + public function get_combined_hash_settings($hash) + { + $output = array(); + + preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); + $hash_settings = substr($hash, strpos($hash, $match[1]) + strlen($match[1]) + 1); + $matches = explode('\\', $match[1]); + foreach ($matches as $cur_type) + { + $dollar_position = strpos($hash_settings, '$'); + $output[] = substr($hash_settings, 0, ($dollar_position != false) ? $dollar_position : strlen($hash_settings)); + $hash_settings = substr($hash_settings, $dollar_position + 1); + } + + return $output; + } + + /** + * Combine hash prefixes, settings, and actual hash + * + * @param array $data Array containing the keys 'prefix' and 'settings'. + * It will hold the prefixes and settings + * @param string $type Data type of the supplied value + * @param string $value Value that should be put into the data array + * + * @return string|null Return complete combined hash if type is neither + * 'prefix' nor 'settings', nothing if it is + */ + public function combine_hash_output(&$data, $type, $value) + { + if ($type == 'prefix') + { + $data[$type] .= ($data[$type] !== '$') ? '\\' : ''; + $data[$type] .= str_replace('$', '', $value); + } + elseif ($type == 'settings') + { + $data[$type] .= ($data[$type] !== '$') ? '$' : ''; + $data[$type] .= $value; + } + else + { + // Return full hash + return $data['prefix'] . $data['settings'] . '$' . $value; + } + } + + /** + * Rebuild hash for hashing functions + * + * @param string $prefix Hash prefix + * @param string $settings Hash settings + * + * @return string Rebuilt hash for hashing functions + */ + public function rebuild_hash($prefix, $settings) + { + $rebuilt_hash = $prefix; + if (strpos($settings, '\\') !== false) + { + $settings = str_replace('\\', '$', $settings); + } + $rebuilt_hash .= $settings; + return $rebuilt_hash; + } + + /** + * Obtain only the actual hash after the prefixes + * + * @param string $hash The full password hash + * @return string Actual hash (incl. settings) + */ + public function obtain_hash_only($hash) + { + return substr($hash, strripos($hash, '$') + 1); + } +} diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php new file mode 100644 index 0000000000..0ac6b05ec4 --- /dev/null +++ b/phpBB/phpbb/passwords/manager.php @@ -0,0 +1,341 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\passwords; + +/** +* @package passwords +*/ +class manager +{ + /** + * Default hashing method + */ + protected $type = false; + + /** + * Hashing algorithm type map + * Will be used to map hash prefix to type + */ + protected $type_map = false; + + /** + * Service collection of hashing algorithms + * Needs to be public for passwords helper + */ + public $algorithms = false; + + /** + * Password convert flag. Signals that password should be converted + */ + public $convert_flag = false; + + /** + * Passwords helper + * @var phpbb\passwords\helper + */ + protected $helper; + + /** + * phpBB configuration + * @var phpbb\config\config + */ + protected $config; + + /** + * Construct a passwords object + * + * @param phpbb\config\config $config phpBB configuration + * @param array $hashing_algorithms Hashing driver + * service collection + * @param phpbb\passwords\helper $helper Passwords helper object + * @param string $defaults List of default driver types + */ + public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults) + { + $this->config = $config; + $this->helper = $helper; + + $this->fill_type_map($hashing_algorithms); + $this->register_default_type($defaults); + } + + /** + * Register default type + * Will register the first supported type from the list of default types + * + * @param array $defaults List of default types in order from first to + * use to last to use + */ + protected function register_default_type($defaults) + { + foreach ($defaults as $type) + { + if ($this->algorithms[$type]->is_supported()) + { + $this->type = $this->algorithms[$type]->get_prefix(); + break; + } + } + } + + /** + * Fill algorithm type map + * + * @param phpbb\di\service_collection $hashing_algorithms + */ + protected function fill_type_map($hashing_algorithms) + { + foreach ($hashing_algorithms as $algorithm) + { + if (!isset($this->type_map[$algorithm->get_prefix()])) + { + $this->type_map[$algorithm->get_prefix()] = $algorithm; + } + } + $this->algorithms = $hashing_algorithms; + } + + /** + * Get the algorithm specified by a specific prefix + * + * @param string $prefix Password hash prefix + * + * @return object|bool The hash type object or false if prefix is not + * supported + */ + protected function get_algorithm($prefix) + { + if (isset($this->type_map[$prefix])) + { + return $this->type_map[$prefix]; + } + else + { + return false; + } + } + + /** + * Detect the hash type of the supplied hash + * + * @param string $hash Password hash that should be checked + * + * @return object|bool The hash type object or false if the specified + * type is not supported + */ + public function detect_algorithm($hash) + { + /* + * preg_match() will also show hashing algos like $2a\H$, which + * is a combination of bcrypt and phpass. Legacy algorithms + * like md5 will not be matched by this and need to be treated + * differently. + */ + if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) + { + return $this->get_algorithm('$H$'); + } + + // Be on the lookout for multiple hashing algorithms + // 2 is correct: H\2a > 2, H\P > 2 + if (strlen($match[1]) > 2) + { + $hash_types = explode('\\', $match[1]); + $return_ary = array(); + foreach ($hash_types as $type) + { + // we do not support the same hashing + // algorithm more than once + if (isset($return_ary[$type])) + { + return false; + } + + $return_ary[$type] = $this->get_algorithm('$' . $type . '$'); + + if (empty($return_ary[$type])) + { + return false; + } + } + return $return_ary; + } + + // get_algorithm() will automatically return false if prefix + // is not supported + return $this->get_algorithm($match[0]); + } + + /** + * Hash supplied password + * + * @param string $password Password that should be hashed + * @param string $type Hash type. Will default to standard hash type if + * none is supplied + * @return string|bool Password hash of supplied password or false if + * if something went wrong during hashing + */ + public function hash($password, $type = '') + { + if (strlen($password) > 4096) + { + // If the password is too huge, we will simply reject it + // and not let the server try to hash it. + return false; + } + + // Try to retrieve algorithm by service name if type doesn't + // start with dollar sign + if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type])) + { + $type = $this->algorithms[$type]->get_prefix(); + } + + $type = ($type === '') ? $this->type : $type; + + if (is_array($type)) + { + return $this->combined_hash_password($password, $type); + } + + if (isset($this->type_map[$type])) + { + $hashing_algorithm = $this->type_map[$type]; + } + else + { + return false; + } + + return $hashing_algorithm->hash($password); + } + + /** + * Check supplied password against hash and set convert_flag if password + * needs to be converted to different format (preferrably newer one) + * + * @param string $password Password that should be checked + * @param string $hash Stored hash + * @return string|bool True if password is correct, false if not + */ + public function check($password, $hash) + { + if (strlen($password) > 4096) + { + // If the password is too huge, we will simply reject it + // and not let the server try to hash it. + return false; + } + + // First find out what kind of hash we're dealing with + $stored_hash_type = $this->detect_algorithm($hash); + if ($stored_hash_type == false) + { + return false; + } + + // Multiple hash passes needed + if (is_array($stored_hash_type)) + { + $correct = $this->check_combined_hash($password, $stored_hash_type, $hash); + $this->convert_flag = ($correct === true) ? true : false; + return $correct; + } + + if ($stored_hash_type->get_prefix() !== $this->type) + { + $this->convert_flag = true; + } + else + { + $this->convert_flag = false; + } + + return $stored_hash_type->check($password, $hash); + } + + /** + * Create combined hash from already hashed password + * + * @param string $password_hash Complete current password hash + * @param string $type Type of the hashing algorithm the password hash + * should be combined with + * @return string|bool Combined password hash if combined hashing was + * successful, else false + */ + public function combined_hash_password($password_hash, $type) + { + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->helper->get_combined_hash_settings($password_hash); + $hash = $hash_settings[0]; + + // Put settings of current hash into data array + $stored_hash_type = $this->detect_algorithm($password_hash); + $this->helper->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix()); + $this->helper->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash)); + + // Hash current hash with the defined types + foreach ($type as $cur_type) + { + if (isset($this->algorithms[$cur_type])) + { + $new_hash_type = $this->algorithms[$cur_type]; + } + else + { + $new_hash_type = $this->get_algorithm($cur_type); + } + + if (!$new_hash_type) + { + return false; + } + + $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash)); + $this->helper->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix()); + $this->helper->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0)); + $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->helper->obtain_hash_only($new_hash)); + } + return $this->helper->combine_hash_output($data, 'hash', $hash); + } + + /** + * Check combined password hash against the supplied password + * + * @param string $password Password entered by user + * @param array $stored_hash_type An array containing the hash types + * as described by stored password hash + * @param string $hash Stored password hash + * + * @return bool True if password is correct, false if not + */ + public function check_combined_hash($password, $stored_hash_type, $hash) + { + $i = 0; + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->helper->get_combined_hash_settings($hash); + foreach ($stored_hash_type as $key => $hash_type) + { + $rebuilt_hash = $this->helper->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]); + $this->helper->combine_hash_output($data, 'prefix', $key); + $this->helper->combine_hash_output($data, 'settings', $hash_settings[$i]); + $cur_hash = $hash_type->hash($password, $rebuilt_hash); + $password = str_replace($rebuilt_hash, '', $cur_hash); + $i++; + } + return ($hash === $this->helper->combine_hash_output($data, 'hash', $password)); + } +} diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php new file mode 100644 index 0000000000..fefef39c51 --- /dev/null +++ b/phpBB/phpbb/path_helper.php @@ -0,0 +1,219 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb; + +/** +* A class with various functions that are related to paths, files and the filesystem +* @package phpBB3 +*/ +class path_helper +{ + /** @var \phpbb\symfony_request */ + protected $symfony_request; + + /** @var \phpbb\filesystem */ + protected $filesystem; + + /** @var string */ + protected $phpbb_root_path; + + /** @var string */ + protected $adm_relative_path; + + /** @var string */ + protected $php_ext; + + /** @var string */ + protected $web_root_path; + + /** + * Constructor + * + * @param \phpbb\symfony_request $symfony_request + * @param \phpbb\filesystem $filesystem + * @param string $phpbb_root_path Relative path to phpBB root + * @param string $php_ext PHP extension (php) + */ + public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $adm_relative_path = null) + { + $this->symfony_request = $symfony_request; + $this->filesystem = $filesystem; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->adm_relative_path = $adm_relative_path; + } + + /** + * Get the phpBB root path + * + * @return string + */ + public function get_phpbb_root_path() + { + return $this->phpbb_root_path; + } + + /** + * Get the adm root path + * + * @return string + */ + public function get_adm_relative_path() + { + return $this->adm_relative_path; + } + + /** + * Get the php extension + * + * @return string + */ + public function get_php_ext() + { + return $this->php_ext; + } + + /** + * Update a web path to the correct relative root path + * + * This replaces $phpbb_root_path . some_url with + * get_web_root_path() . some_url + * + * @param string $path The path to be updated + * @return string + */ + public function update_web_root_path($path) + { + if (strpos($path, $this->phpbb_root_path) === 0) + { + $path = substr($path, strlen($this->phpbb_root_path)); + + return $this->get_web_root_path() . $path; + } + + return $path; + } + + /** + * Strips away the web root path and prepends the normal root path + * + * This replaces get_web_root_path() . some_url with + * $phpbb_root_path . some_url + * + * @param string $path The path to be updated + * @return string + */ + public function remove_web_root_path($path) + { + if (strpos($path, $this->get_web_root_path()) === 0) + { + $path = substr($path, strlen($this->get_web_root_path())); + + return $this->phpbb_root_path . $path; + } + + return $path; + } + + /** + * Get a relative root path from the current URL + * + * @return string + */ + public function get_web_root_path() + { + if ($this->symfony_request === null) + { + return $this->phpbb_root_path; + } + + if (null !== $this->web_root_path) + { + return $this->web_root_path; + } + + // Path info (e.g. /foo/bar) + $path_info = $this->filesystem->clean_path($this->symfony_request->getPathInfo()); + + // Full request URI (e.g. phpBB/app.php/foo/bar) + $request_uri = $this->symfony_request->getRequestUri(); + + // Script name URI (e.g. phpBB/app.php) + $script_name = $this->symfony_request->getScriptName(); + + /* + * If the path info is empty but we're using app.php, then we + * might be using an empty route like app.php/ which is + * supported by symfony's routing + */ + if ($path_info === '/' && preg_match('/app\.' . $this->php_ext . '\/$/', $request_uri)) + { + return $this->web_root_path = $this->phpbb_root_path . '../'; + } + + /* + * If the path info is empty (single /), then we're not using + * a route like app.php/foo/bar + */ + if ($path_info === '/') + { + return $this->web_root_path = $this->phpbb_root_path; + } + + // How many corrections might we need? + $corrections = substr_count($path_info, '/'); + + /* + * If the script name (e.g. phpBB/app.php) exists in the + * requestUri (e.g. phpBB/app.php/foo/template), then we + * are have a non-rewritten URL. + */ + if (strpos($request_uri, $script_name) === 0) + { + /* + * Append ../ to the end of the phpbb_root_path as many times + * as / exists in path_info + */ + return $this->web_root_path = $this->phpbb_root_path . str_repeat('../', $corrections); + } + + /* + * If we're here it means we're at a re-written path, so we must + * correct the relative path for web URLs. We must append ../ + * to the end of the root path as many times as / exists in path_info + * less one time (because the script, e.g. /app.php, doesn't exist in + * the URL) + */ + return $this->web_root_path = $this->phpbb_root_path . str_repeat('../', $corrections - 1); + } + + /** + * Eliminates useless . and .. components from specified URL + * + * @param string $url URL to clean + * + * @return string Cleaned URL + */ + public function clean_url($url) + { + $delimiter_position = strpos($url, '://'); + // URL should contain :// but it shouldn't start with it. + // Do not clean URLs that do not fit these constraints. + if (empty($delimiter_position)) + { + return $url; + } + $scheme = substr($url, 0, $delimiter_position) . '://'; + // Add length of URL delimiter to position + $path = substr($url, $delimiter_position + 3); + + return $scheme . $this->filesystem->clean_path($path); + } +} diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php index 0fbacdad8a..3cf39b5126 100644 --- a/phpBB/phpbb/permissions.php +++ b/phpBB/phpbb/permissions.php @@ -7,36 +7,30 @@ * */ -/** -* DO NOT CHANGE -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; -class phpbb_permissions +class permissions { /** * Event dispatcher object - * @var phpbb_event_dispatcher + * @var \phpbb\event\dispatcher */ protected $dispatcher; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Constructor * - * @param phpbb_event_dispatcher $phpbb_dispatcher Event dispatcher - * @param phpbb_user $user User Object + * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher + * @param \phpbb\user $user User Object * @return null */ - public function __construct(phpbb_event_dispatcher $phpbb_dispatcher, phpbb_user $user) + public function __construct(\phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\user $user) { $this->dispatcher = $phpbb_dispatcher; $this->user = $user; @@ -63,7 +57,7 @@ class phpbb_permissions * 'lang' => 'ACL_U_VIEWPROFILE', * 'cat' => 'profile', * ), - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('types', 'categories', 'permissions'); extract($phpbb_dispatcher->trigger_event('core.permissions', compact($vars))); @@ -241,14 +235,14 @@ class phpbb_permissions // Forum Permissions 'f_list' => array('lang' => 'ACL_F_LIST', 'cat' => 'actions'), - 'f_read' => array('lang' => 'ACL_F_READ', 'cat' => 'actions'), + 'f_read' => array('lang' => 'ACL_F_READ', 'cat' => 'actions'), 'f_search' => array('lang' => 'ACL_F_SEARCH', 'cat' => 'actions'), 'f_subscribe' => array('lang' => 'ACL_F_SUBSCRIBE', 'cat' => 'actions'), - 'f_print' => array('lang' => 'ACL_F_PRINT', 'cat' => 'actions'), - 'f_email' => array('lang' => 'ACL_F_EMAIL', 'cat' => 'actions'), + 'f_print' => array('lang' => 'ACL_F_PRINT', 'cat' => 'actions'), + 'f_email' => array('lang' => 'ACL_F_EMAIL', 'cat' => 'actions'), 'f_bump' => array('lang' => 'ACL_F_BUMP', 'cat' => 'actions'), 'f_user_lock' => array('lang' => 'ACL_F_USER_LOCK', 'cat' => 'actions'), - 'f_download' => array('lang' => 'ACL_F_DOWNLOAD', 'cat' => 'actions'), + 'f_download' => array('lang' => 'ACL_F_DOWNLOAD', 'cat' => 'actions'), 'f_report' => array('lang' => 'ACL_F_REPORT', 'cat' => 'actions'), 'f_post' => array('lang' => 'ACL_F_POST', 'cat' => 'post'), @@ -257,13 +251,14 @@ class phpbb_permissions 'f_reply' => array('lang' => 'ACL_F_REPLY', 'cat' => 'post'), 'f_edit' => array('lang' => 'ACL_F_EDIT', 'cat' => 'post'), 'f_delete' => array('lang' => 'ACL_F_DELETE', 'cat' => 'post'), + 'f_softdelete' => array('lang' => 'ACL_F_SOFTDELETE', 'cat' => 'post'), 'f_ignoreflood' => array('lang' => 'ACL_F_IGNOREFLOOD', 'cat' => 'post'), 'f_postcount' => array('lang' => 'ACL_F_POSTCOUNT', 'cat' => 'post'), - 'f_noapprove' => array('lang' => 'ACL_F_NOAPPROVE', 'cat' => 'post'), + 'f_noapprove' => array('lang' => 'ACL_F_NOAPPROVE', 'cat' => 'post'), - 'f_attach' => array('lang' => 'ACL_F_ATTACH', 'cat' => 'content'), + 'f_attach' => array('lang' => 'ACL_F_ATTACH', 'cat' => 'content'), 'f_icons' => array('lang' => 'ACL_F_ICONS', 'cat' => 'content'), - 'f_bbcode' => array('lang' => 'ACL_F_BBCODE', 'cat' => 'content'), + 'f_bbcode' => array('lang' => 'ACL_F_BBCODE', 'cat' => 'content'), 'f_flash' => array('lang' => 'ACL_F_FLASH', 'cat' => 'content'), 'f_img' => array('lang' => 'ACL_F_IMG', 'cat' => 'content'), 'f_sigs' => array('lang' => 'ACL_F_SIGS', 'cat' => 'content'), diff --git a/phpBB/phpbb/php/ini.php b/phpBB/phpbb/php/ini.php index 17e8c54a57..f0f53807fe 100644 --- a/phpBB/phpbb/php/ini.php +++ b/phpBB/phpbb/php/ini.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\php; /** * Wrapper class for ini_get function. @@ -22,7 +16,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB */ -class phpbb_php_ini +class ini { /** * Simple wrapper for ini_get() diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php new file mode 100644 index 0000000000..b988ce7ce0 --- /dev/null +++ b/phpBB/phpbb/plupload/plupload.php @@ -0,0 +1,375 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\plupload; + +/** +* This class handles all server-side plupload functions +* +* @package \phpbb\plupload\plupload +*/ +class plupload +{ + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var \phpbb\config\config + */ + protected $config; + + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * @var \phpbb\php\ini + */ + protected $php_ini; + + /** + * @var \phpbb\mimetype\guesser + */ + protected $mimetype_guesser; + + /** + * Final destination for uploaded files, i.e. the "files" directory. + * @var string + */ + protected $upload_directory; + + /** + * Temporary upload directory for plupload uploads. + * @var string + */ + protected $temporary_directory; + + /** + * Constructor. + * + * @param string $phpbb_root_path + * @param \phpbb\config\config $config + * @param \phpbb\request\request_interface $request + * @param \phpbb\user $user + * @param \phpbb\php\ini $php_ini + * @param \phpbb\mimetype\guesser $mimetype_guesser + * + * @return null + */ + public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \phpbb\php\ini $php_ini, \phpbb\mimetype\guesser $mimetype_guesser) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->config = $config; + $this->request = $request; + $this->user = $user; + $this->php_ini = $php_ini; + $this->mimetype_guesser = $mimetype_guesser; + + $this->upload_directory = $this->phpbb_root_path . $this->config['upload_path']; + $this->temporary_directory = $this->upload_directory . '/plupload'; + } + + /** + * Plupload allows for chunking so we must check for that and assemble + * the whole file first before performing any checks on it. + * + * @param string $form_name The name of the file element in the upload form + * + * @return array|null null if there are no chunks to piece together + * otherwise array containing the path to the + * pieced-together file and its size + */ + public function handle_upload($form_name) + { + $chunks_expected = $this->request->variable('chunks', 0); + + // If chunking is disabled or we are not using plupload, just return + // and handle the file as usual + if ($chunks_expected < 2) + { + return; + } + + $file_name = $this->request->variable('name', ''); + $chunk = $this->request->variable('chunk', 0); + + $this->user->add_lang('plupload'); + $this->prepare_temporary_directory(); + + $file_path = $this->temporary_filepath($file_name); + $this->integrate_uploaded_file($form_name, $chunk, $file_path); + + // If we are done with all the chunks, strip the .part suffix and then + // handle the resulting file as normal, otherwise die and await the + // next chunk. + if ($chunk == $chunks_expected - 1) + { + rename("{$file_path}.part", $file_path); + + // Need to modify some of the $_FILES values to reflect the new file + return array( + 'tmp_name' => $file_path, + 'name' => $this->request->variable('real_filename', ''), + 'size' => filesize($file_path), + 'type' => $this->mimetype_guesser->guess($file_path, $file_name), + ); + } + else + { + $json_response = new \phpbb\json_response(); + $json_response->send(array( + 'jsonrpc' => '2.0', + 'id' => 'id', + 'result' => null, + )); + } + } + + /** + * Fill in the plupload configuration options in the template + * + * @param \phpbb\cache\service $cache + * @param \phpbb\template\template $template + * @param string $s_action The URL to submit the POST data to + * @param int $forum_id The ID of the forum + * @param int $max_files Maximum number of files allowed. 0 for unlimited. + * + * @return null + */ + public function configure(\phpbb\cache\service $cache, \phpbb\template\template $template, $s_action, $forum_id, $max_files) + { + $filters = $this->generate_filter_string($cache, $forum_id); + $chunk_size = $this->get_chunk_size(); + $resize = $this->generate_resize_string(); + + $template->assign_vars(array( + 'S_RESIZE' => $resize, + 'S_PLUPLOAD' => true, + 'FILTERS' => $filters, + 'CHUNK_SIZE' => $chunk_size, + 'S_PLUPLOAD_URL' => htmlspecialchars_decode($s_action), + 'MAX_ATTACHMENTS' => $max_files, + 'ATTACH_ORDER' => ($this->config['display_order']) ? 'asc' : 'desc', + 'L_TOO_MANY_ATTACHMENTS' => $this->user->lang('TOO_MANY_ATTACHMENTS', $max_files), + )); + + $this->user->add_lang('plupload'); + } + + /** + * Checks whether the page request was sent by plupload or not + * + * @return bool + */ + public function is_active() + { + return $this->request->header('X-PHPBB-USING-PLUPLOAD', false); + } + + /** + * Returns whether the current HTTP request is a multipart request. + * + * @return bool + */ + public function is_multipart() + { + $content_type = $this->request->server('CONTENT_TYPE'); + + return strpos($content_type, 'multipart') === 0; + } + + /** + * Sends an error message back to the client via JSON response + * + * @param int $code The error code + * @param string $msg The translation string of the message to be sent + * + * @return null + */ + public function emit_error($code, $msg) + { + $json_response = new \phpbb\json_response(); + $json_response->send(array( + 'jsonrpc' => '2.0', + 'id' => 'id', + 'error' => array( + 'code' => $code, + 'message' => $this->user->lang($msg), + ), + )); + } + + /** + * Looks at the list of allowed extensions and generates a string + * appropriate for use in configuring plupload with + * + * @param \phpbb\cache\service $cache + * @param string $forum_id The ID of the forum + * + * @return string + */ + public function generate_filter_string(\phpbb\cache\service $cache, $forum_id) + { + $attach_extensions = $cache->obtain_attach_extensions($forum_id); + unset($attach_extensions['_allowed_']); + $groups = array(); + + // Re-arrange the extension array to $groups[$group_name][] + foreach ($attach_extensions as $extension => $extension_info) + { + if (!isset($groups[$extension_info['group_name']])) + { + $groups[$extension_info['group_name']] = array(); + } + + $groups[$extension_info['group_name']][] = $extension; + } + + $filters = array(); + foreach ($groups as $group => $extensions) + { + $filters[] = sprintf( + "{title: '%s', extensions: '%s'}", + addslashes(ucfirst(strtolower($group))), + addslashes(implode(',', $extensions)) + ); + } + + return implode(',', $filters); + } + + /** + * Generates a string that is used to tell plupload to automatically resize + * files before uploading them. + * + * @return string + */ + public function generate_resize_string() + { + $resize = ''; + if ($this->config['img_max_height'] > 0 && $this->config['img_max_width'] > 0) + { + $resize = sprintf( + 'resize: {width: %d, height: %d, quality: 100},', + (int) $this->config['img_max_height'], + (int) $this->config['img_max_width'] + ); + } + + return $resize; + } + + /** + * Checks various php.ini values and the maximum file size to determine + * the maximum size chunks a file can be split up into for upload + * + * @return int + */ + public function get_chunk_size() + { + $max = min( + $this->php_ini->get_bytes('upload_max_filesize'), + $this->php_ini->get_bytes('post_max_size'), + max(1, $this->php_ini->get_bytes('memory_limit')), + $this->config['max_filesize'] + ); + + // Use half of the maximum possible to leave plenty of room for other + // POST data. + return floor($max / 2); + } + + protected function temporary_filepath($file_name) + { + // Must preserve the extension for plupload to work. + return sprintf( + '%s/%s_%s%s', + $this->temporary_directory, + $this->config['plupload_salt'], + md5($file_name), + \filespec::get_extension($file_name) + ); + } + + /** + * Checks whether the chunk we are about to deal with was actually uploaded + * by PHP and actually exists, if not, it generates an error + * + * @param string $form_name The name of the file in the form data + * + * @return null + */ + protected function integrate_uploaded_file($form_name, $chunk, $file_path) + { + $is_multipart = $this->is_multipart(); + $upload = $this->request->file($form_name); + if ($is_multipart && (!isset($upload['tmp_name']) || !is_uploaded_file($upload['tmp_name']))) + { + $this->emit_error(103, 'PLUPLOAD_ERR_MOVE_UPLOADED'); + } + + $tmp_file = $this->temporary_filepath($upload['tmp_name']); + + if (!move_uploaded_file($upload['tmp_name'], $tmp_file)) + { + $this->emit_error(103, 'PLUPLOAD_ERR_MOVE_UPLOADED'); + } + + $out = fopen("{$file_path}.part", $chunk == 0 ? 'wb' : 'ab'); + if (!$out) + { + $this->emit_error(102, 'PLUPLOAD_ERR_OUTPUT'); + } + + $in = fopen(($is_multipart) ? $tmp_file : 'php://input', 'rb'); + if (!$in) + { + $this->emit_error(101, 'PLUPLOAD_ERR_INPUT'); + } + + while ($buf = fread($in, 4096)) + { + fwrite($out, $buf); + } + + fclose($in); + fclose($out); + + if ($is_multipart) + { + unlink($tmp_file); + } + } + + /** + * Creates the temporary directory if it does not already exist. + * + * @return null + */ + protected function prepare_temporary_directory() + { + if (!file_exists($this->temporary_directory)) + { + mkdir($this->temporary_directory); + + copy( + $this->upload_directory . '/index.htm', + $this->temporary_directory . '/index.htm' + ); + } + } +} diff --git a/phpBB/phpbb/profilefields/lang_helper.php b/phpBB/phpbb/profilefields/lang_helper.php new file mode 100644 index 0000000000..7ad4722230 --- /dev/null +++ b/phpBB/phpbb/profilefields/lang_helper.php @@ -0,0 +1,130 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields; + +/** +* Custom Profile Fields +* @package phpBB3 +*/ +class lang_helper +{ + /** + * Array with the language option, grouped by field and language + * @var array + */ + protected $options_lang = array(); + + /** + * Database object + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * Table where the language strings are stored + * @var string + */ + protected $language_table; + + /** + * Construct + * + * @param \phpbb\db\driver\driver_interface $db Database object + * @param string $language_table Table where the language strings are stored + */ + public function __construct($db, $language_table) + { + $this->db = $db; + $this->language_table = $language_table; + } + + /** + * Get language entries for options and store them here for later use + */ + public function get_option_lang($field_id, $lang_id, $field_type, $preview_options) + { + if ($preview_options !== false) + { + $lang_options = (!is_array($preview_options)) ? explode("\n", $preview_options) : $preview_options; + + foreach ($lang_options as $num => $var) + { + if (!isset($this->options_lang[$field_id])) + { + $this->options_lang[$field_id] = array(); + } + if (!isset($this->options_lang[$field_id][$lang_id])) + { + $this->options_lang[$field_id][$lang_id] = array(); + } + $this->options_lang[$field_id][$lang_id][($num + 1)] = $var; + } + } + else + { + $sql = 'SELECT option_id, lang_value + FROM ' . $this->language_table . ' + WHERE field_id = ' . (int) $field_id . ' + AND lang_id = ' . (int) $lang_id . " + AND field_type = '" . $this->db->sql_escape($field_type) . "' + ORDER BY option_id"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['lang_value']; + } + $this->db->sql_freeresult($result); + } + } + + /** + * Are language options set for this field? + * + * @param int $field_id Database ID of the field + * @param int $lang_id ID of the language + * @param int $field_value Selected value of the field + * @return boolean + */ + public function is_set($field_id, $lang_id = null, $field_value = null) + { + $is_set = isset($this->options_lang[$field_id]); + + if ($is_set && (!is_null($lang_id) || !is_null($field_value))) + { + $is_set = isset($this->options_lang[$field_id][$lang_id]); + } + + if ($is_set && !is_null($field_value)) + { + $is_set = isset($this->options_lang[$field_id][$lang_id][$field_value]); + } + + return $is_set; + } + + /** + * Get the selected language string + * + * @param int $field_id Database ID of the field + * @param int $lang_id ID of the language + * @param int $field_value Selected value of the field + * @return string + */ + public function get($field_id, $lang_id, $field_value = null) + { + if (is_null($field_value)) + { + return $this->options_lang[$field_id][$lang_id]; + } + + return $this->options_lang[$field_id][$lang_id][$field_value]; + } +} diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php new file mode 100644 index 0000000000..37449c67c4 --- /dev/null +++ b/phpBB/phpbb/profilefields/manager.php @@ -0,0 +1,437 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields; + +/** +* Custom Profile Fields +* @package phpBB3 +*/ +class manager +{ + /** + * Auth object + * @var \phpbb\auth\auth + */ + protected $auth; + + /** + * Database object + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * Service Collection object + * @var \phpbb\di\service_collection + */ + protected $type_collection; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + protected $fields_table; + + protected $fields_language_table; + + protected $fields_data_table; + + protected $profile_cache = array(); + + /** + * Construct + * + * @param \phpbb\auth\auth $auth Auth object + * @param \phpbb\db\driver\driver_interface $db Database object + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\di\service_collection $type_collection + * @param \phpbb\user $user User object + * @param string $fields_table + * @param string $fields_language_table + * @param string $fields_data_table + */ + public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table) + { + $this->auth = $auth; + $this->db = $db; + $this->request = $request; + $this->template = $template; + $this->type_collection = $type_collection; + $this->user = $user; + + $this->fields_table = $fields_table; + $this->fields_language_table = $fields_language_table; + $this->fields_data_table = $fields_data_table; + } + + /** + * Assign editable fields to template, mode can be profile (for profile change) or register (for registration) + * Called by ucp_profile and ucp_register + */ + public function generate_profile_fields($mode, $lang_id) + { + $sql_where = ''; + switch ($mode) + { + case 'register': + // If the field is required we show it on the registration page + $sql_where .= ' AND f.field_show_on_reg = 1'; + break; + + case 'profile': + // Show hidden fields to moderators/admins + if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_')) + { + $sql_where .= ' AND f.field_show_profile = 1'; + } + break; + + default: + trigger_error('Wrong profile mode specified', E_USER_ERROR); + break; + } + + $sql = 'SELECT l.*, f.* + FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . " f + WHERE f.field_active = 1 + $sql_where + AND l.lang_id = " . (int) $lang_id . ' + AND l.field_id = f.field_id + ORDER BY f.field_order'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + // Return templated field + $profile_field = $this->type_collection[$row['field_type']]; + $tpl_snippet = $profile_field->process_field_row('change', $row); + + $this->template->assign_block_vars('profile_fields', array( + 'LANG_NAME' => $this->user->lang($row['lang_name']), + 'LANG_EXPLAIN' => $this->user->lang($row['lang_explain']), + 'FIELD' => $tpl_snippet, + 'FIELD_ID' => $profile_field->get_field_ident($row), + 'S_REQUIRED' => ($row['field_required']) ? true : false, + )); + } + $this->db->sql_freeresult($result); + } + + /** + * Build profile cache, used for display + */ + protected function build_cache() + { + $this->profile_cache = array(); + + // Display hidden/no_view fields for admin/moderator + $sql = 'SELECT l.*, f.* + FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f + WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . ' + AND f.field_active = 1 ' . + ((!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_')) ? ' AND f.field_hide = 0 ' : '') . ' + AND f.field_no_view = 0 + AND l.field_id = f.field_id + ORDER BY f.field_order'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $this->profile_cache[$row['field_ident']] = $row; + } + $this->db->sql_freeresult($result); + } + + /** + * Submit profile field for validation + */ + public function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error) + { + $sql_where = ''; + switch ($mode) + { + case 'register': + // If the field is required we show it on the registration page + $sql_where .= ' AND f.field_show_on_reg = 1'; + break; + + case 'profile': + // Show hidden fields to moderators/admins + if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_')) + { + $sql_where .= ' AND f.field_show_profile = 1'; + } + break; + + default: + trigger_error('Wrong profile mode specified', E_USER_ERROR); + break; + } + + $sql = 'SELECT l.*, f.* + FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f + WHERE l.lang_id = ' . (int) $lang_id . " + AND f.field_active = 1 + $sql_where + AND l.field_id = f.field_id + ORDER BY f.field_order"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $profile_field = $this->type_collection[$row['field_type']]; + $cp_data['pf_' . $row['field_ident']] = $profile_field->get_profile_field($row); + $check_value = $cp_data['pf_' . $row['field_ident']]; + + if (($cp_result = $profile_field->validate_profile_field($check_value, $row)) !== false) + { + // If the result is not false, it's an error message + $cp_error[] = $cp_result; + } + } + $this->db->sql_freeresult($result); + } + + /** + * Update profile field data directly + */ + public function update_profile_field_data($user_id, $cp_data) + { + if (!sizeof($cp_data)) + { + return; + } + + $sql = 'UPDATE ' . $this->fields_data_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . ' + WHERE user_id = ' . (int) $user_id; + $this->db->sql_query($sql); + + if (!$this->db->sql_affectedrows()) + { + $cp_data = $this->build_insert_sql_array($cp_data); + $cp_data['user_id'] = (int) $user_id; + + $this->db->sql_return_on_error(true); + + $sql = 'INSERT INTO ' . $this->fields_data_table . ' ' . $this->db->sql_build_array('INSERT', $cp_data); + $this->db->sql_query($sql); + + $this->db->sql_return_on_error(false); + } + } + + /** + * Generate the template arrays in order to display the column names + * + * @param string $restrict_option Restrict the published fields to a certain profile field option + * @return array Returns an array with the template variables type, name and explain for the fields to display + */ + public function generate_profile_fields_template_headlines($restrict_option = '') + { + if (!sizeof($this->profile_cache)) + { + $this->build_cache(); + } + + $tpl_fields = array(); + + // Go through the fields in correct order + foreach ($this->profile_cache as $field_ident => $field_data) + { + if ($restrict_option && !$field_data[$restrict_option]) + { + continue; + } + + $profile_field = $this->type_collection[$field_data['field_type']]; + + $tpl_fields[] = array( + 'PROFILE_FIELD_TYPE' => $field_data['field_type'], + 'PROFILE_FIELD_NAME' => $profile_field->get_field_name($field_data['lang_name']), + 'PROFILE_FIELD_EXPLAIN' => $this->user->lang($field_data['lang_explain']), + ); + } + + return $tpl_fields; + } + + /** + * Grab the user specific profile fields data + * + * @param int|array $user_ids Single user id or an array of ids + * @return array Users profile fields data + */ + public function grab_profile_fields_data($user_ids = 0) + { + if (!is_array($user_ids)) + { + $user_ids = array($user_ids); + } + + if (!sizeof($this->profile_cache)) + { + $this->build_cache(); + } + + if (!sizeof($user_ids)) + { + return array(); + } + + $sql = 'SELECT * + FROM ' . $this->fields_data_table . ' + WHERE ' . $this->db->sql_in_set('user_id', array_map('intval', $user_ids)); + $result = $this->db->sql_query($sql); + + $field_data = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $field_data[$row['user_id']] = $row; + } + $this->db->sql_freeresult($result); + + $user_fields = array(); + + // Go through the fields in correct order + foreach (array_keys($this->profile_cache) as $used_ident) + { + foreach ($field_data as $user_id => $row) + { + $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident]; + $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; + } + + foreach ($user_ids as $user_id) + { + if (!isset($user_fields[$user_id][$used_ident]) && $this->profile_cache[$used_ident]['field_show_novalue']) + { + $user_fields[$user_id][$used_ident]['value'] = ''; + $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; + } + } + } + + return $user_fields; + } + + /** + * Assign the user's profile fields data to the template + * + * @param array $profile_row Array with users profile field data + * @param bool $use_contact_fields Should we display contact fields as such? + * This requires special treatments (links should not be parsed in the values, and more) + * @return array + */ + public function generate_profile_fields_template_data($profile_row, $use_contact_fields = true) + { + // $profile_row == $user_fields[$row['user_id']]; + $tpl_fields = array(); + $tpl_fields['row'] = $tpl_fields['blockrow'] = array(); + + foreach ($profile_row as $ident => $ident_ary) + { + $profile_field = $this->type_collection[$ident_ary['data']['field_type']]; + $value = $profile_field->get_profile_value($ident_ary['value'], $ident_ary['data']); + + if ($value === null) + { + continue; + } + + $field_desc = $contact_url = ''; + if ($use_contact_fields) + { + $value = $profile_field->get_profile_contact_value($ident_ary['value'], $ident_ary['data']); + $field_desc = $this->user->lang($ident_ary['data']['field_contact_desc']); + if (strpos($field_desc, '%s') !== false) + { + $field_desc = sprintf($field_desc, $value); + } + $contact_url = ''; + if (strpos($ident_ary['data']['field_contact_url'], '%s') !== false) + { + $contact_url = sprintf($ident_ary['data']['field_contact_url'], $value); + } + } + + $tpl_fields['row'] += array( + 'PROFILE_' . strtoupper($ident) . '_IDENT' => $ident, + 'PROFILE_' . strtoupper($ident) . '_VALUE' => $value, + 'PROFILE_' . strtoupper($ident) . '_CONTACT'=> $contact_url, + 'PROFILE_' . strtoupper($ident) . '_DESC' => $field_desc, + 'PROFILE_' . strtoupper($ident) . '_TYPE' => $ident_ary['data']['field_type'], + 'PROFILE_' . strtoupper($ident) . '_NAME' => $this->user->lang($ident_ary['data']['lang_name']), + 'PROFILE_' . strtoupper($ident) . '_EXPLAIN'=> $this->user->lang($ident_ary['data']['lang_explain']), + + 'S_PROFILE_' . strtoupper($ident) . '_CONTACT' => $ident_ary['data']['field_is_contact'], + 'S_PROFILE_' . strtoupper($ident) => true, + ); + + $tpl_fields['blockrow'][] = array( + 'PROFILE_FIELD_IDENT' => $ident, + 'PROFILE_FIELD_VALUE' => $value, + 'PROFILE_FIELD_CONTACT' => $contact_url, + 'PROFILE_FIELD_DESC' => $field_desc, + 'PROFILE_FIELD_TYPE' => $ident_ary['data']['field_type'], + 'PROFILE_FIELD_NAME' => $this->user->lang($ident_ary['data']['lang_name']), + 'PROFILE_FIELD_EXPLAIN' => $this->user->lang($ident_ary['data']['lang_explain']), + + 'S_PROFILE_CONTACT' => $ident_ary['data']['field_is_contact'], + 'S_PROFILE_' . strtoupper($ident) => true, + ); + } + + return $tpl_fields; + } + + /** + * Build Array for user insertion into custom profile fields table + */ + public function build_insert_sql_array($cp_data) + { + $sql_not_in = array(); + foreach ($cp_data as $key => $null) + { + $sql_not_in[] = (strncmp($key, 'pf_', 3) === 0) ? substr($key, 3) : $key; + } + + $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value + FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f + WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . ' + ' . ((sizeof($sql_not_in)) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' + AND l.field_id = f.field_id'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $profile_field = $this->type_collection[$row['field_type']]; + $cp_data['pf_' . $row['field_ident']] = $profile_field->get_default_field_value($row); + } + $this->db->sql_freeresult($result); + + return $cp_data; + } +} diff --git a/phpBB/phpbb/profilefields/type/type_base.php b/phpBB/phpbb/profilefields/type/type_base.php new file mode 100644 index 0000000000..a96196674d --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_base.php @@ -0,0 +1,191 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +abstract class type_base implements type_interface +{ + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name() + { + return $this->user->lang('FIELD_' . strtoupper($this->get_name_short())); + } + + /** + * {@inheritDoc} + */ + public function get_service_name() + { + return 'profilefields.type.' . $this->get_name_short(); + } + + /** + * {@inheritDoc} + */ + public function get_template_filename() + { + return 'profilefields/' . $this->get_name_short() . '.html'; + } + + /** + * {@inheritDoc} + */ + public function get_field_ident($field_data) + { + return 'pf_' . $field_data['field_ident']; + } + + /** + * {@inheritDoc} + */ + public function get_field_name($field_name) + { + return isset($this->user->lang[$field_name]) ? $this->user->lang[$field_name] : $field_name; + } + + /** + * {@inheritDoc} + */ + public function get_profile_contact_value($field_value, $field_data) + { + return $this->get_profile_value($field_value, $field_data); + } + + /** + * {@inheritDoc} + */ + public function get_language_options_input($field_data) + { + $field_data['l_lang_name'] = $this->request->variable('l_lang_name', array(0 => ''), true); + $field_data['l_lang_explain'] = $this->request->variable('l_lang_explain', array(0 => ''), true); + $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => ''), true); + $field_data['l_lang_options'] = $this->request->variable('l_lang_options', array(0 => ''), true); + + return $field_data; + } + + /** + * {@inheritDoc} + */ + public function prepare_options_form(&$exclude_options, &$visibility_options) + { + return $this->request->variable('lang_options', '', true); + } + + /** + * {@inheritDoc} + */ + public function validate_options_on_submit($error, $field_data) + { + return $error; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 3 && ($field_data[$key] || $action != 'edit') && $key == 'l_lang_options' && is_array($field_data[$key])) + { + foreach ($field_data[$key] as $lang_id => $options) + { + $field_data[$key][$lang_id] = explode("\n", $options); + } + + return $current_value; + } + + return $current_value; + } + + /** + * {@inheritDoc} + */ + public function prepare_hidden_fields($step, $key, $action, &$field_data) + { + if (!$this->request->is_set($key)) + { + // Do not set this variable, we will use the default value + return null; + } + else if ($key == 'field_ident' && isset($field_data[$key])) + { + return $field_data[$key]; + } + else + { + return $this->request->variable($key, '', true); + } + } + + /** + * {@inheritDoc} + */ + public function display_options(&$template_vars, &$field_data) + { + return; + } + + /** + * Return templated value/field. Possible values for $mode are: + * change == user is able to set/enter profile values; preview == just show the value + */ + public function process_field_row($mode, $profile_row) + { + $preview_options = ($mode == 'preview') ? $profile_row['lang_options'] : false; + + // set template filename + $this->template->set_filenames(array( + 'cp_body' => $this->get_template_filename(), + )); + + // empty previously filled blockvars + $this->template->destroy_block_vars($this->get_name_short()); + + // Assign template variables + $this->generate_field($profile_row, $preview_options); + + return $this->template->assign_display('cp_body'); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php new file mode 100644 index 0000000000..fa9c0a8714 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_bool.php @@ -0,0 +1,387 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_bool extends type_base +{ + /** + * Profile fields language helper + * @var \phpbb\profilefields\lang_helper + */ + protected $lang_helper; + + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\profilefields\lang_helper $lang_helper Profile fields language helper + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\profilefields\lang_helper $lang_helper, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->lang_helper = $lang_helper; + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'bool'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $profile_row = array( + 'var_name' => 'field_default_value', + 'field_id' => 1, + 'lang_name' => $field_data['lang_name'], + 'lang_explain' => $field_data['lang_explain'], + 'lang_id' => $default_lang_id, + 'field_default_value' => $field_data['field_default_value'], + 'field_ident' => 'field_default_value', + 'field_type' => $this->get_service_name(), + 'field_length' => $field_data['field_length'], + 'lang_options' => $field_data['lang_options'], + ); + + $options = array( + 0 => array('TITLE' => $this->user->lang['FIELD_TYPE'], 'EXPLAIN' => $this->user->lang['BOOL_TYPE_EXPLAIN'], 'FIELD' => '<label><input type="radio" class="radio" name="field_length" value="1"' . (($field_data['field_length'] == 1) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['RADIO_BUTTONS'] . '</label><label><input type="radio" class="radio" name="field_length" value="2"' . (($field_data['field_length'] == 2) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['CHECKBOX'] . '</label>'), + 1 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 1, + 'field_minlen' => 0, + 'field_maxlen' => 0, + 'field_validation' => '', + 'field_novalue' => 0, + 'field_default_value' => 0, + ); + } + + /** + * {@inheritDoc} + */ + public function get_default_field_value($field_data) + { + return $field_data['field_default_value']; + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + + // Checkbox + if ($profile_row['field_length'] == 2) + { + return ($this->request->is_set($var_name)) ? 1 : 0; + } + else + { + return $this->request->variable($var_name, (int) $profile_row['field_default_value']); + } + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + $field_value = (bool) $field_value; + + if (!$field_value && $field_data['field_required']) + { + return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + $field_id = $field_data['field_id']; + $lang_id = $field_data['lang_id']; + + if (!$this->lang_helper->is_set($field_id, $lang_id)) + { + $this->lang_helper->get_option_lang($field_id, $lang_id, FIELD_BOOL, false); + } + + if (!$field_value && $field_data['field_show_novalue']) + { + $field_value = $field_data['field_default_value']; + } + + if ($field_data['field_length'] == 1) + { + return ($this->lang_helper->is_set($field_id, $lang_id, (int) $field_value)) ? $this->lang_helper->get($field_id, $lang_id, (int) $field_value) : null; + } + else if (!$field_value) + { + return null; + } + else + { + return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1); + } + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + $default_value = $profile_row['field_default_value']; + + // checkbox - set the value to "true" if it has been set to 1 + if ($profile_row['field_length'] == 2) + { + $value = ($this->request->is_set($field_ident) && $this->request->variable($field_ident, $default_value) == 1) ? true : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]); + } + else + { + $value = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]); + } + + $profile_row['field_value'] = (int) $value; + $this->template->assign_block_vars('bool', array_change_key_case($profile_row, CASE_UPPER)); + + if ($profile_row['field_length'] == 1) + { + if (!$this->lang_helper->is_set($profile_row['field_id'], $profile_row['lang_id'], 1)) + { + $this->lang_helper->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], $this->get_service_name(), $preview_options); + } + + $options = $this->lang_helper->get($profile_row['field_id'], $profile_row['lang_id']); + foreach ($options as $option_id => $option_value) + { + $this->template->assign_block_vars('bool.options', array( + 'OPTION_ID' => $option_id, + 'CHECKED' => ($value == $option_id) ? ' checked="checked"' : '', + 'VALUE' => $option_value, + )); + } + } + } + + /** + * {@inheritDoc} + */ + public function get_field_ident($field_data) + { + return ($field_data['field_length'] == '1') ? '' : 'pf_' . $field_data['field_ident']; + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'TINT:2'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + 'lang_options' => 'two_options', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_language_options_input($field_data) + { + $field_data['l_lang_name'] = $this->request->variable('l_lang_name', array(0 => ''), true); + $field_data['l_lang_explain'] = $this->request->variable('l_lang_explain', array(0 => ''), true); + $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => ''), true); + + /** + * @todo check if this line is correct... + $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => array('')), true); + */ + $field_data['l_lang_options'] = $this->request->variable('l_lang_options', array(0 => array('')), true); + + return $field_data; + } + + /** + * {@inheritDoc} + */ + public function prepare_options_form(&$exclude_options, &$visibility_options) + { + $exclude_options[1][] = 'lang_options'; + + return $this->request->variable('lang_options', array(''), true); + } + + /** + * {@inheritDoc} + */ + public function validate_options_on_submit($error, $field_data) + { + if (empty($field_data['lang_options'][0]) || empty($field_data['lang_options'][1])) + { + $error[] = $this->user->lang['NO_FIELD_ENTRIES']; + } + + return $error; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 2 && $key == 'field_default_value') + { + // 'field_length' == 1 defines radio buttons. Possible values are 1 or 2 only. + // 'field_length' == 2 defines checkbox. Possible values are 0 or 1 only. + // If we switch the type on step 2, we have to adjust field value. + // 1 is a common value for the checkbox and radio buttons. + + // Adjust unchecked checkbox value. + // If we return or save settings from 2nd/3rd page + // and the checkbox is unchecked, set the value to 0. + if ($this->request->is_set('step') && !$this->request->is_set($key)) + { + return 0; + } + + // If we switch to the checkbox type but former radio buttons value was 2, + // which is not the case for the checkbox, set it to 0 (unchecked). + if ($field_data['field_length'] == 2 && $current_value == 2) + { + return 0; + } + // If we switch to the radio buttons but the former checkbox value was 0, + // which is not the case for the radio buttons, set it to 0. + else if ($field_data['field_length'] == 1 && $current_value == 0) + { + return 2; + } + } + + if ($step == 3 && ($field_data[$key] || $action != 'edit') && $key == 'l_lang_options') + { + $field_data[$key] = $this->request->variable($key, array(0 => array('')), true); + + return $current_value; + } + + return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); + } + + /** + * {@inheritDoc} + */ + public function prepare_hidden_fields($step, $key, $action, &$field_data) + { + if ($key == 'l_lang_options' && $this->request->is_set('l_lang_options')) + { + return $this->request->variable($key, array(array('')), true); + } + else if ($key == 'field_default_value') + { + return $this->request->variable($key, $field_data[$key]); + } + else + { + if (!$this->request->is_set($key)) + { + return false; + } + else if ($key == 'field_ident' && isset($field_data[$key])) + { + return $field_data[$key]; + } + else + { + return ($key == 'lang_options') ? $this->request->variable($key, array(''), true) : $this->request->variable($key, '', true); + } + } + } + + /** + * {@inheritDoc} + */ + public function display_options(&$template_vars, &$field_data) + { + // Initialize these array elements if we are creating a new field + if (!sizeof($field_data['lang_options'])) + { + // No options have been defined for a boolean field. + $field_data['lang_options'][0] = ''; + $field_data['lang_options'][1] = ''; + } + + $template_vars = array_merge($template_vars, array( + 'S_BOOL' => true, + 'L_LANG_OPTIONS_EXPLAIN' => $this->user->lang['BOOL_ENTRIES_EXPLAIN'], + 'FIRST_LANG_OPTION' => $field_data['lang_options'][0], + 'SECOND_LANG_OPTION' => $field_data['lang_options'][1], + )); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php new file mode 100644 index 0000000000..af3d65c9b6 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_date.php @@ -0,0 +1,358 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_date extends type_base +{ + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'date'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $profile_row = array( + 'var_name' => 'field_default_value', + 'lang_name' => $field_data['lang_name'], + 'lang_explain' => $field_data['lang_explain'], + 'lang_id' => $default_lang_id, + 'field_default_value' => $field_data['field_default_value'], + 'field_ident' => 'field_default_value', + 'field_type' => $this->get_service_name(), + 'field_length' => $field_data['field_length'], + 'lang_options' => $field_data['lang_options'], + ); + + $always_now = request_var('always_now', -1); + if ($always_now == -1) + { + $s_checked = ($field_data['field_default_value'] == 'now') ? true : false; + } + else + { + $s_checked = ($always_now) ? true : false; + } + + $options = array( + 0 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)), + 1 => array('TITLE' => $this->user->lang['ALWAYS_TODAY'], 'FIELD' => '<label><input type="radio" class="radio" name="always_now" value="1"' . (($s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['YES'] . '</label><label><input type="radio" class="radio" name="always_now" value="0"' . ((!$s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['NO'] . '</label>'), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 10, + 'field_minlen' => 10, + 'field_maxlen' => 10, + 'field_validation' => '', + 'field_novalue' => ' 0- 0- 0', + 'field_default_value' => ' 0- 0- 0', + ); + } + + /** + * {@inheritDoc} + */ + public function get_default_field_value($field_data) + { + if ($field_data['field_default_value'] == 'now') + { + $now = getdate(); + $field_data['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); + } + + return $field_data['field_default_value']; + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + + if (!$this->request->is_set($var_name . '_day')) + { + if ($profile_row['field_default_value'] == 'now') + { + $now = getdate(); + $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); + } + list($day, $month, $year) = explode('-', $profile_row['field_default_value']); + } + else + { + $day = $this->request->variable($var_name . '_day', 0); + $month = $this->request->variable($var_name . '_month', 0); + $year = $this->request->variable($var_name . '_year', 0); + } + + return sprintf('%2d-%2d-%4d', $day, $month, $year); + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + $field_validate = explode('-', $field_value); + + $day = (isset($field_validate[0])) ? (int) $field_validate[0] : 0; + $month = (isset($field_validate[1])) ? (int) $field_validate[1] : 0; + $year = (isset($field_validate[2])) ? (int) $field_validate[2] : 0; + + if ((!$day || !$month || !$year) && !$field_data['field_required']) + { + return false; + } + + if ((!$day || !$month || !$year) && $field_data['field_required']) + { + return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); + } + + if ($day < 0 || $day > 31 || $month < 0 || $month > 12 || ($year < 1901 && $year > 0) || $year > gmdate('Y', time()) + 50) + { + return $this->user->lang('FIELD_INVALID_DATE', $this->get_field_name($field_data['lang_name'])); + } + + if (checkdate($month, $day, $year) === false) + { + return $this->user->lang('FIELD_INVALID_DATE', $this->get_field_name($field_data['lang_name'])); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + $date = explode('-', $field_value); + $day = (isset($date[0])) ? (int) $date[0] : 0; + $month = (isset($date[1])) ? (int) $date[1] : 0; + $year = (isset($date[2])) ? (int) $date[2] : 0; + + if (!$day && !$month && !$year && !$field_data['field_show_novalue']) + { + return null; + } + else if ($day && $month && $year) + { + // Date should display as the same date for every user regardless of timezone + return $this->user->create_datetime() + ->setDate($year, $month, $day) + ->setTime(0, 0, 0) + ->format($this->user->lang['DATE_FORMAT'], true); + } + + return $field_value; + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + + $now = getdate(); + + if (!$this->request->is_set($profile_row['field_ident'] . '_day')) + { + if ($profile_row['field_default_value'] == 'now') + { + $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); + } + list($day, $month, $year) = explode('-', ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $profile_row['field_default_value'] : $this->user->profile_fields[$field_ident])); + } + else + { + if ($preview_options !== false && $profile_row['field_default_value'] == 'now') + { + $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); + list($day, $month, $year) = explode('-', ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $profile_row['field_default_value'] : $this->user->profile_fields[$field_ident])); + } + else + { + $day = $this->request->variable($profile_row['field_ident'] . '_day', 0); + $month = $this->request->variable($profile_row['field_ident'] . '_month', 0); + $year = $this->request->variable($profile_row['field_ident'] . '_year', 0); + } + } + + $profile_row['s_day_options'] = '<option value="0"' . ((!$day) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 32; $i++) + { + $profile_row['s_day_options'] .= '<option value="' . $i . '"' . (($i == $day) ? ' selected="selected"' : '') . ">$i</option>"; + } + + $profile_row['s_month_options'] = '<option value="0"' . ((!$month) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 13; $i++) + { + $profile_row['s_month_options'] .= '<option value="' . $i . '"' . (($i == $month) ? ' selected="selected"' : '') . ">$i</option>"; + } + + $profile_row['s_year_options'] = '<option value="0"' . ((!$year) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = $now['year'] - 100; $i <= $now['year'] + 100; $i++) + { + $profile_row['s_year_options'] .= '<option value="' . $i . '"' . (($i == $year) ? ' selected="selected"' : '') . ">$i</option>"; + } + + $profile_row['field_value'] = 0; + $this->template->assign_block_vars('date', array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * {@inheritDoc} + */ + public function get_field_ident($field_data) + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'VCHAR:10'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 2 && $key == 'field_default_value') + { + $always_now = $this->request->variable('always_now', -1); + + if ($always_now == 1 || ($always_now === -1 && $current_value == 'now')) + { + $now = getdate(); + + $field_data['field_default_value_day'] = $now['mday']; + $field_data['field_default_value_month'] = $now['mon']; + $field_data['field_default_value_year'] = $now['year']; + $current_value = 'now'; + $this->request->overwrite('field_default_value', $current_value, \phpbb\request\request_interface::POST); + } + else + { + if ($this->request->is_set('field_default_value_day')) + { + $field_data['field_default_value_day'] = $this->request->variable('field_default_value_day', 0); + $field_data['field_default_value_month'] = $this->request->variable('field_default_value_month', 0); + $field_data['field_default_value_year'] = $this->request->variable('field_default_value_year', 0); + $current_value = sprintf('%2d-%2d-%4d', $field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']); + $this->request->overwrite('field_default_value', $current_value, \phpbb\request\request_interface::POST); + } + else + { + list($field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']) = explode('-', $current_value); + } + } + + return $current_value; + } + + return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); + } + + /** + * {@inheritDoc} + */ + public function prepare_hidden_fields($step, $key, $action, &$field_data) + { + if ($key == 'field_default_value') + { + $always_now = $this->request->variable('always_now', 0); + + if ($always_now) + { + return 'now'; + } + else if ($this->request->is_set('field_default_value_day')) + { + $field_data['field_default_value_day'] = $this->request->variable('field_default_value_day', 0); + $field_data['field_default_value_month'] = $this->request->variable('field_default_value_month', 0); + $field_data['field_default_value_year'] = $this->request->variable('field_default_value_year', 0); + return sprintf('%2d-%2d-%4d', $field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']); + } + } + + return parent::prepare_hidden_fields($step, $key, $action, $field_data); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_dropdown.php b/phpBB/phpbb/profilefields/type/type_dropdown.php new file mode 100644 index 0000000000..bcf0ba05f9 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_dropdown.php @@ -0,0 +1,297 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_dropdown extends type_base +{ + /** + * Profile fields language helper + * @var \phpbb\profilefields\lang_helper + */ + protected $lang_helper; + + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\profilefields\lang_helper $lang_helper Profile fields language helper + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\profilefields\lang_helper $lang_helper, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->lang_helper = $lang_helper; + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'dropdown'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $profile_row[0] = array( + 'var_name' => 'field_default_value', + 'field_id' => 1, + 'lang_name' => $field_data['lang_name'], + 'lang_explain' => $field_data['lang_explain'], + 'lang_id' => $default_lang_id, + 'field_default_value' => $field_data['field_default_value'], + 'field_ident' => 'field_default_value', + 'field_type' => $this->get_service_name(), + 'lang_options' => $field_data['lang_options'], + ); + + $profile_row[1] = $profile_row[0]; + $profile_row[1]['var_name'] = 'field_novalue'; + $profile_row[1]['field_ident'] = 'field_novalue'; + $profile_row[1]['field_default_value'] = $field_data['field_novalue']; + + $options = array( + 0 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row[0])), + 1 => array('TITLE' => $this->user->lang['NO_VALUE_OPTION'], 'EXPLAIN' => $this->user->lang['NO_VALUE_OPTION_EXPLAIN'], 'FIELD' => $this->process_field_row('preview', $profile_row[1])), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 0, + 'field_minlen' => 0, + 'field_maxlen' => 5, + 'field_validation' => '', + 'field_novalue' => 0, + 'field_default_value' => 0, + ); + } + + /** + * {@inheritDoc} + */ + public function get_default_field_value($field_data) + { + return $field_data['field_default_value']; + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + return $this->request->variable($var_name, (int) $profile_row['field_default_value']); + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + $field_value = (int) $field_value; + + // retrieve option lang data if necessary + if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], 1)) + { + $this->lang_helper->get_option_lang($field_data['field_id'], $field_data['lang_id'], $this->get_service_name(), false); + } + + if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], $field_value)) + { + return $this->user->lang('FIELD_INVALID_VALUE', $this->get_field_name($field_data['lang_name'])); + } + + if ($field_value == $field_data['field_novalue'] && $field_data['field_required']) + { + return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + $field_id = $field_data['field_id']; + $lang_id = $field_data['lang_id']; + if (!$this->lang_helper->is_set($field_id, $lang_id)) + { + $this->lang_helper->get_option_lang($field_id, $lang_id, $this->get_service_name(), false); + } + + if ($field_value == $field_data['field_novalue'] && !$field_data['field_show_novalue']) + { + return null; + } + + $field_value = (int) $field_value; + + // User not having a value assigned + if (!$this->lang_helper->is_set($field_id, $lang_id, $field_value)) + { + if ($field_data['field_show_novalue']) + { + $field_value = $field_data['field_novalue']; + } + else + { + return null; + } + } + + return $this->lang_helper->get($field_id, $lang_id, $field_value); + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + $default_value = $profile_row['field_default_value']; + + $value = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]); + + if (!$this->lang_helper->is_set($profile_row['field_id'], $profile_row['lang_id'], 1)) + { + $this->lang_helper->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], $this->get_service_name(), $preview_options); + } + + $profile_row['field_value'] = (int) $value; + $this->template->assign_block_vars('dropdown', array_change_key_case($profile_row, CASE_UPPER)); + + $options = $this->lang_helper->get($profile_row['field_id'], $profile_row['lang_id']); + foreach ($options as $option_id => $option_value) + { + $this->template->assign_block_vars('dropdown.options', array( + 'OPTION_ID' => $option_id, + 'SELECTED' => ($value == $option_id) ? ' selected="selected"' : '', + 'VALUE' => $option_value, + )); + } + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'UINT'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + 'lang_options' => 'optionfield', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function prepare_options_form(&$exclude_options, &$visibility_options) + { + $exclude_options[1][] = 'lang_options'; + + return $this->request->variable('lang_options', '', true); + } + + /** + * {@inheritDoc} + */ + public function validate_options_on_submit($error, $field_data) + { + if (!sizeof($field_data['lang_options'])) + { + $error[] = $this->user->lang['NO_FIELD_ENTRIES']; + } + + return $error; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 2 && $key == 'field_maxlen') + { + // Get the number of options if this key is 'field_maxlen' + return sizeof(explode("\n", $this->request->variable('lang_options', '', true))); + } + + return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); + } + + /** + * {@inheritDoc} + */ + public function display_options(&$template_vars, &$field_data) + { + // Initialize these array elements if we are creating a new field + if (!sizeof($field_data['lang_options'])) + { + // No options have been defined for the dropdown menu + $field_data['lang_options'] = array(); + } + + $template_vars = array_merge($template_vars, array( + 'S_DROPDOWN' => true, + 'L_LANG_OPTIONS_EXPLAIN' => $this->user->lang['DROPDOWN_ENTRIES_EXPLAIN'], + 'LANG_OPTIONS' => implode("\n", $field_data['lang_options']), + )); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_int.php b/phpBB/phpbb/profilefields/type/type_int.php new file mode 100644 index 0000000000..c98c863e13 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_int.php @@ -0,0 +1,234 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_int extends type_base +{ + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'int'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $options = array( + 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'), + 1 => array('TITLE' => $this->user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'), + 2 => array('TITLE' => $this->user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'), + 3 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => '<input type="number" name="field_default_value" value="' . $field_data['field_default_value'] . '" />'), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 5, + 'field_minlen' => 0, + 'field_maxlen' => 100, + 'field_validation' => '', + 'field_novalue' => 0, + 'field_default_value' => 0, + ); + } + + /** + * {@inheritDoc} + */ + public function get_default_field_value($field_data) + { + if ($field_data['field_default_value'] === '') + { + // We cannot insert an empty string into an integer column. + return null; + } + + return $field_data['field_default_value']; + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + if ($this->request->is_set($var_name) && $this->request->variable($var_name, '') === '') + { + return null; + } + else + { + return $this->request->variable($var_name, (int) $profile_row['field_default_value']); + } + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + if (trim($field_value) === '' && !$field_data['field_required']) + { + return false; + } + + $field_value = (int) $field_value; + + if ($field_value < $field_data['field_minlen']) + { + return $this->user->lang('FIELD_TOO_SMALL', (int) $field_data['field_minlen'], $this->get_field_name($field_data['lang_name'])); + } + else if ($field_value > $field_data['field_maxlen']) + { + return $this->user->lang('FIELD_TOO_LARGE', (int) $field_data['field_maxlen'], $this->get_field_name($field_data['lang_name'])); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + if (($field_value === '' || $field_value === null) && !$field_data['field_show_novalue']) + { + return null; + } + return (int) $field_value; + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + $default_value = $profile_row['field_default_value']; + + if ($this->request->is_set($field_ident)) + { + $value = ($this->request->variable($field_ident, '') === '') ? null : $this->request->variable($field_ident, $default_value); + } + else + { + if ($preview_options === false && array_key_exists($field_ident, $this->user->profile_fields) && is_null($this->user->profile_fields[$field_ident])) + { + $value = null; + } + else if (!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) + { + $value = $default_value; + } + else + { + $value = $this->user->profile_fields[$field_ident]; + } + } + + $profile_row['field_value'] = (is_null($value) || $value === '') ? '' : (int) $value; + + $this->template->assign_block_vars('int', array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * {@inheritDoc} + */ + public function get_field_ident($field_data) + { + return 'pf_' . $field_data['field_ident']; + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'BINT'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 2 && $key == 'field_default_value') + { + // Permit an empty string + if ($action == 'create' && $this->request->variable('field_default_value', '') === '') + { + return ''; + } + } + + return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_interface.php b/phpBB/phpbb/profilefields/type/type_interface.php new file mode 100644 index 0000000000..a1c3d879c8 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_interface.php @@ -0,0 +1,205 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +interface type_interface +{ + /** + * Get the translated name of the type + * + * @return string Translated name of the field type + */ + public function get_name(); + + /** + * Get the short name of the type, used for error messages and template loops + * + * @return string lowercase version of the fields type + */ + public function get_name_short(); + + /** + * Get the name of service representing the type + * + * @return string lowercase version of the fields type + */ + public function get_service_name(); + + /** + * Get the name of template file for this type + * + * @return string Returns the name of the template file + */ + public function get_template_filename(); + + /** + * Get dropdown options for second step in ACP + * + * @param string $default_lang_id ID of the default language + * @param array $field_data Array with data for this field + * @return array with the acp options + */ + public function get_options($default_lang_id, $field_data); + + /** + * Get default values for the options of this type + * + * @return array with values like default field size and more + */ + public function get_default_option_values(); + + /** + * Get default value for this type + * + * @param array $field_data Array with data for this field + * @return mixed default value for new users when no value is given + */ + public function get_default_field_value($field_data); + + /** + * Get profile field value on submit + * + * @param array $profile_row Array with data for this field + * @return mixed Submitted value of the profile field + */ + public function get_profile_field($profile_row); + + /** + * Validate entered profile field data + * + * @param mixed $field_value Field value to validate + * @param array $field_data Array with requirements of the field + * @return mixed String with the error message + */ + public function validate_profile_field(&$field_value, $field_data); + + /** + * Get Profile Value for display + * + * @param mixed $field_value Field value as stored in the database + * @param array $field_data Array with requirements of the field + * @return mixed Field value to display + */ + public function get_profile_value($field_value, $field_data); + + /** + * Get Profile Value for display + * + * When displaying a contact field, we don't want to have links already parsed and more + * + * @param mixed $field_value Field value as stored in the database + * @param array $field_data Array with requirements of the field + * @return mixed Field value to display + */ + public function get_profile_contact_value($field_value, $field_data); + + /** + * Generate the input field for display + * + * @param array $profile_row Array with data for this field + * @param mixed $preview_options When previewing we use different data + * @return null + */ + public function generate_field($profile_row, $preview_options = false); + + /** + * Get the ident of the field + * + * Some types are multivalue, we can't give them a field_id + * as we would not know which to pick. + * + * @param array $field_data Array with data for this field + * @return string ident of the field + */ + public function get_field_ident($field_data); + + /** + * Get the column type for the database + * + * @return string Returns the database column type + */ + public function get_database_column_type(); + + /** + * Get the options we need to display for the language input fields in the ACP + * + * @param array $field_data Array with data for this field + * @return array Returns the language options we need to generate + */ + public function get_language_options($field_data); + + /** + * Get the input for the supplied language options + * + * @param array $field_data Array with data for this field + * @return array Returns the language options we need to generate + */ + public function get_language_options_input($field_data); + + /** + * Allows exclusion of options in single steps of the creation process + * + * @param array $exclude_options Array with options that should be excluded in the steps + * @param array $visibility_options Array with options responsible for the fields visibility + * @return mixed Returns the provided language options + */ + public function prepare_options_form(&$exclude_options, &$visibility_options); + + /** + * Allows exclusion of options in single steps of the creation process + * + * @param array $error Array with error messages + * @param array $field_data Array with data for this field + * @return array Array with error messages + */ + public function validate_options_on_submit($error, $field_data); + + /** + * Allows manipulating the intended variables if needed + * + * @param string $key Name of the option + * @param string $action Currently performed action (create|edit) + * @param mixed $current_value Currently value of the option + * @param array $field_data Array with data for this field + * @param int $step Step on which the option is excluded + * @return mixed Final value of the option + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step); + + /** + * Allows manipulating the intended variables if needed + * + * @param string $key Name of the option + * @param int $step Step on which the option is hidden + * @param string $action Currently performed action (create|edit) + * @param array $field_data Array with data for this field + * @return mixed Final value of the option + */ + public function prepare_hidden_fields($step, $key, $action, &$field_data); + + /** + * Allows assigning of additional template variables + * + * @param array $template_vars Template variables we are going to assign + * @param array $field_data Array with data for this field + * @return null + */ + public function display_options(&$template_vars, &$field_data); + + /** + * Return templated value/field. Possible values for $mode are: + * change == user is able to set/enter profile values; preview == just show the value + * + * @param string $mode Mode for displaying the field (preview|change) + * @param array $profile_row Array with data for this field + * @return null + */ + public function process_field_row($mode, $profile_row); +} diff --git a/phpBB/phpbb/profilefields/type/type_string.php b/phpBB/phpbb/profilefields/type/type_string.php new file mode 100644 index 0000000000..9dada592eb --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_string.php @@ -0,0 +1,156 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_string extends type_string_common +{ + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'string'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $options = array( + 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'), + 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'), + 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'), + 3 => array('TITLE' => $this->user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options($field_data) . '</select>'), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 10, + 'field_minlen' => 0, + 'field_maxlen' => 20, + 'field_validation' => '.*', + 'field_novalue' => '', + 'field_default_value' => '', + ); + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + return $this->request->variable($var_name, (string) $profile_row['field_default_value'], true); + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + return $this->validate_string_profile_field('string', $field_value, $field_data); + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + $default_value = $profile_row['lang_default_value']; + $profile_row['field_value'] = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value, true) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]); + + $this->template->assign_block_vars($this->get_name_short(), array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'VCHAR'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + if (strlen($field_data['lang_default_value'])) + { + $options['lang_default_value'] = 'string'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function display_options(&$template_vars, &$field_data) + { + $template_vars = array_merge($template_vars, array( + 'S_STRING' => true, + 'L_DEFAULT_VALUE_EXPLAIN' => $this->user->lang['STRING_DEFAULT_VALUE_EXPLAIN'], + 'LANG_DEFAULT_VALUE' => $field_data['lang_default_value'], + )); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_string_common.php b/phpBB/phpbb/profilefields/type/type_string_common.php new file mode 100644 index 0000000000..78e219a61f --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_string_common.php @@ -0,0 +1,128 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +abstract class type_string_common extends type_base +{ + protected $validation_options = array( + 'CHARS_ANY' => '.*', + 'NUMBERS_ONLY' => '[0-9]+', + 'ALPHA_ONLY' => '[\w]+', + 'ALPHA_UNDERSCORE' => '[\w_]+', + 'ALPHA_SPACERS' => '[\w_\+\. \-\[\]]+', + ); + + /** + * Return possible validation options + */ + public function validate_options($field_data) + { + $validate_options = ''; + foreach ($this->validation_options as $lang => $value) + { + $selected = ($field_data['field_validation'] == $value) ? ' selected="selected"' : ''; + $validate_options .= '<option value="' . $value . '"' . $selected . '>' . $this->user->lang[$lang] . '</option>'; + } + + return $validate_options; + } + + /** + * {@inheritDoc} + */ + public function get_default_field_value($field_data) + { + return $field_data['lang_default_value']; + } + + /** + * Validate entered profile field data + * + * @param string $field_type Field type (string or text) + * @param mixed $field_value Field value to validate + * @param array $field_data Array with requirements of the field + * @return mixed String with key of the error language string, false otherwise + */ + public function validate_string_profile_field($field_type, &$field_value, $field_data) + { + if (trim($field_value) === '' && !$field_data['field_required']) + { + return false; + } + else if (trim($field_value) === '' && $field_data['field_required']) + { + return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); + } + + if ($field_data['field_minlen'] && utf8_strlen($field_value) < $field_data['field_minlen']) + { + return $this->user->lang('FIELD_TOO_SHORT', (int) $field_data['field_minlen'], $this->get_field_name($field_data['lang_name'])); + } + else if ($field_data['field_maxlen'] && utf8_strlen(html_entity_decode($field_value)) > $field_data['field_maxlen']) + { + return $this->user->lang('FIELD_TOO_LONG', (int) $field_data['field_maxlen'], $this->get_field_name($field_data['lang_name'])); + } + + if (!empty($field_data['field_validation']) && $field_data['field_validation'] != '.*') + { + $field_validate = ($field_type != 'text') ? $field_value : bbcode_nl2br($field_value); + if (!preg_match('#^' . str_replace('\\\\', '\\', $field_data['field_validation']) . '$#i', $field_validate)) + { + $validation = array_search($field_data['field_validation'], $this->validation_options); + if ($validation) + { + return $this->user->lang('FIELD_INVALID_CHARS_' . $validation, $this->get_field_name($field_data['lang_name'])); + } + return $this->user->lang('FIELD_INVALID_CHARS_INVALID', $this->get_field_name($field_data['lang_name'])); + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + if (!$field_value && !$field_data['field_show_novalue']) + { + return null; + } + + $field_value = make_clickable($field_value); + $field_value = censor_text($field_value); + $field_value = bbcode_nl2br($field_value); + return $field_value; + } + + /** + * {@inheritDoc} + */ + public function get_profile_contact_value($field_value, $field_data) + { + if (!$field_value && !$field_data['field_show_novalue']) + { + return null; + } + + return $field_value; + } + + /** + * {@inheritDoc} + */ + public function prepare_options_form(&$exclude_options, &$visibility_options) + { + $exclude_options[1][] = 'lang_default_value'; + + return $this->request->variable('lang_options', '', true); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_text.php b/phpBB/phpbb/profilefields/type/type_text.php new file mode 100644 index 0000000000..660bb20ef8 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_text.php @@ -0,0 +1,201 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_text extends type_string_common +{ + /** + * Request object + * @var \phpbb\request\request + */ + protected $request; + + /** + * Template object + * @var \phpbb\template\template + */ + protected $template; + + /** + * User object + * @var \phpbb\user + */ + protected $user; + + /** + * Construct + * + * @param \phpbb\request\request $request Request object + * @param \phpbb\template\template $template Template object + * @param \phpbb\user $user User object + * @param string $language_table Table where the language strings are stored + */ + public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) + { + $this->request = $request; + $this->template = $template; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'text'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $options = array( + 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="rows" size="5" value="' . $field_data['rows'] . '" /> ' . $this->user->lang['ROWS'] . '</dd><dd><input type="number" min="0" max="99999" name="columns" size="5" value="' . $field_data['columns'] . '" /> ' . $this->user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $field_data['field_length'] . '" />'), + 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_minlen" size="10" value="' . $field_data['field_minlen'] . '" />'), + 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_maxlen" size="10" value="' . $field_data['field_maxlen'] . '" />'), + 3 => array('TITLE' => $this->user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options($field_data) . '</select>'), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => '5|80', + 'field_minlen' => 0, + 'field_maxlen' => 1000, + 'field_validation' => '.*', + 'field_novalue' => '', + 'field_default_value' => '', + ); + } + + /** + * {@inheritDoc} + */ + public function get_profile_field($profile_row) + { + $var_name = 'pf_' . $profile_row['field_ident']; + return $this->request->variable($var_name, (string) $profile_row['field_default_value'], true); + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + return $this->validate_string_profile_field('text', $field_value, $field_data); + } + + /** + * {@inheritDoc} + */ + public function generate_field($profile_row, $preview_options = false) + { + $field_length = explode('|', $profile_row['field_length']); + $profile_row['field_rows'] = $field_length[0]; + $profile_row['field_cols'] = $field_length[1]; + $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; + $field_ident = $profile_row['field_ident']; + $default_value = $profile_row['lang_default_value']; + + $profile_row['field_value'] = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value, true) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]); + + $this->template->assign_block_vars('text', array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * {@inheritDoc} + */ + public function get_database_column_type() + { + return 'MTEXT'; + } + + /** + * {@inheritDoc} + */ + public function get_language_options($field_data) + { + $options = array( + 'lang_name' => 'string', + ); + + if ($field_data['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + if (strlen($field_data['lang_default_value'])) + { + $options['lang_default_value'] = 'text'; + } + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_excluded_options($key, $action, $current_value, &$field_data, $step) + { + if ($step == 2 && $key == 'field_length') + { + if ($this->request->is_set('rows')) + { + $field_data['rows'] = $this->request->variable('rows', 0); + $field_data['columns'] = $this->request->variable('columns', 0); + $current_value = $field_data['rows'] . '|' . $field_data['columns']; + } + else + { + $row_col = explode('|', $current_value); + $field_data['rows'] = $row_col[0]; + $field_data['columns'] = $row_col[1]; + } + + return $current_value; + } + + return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); + } + + /** + * {@inheritDoc} + */ + public function prepare_hidden_fields($step, $key, $action, &$field_data) + { + if ($key == 'field_length' && $this->request->is_set('rows')) + { + $field_data['rows'] = $this->request->variable('rows', 0); + $field_data['columns'] = $this->request->variable('columns', 0); + return $field_data['rows'] . '|' . $field_data['columns']; + } + + return parent::prepare_hidden_fields($step, $key, $action, $field_data); + } + + /** + * {@inheritDoc} + */ + public function display_options(&$template_vars, &$field_data) + { + $template_vars = array_merge($template_vars, array( + 'S_TEXT' => true, + 'L_DEFAULT_VALUE_EXPLAIN' => $this->user->lang['TEXT_DEFAULT_VALUE_EXPLAIN'], + 'LANG_DEFAULT_VALUE' => $field_data['lang_default_value'], + )); + } +} diff --git a/phpBB/phpbb/profilefields/type/type_url.php b/phpBB/phpbb/profilefields/type/type_url.php new file mode 100644 index 0000000000..b1523b9355 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_url.php @@ -0,0 +1,70 @@ +<?php +/** +* +* @package phpBB +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\profilefields\type; + +class type_url extends type_string +{ + /** + * {@inheritDoc} + */ + public function get_name_short() + { + return 'url'; + } + + /** + * {@inheritDoc} + */ + public function get_options($default_lang_id, $field_data) + { + $options = array( + 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'), + 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'), + 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'), + ); + + return $options; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 40, + 'field_minlen' => 0, + 'field_maxlen' => 200, + 'field_validation' => '', + 'field_novalue' => '', + 'field_default_value' => '', + ); + } + + /** + * {@inheritDoc} + */ + public function validate_profile_field(&$field_value, $field_data) + { + $field_value = trim($field_value); + + if ($field_value === '' && !$field_data['field_required']) + { + return false; + } + + if (!preg_match('#^' . get_preg_expression('url') . '$#i', $field_value)) + { + return $this->user->lang('FIELD_INVALID_URL', $this->get_field_name($field_data['lang_name'])); + } + + return false; + } +} diff --git a/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php b/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php new file mode 100644 index 0000000000..6ef63ec906 --- /dev/null +++ b/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php @@ -0,0 +1,28 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb; + +/** +* Class recursive_dot_prefix_filter_iterator +* +* This filter ignores directories starting with a dot. +* When searching for php classes and template files of extensions +* we don't need to look inside these directories. +* +* @package phpbb +*/ +class recursive_dot_prefix_filter_iterator extends \RecursiveFilterIterator +{ + public function accept() + { + $filename = $this->current()->getFilename(); + return !$this->current()->isDir() || $filename[0] !== '.'; + } +} diff --git a/phpBB/phpbb/request/deactivated_super_global.php b/phpBB/phpbb/request/deactivated_super_global.php index cc05847ec7..b6940cf51f 100644 --- a/phpBB/phpbb/request/deactivated_super_global.php +++ b/phpBB/phpbb/request/deactivated_super_global.php @@ -1,27 +1,21 @@ <?php /** * -* @package phpbb_request +* @package \phpbb\request\request * @copyright (c) 2010 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\request; /** * Replacement for a superglobal (like $_GET or $_POST) which calls * trigger_error on all operations but isset, overloads the [] operator with SPL. * -* @package phpbb_request +* @package \phpbb\request\request */ -class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, IteratorAggregate +class deactivated_super_global implements \ArrayAccess, \Countable, \IteratorAggregate { /** * @var string Holds the name of the superglobal this is replacing. @@ -29,23 +23,23 @@ class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, private $name; /** - * @var phpbb_request_interface::POST|GET|REQUEST|COOKIE Super global constant. + * @var \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE Super global constant. */ private $super_global; /** - * @var phpbb_request_interface The request class instance holding the actual request data. + * @var \phpbb\request\request_interface The request class instance holding the actual request data. */ private $request; /** * Constructor generates an error message fitting the super global to be used within the other functions. * - * @param phpbb_request_interface $request A request class instance holding the real super global data. + * @param \phpbb\request\request_interface $request A request class instance holding the real super global data. * @param string $name Name of the super global this is a replacement for - e.g. '_GET'. - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global The variable's super global constant. + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global The variable's super global constant. */ - public function __construct(phpbb_request_interface $request, $name, $super_global) + public function __construct(\phpbb\request\request_interface $request, $name, $super_global) { $this->request = $request; $this->name = $name; @@ -84,7 +78,7 @@ class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, } /**#@+ - * Part of the ArrayAccess implementation, will always result in a FATAL error. + * Part of the \ArrayAccess implementation, will always result in a FATAL error. */ public function offsetGet($offset) { @@ -103,7 +97,7 @@ class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, /**#@-*/ /** - * Part of the Countable implementation, will always result in a FATAL error + * Part of the \Countable implementation, will always result in a FATAL error */ public function count() { @@ -118,4 +112,3 @@ class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, $this->error(); } } - diff --git a/phpBB/phpbb/request/request.php b/phpBB/phpbb/request/request.php index ae3c526d89..3171a6edb7 100644 --- a/phpBB/phpbb/request/request.php +++ b/phpBB/phpbb/request/request.php @@ -1,19 +1,13 @@ <?php /** * -* @package phpbb_request +* @package \phpbb\request\request * @copyright (c) 2010 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\request; /** * All application input is accessed through this class. @@ -21,20 +15,20 @@ if (!defined('IN_PHPBB')) * It provides a method to disable access to input data through super globals. * This should force MOD authors to read about data validation. * -* @package phpbb_request +* @package \phpbb\request\request */ -class phpbb_request implements phpbb_request_interface +class request implements \phpbb\request\request_interface { /** * @var array The names of super global variables that this class should protect if super globals are disabled. */ protected $super_globals = array( - phpbb_request_interface::POST => '_POST', - phpbb_request_interface::GET => '_GET', - phpbb_request_interface::REQUEST => '_REQUEST', - phpbb_request_interface::COOKIE => '_COOKIE', - phpbb_request_interface::SERVER => '_SERVER', - phpbb_request_interface::FILES => '_FILES', + \phpbb\request\request_interface::POST => '_POST', + \phpbb\request\request_interface::GET => '_GET', + \phpbb\request\request_interface::REQUEST => '_REQUEST', + \phpbb\request\request_interface::COOKIE => '_COOKIE', + \phpbb\request\request_interface::SERVER => '_SERVER', + \phpbb\request\request_interface::FILES => '_FILES', ); /** @@ -53,15 +47,15 @@ class phpbb_request implements phpbb_request_interface protected $input; /** - * @var phpbb_request_type_cast_helper_interface An instance of a type cast helper providing convenience methods for type conversions. + * @var \phpbb\request\type_cast_helper_interface An instance of a type cast helper providing convenience methods for type conversions. */ protected $type_cast_helper; /** * Initialises the request class, that means it stores all input data in {@link $input input} - * and then calls {@link phpbb_request_deactivated_super_global phpbb_request_deactivated_super_global} + * and then calls {@link \phpbb\request\deactivated_super_global \phpbb\request\deactivated_super_global} */ - public function __construct(phpbb_request_type_cast_helper_interface $type_cast_helper = null, $disable_super_globals = true) + public function __construct(\phpbb\request\type_cast_helper_interface $type_cast_helper = null, $disable_super_globals = true) { if ($type_cast_helper) { @@ -69,7 +63,7 @@ class phpbb_request implements phpbb_request_interface } else { - $this->type_cast_helper = new phpbb_request_type_cast_helper(); + $this->type_cast_helper = new \phpbb\request\type_cast_helper(); } foreach ($this->super_globals as $const => $super_global) @@ -78,8 +72,8 @@ class phpbb_request implements phpbb_request_interface } // simulate request_order = GP - $this->original_request = $this->input[phpbb_request_interface::REQUEST]; - $this->input[phpbb_request_interface::REQUEST] = $this->input[phpbb_request_interface::POST] + $this->input[phpbb_request_interface::GET]; + $this->original_request = $this->input[\phpbb\request\request_interface::REQUEST]; + $this->input[\phpbb\request\request_interface::REQUEST] = $this->input[\phpbb\request\request_interface::POST] + $this->input[\phpbb\request\request_interface::GET]; if ($disable_super_globals) { @@ -99,7 +93,7 @@ class phpbb_request implements phpbb_request_interface /** * Disables access of super globals specified in $super_globals. - * This is achieved by overwriting the super globals with instances of {@link phpbb_request_deactivated_super_global phpbb_request_deactivated_super_global} + * This is achieved by overwriting the super globals with instances of {@link \phpbb\request\deactivated_super_global \phpbb\request\deactivated_super_global} */ public function disable_super_globals() { @@ -108,7 +102,7 @@ class phpbb_request implements phpbb_request_interface foreach ($this->super_globals as $const => $super_global) { unset($GLOBALS[$super_global]); - $GLOBALS[$super_global] = new phpbb_request_deactivated_super_global($this, $super_global, $const); + $GLOBALS[$super_global] = new \phpbb\request\deactivated_super_global($this, $super_global, $const); } $this->super_globals_disabled = true; @@ -144,10 +138,10 @@ class phpbb_request implements phpbb_request_interface * @param string $var_name The name of the variable that shall be overwritten * @param mixed $value The value which the variable shall contain. * If this is null the variable will be unset. - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global shall be changed */ - public function overwrite($var_name, $value, $super_global = phpbb_request_interface::REQUEST) + public function overwrite($var_name, $value, $super_global = \phpbb\request\request_interface::REQUEST) { if (!isset($this->super_globals[$super_global])) { @@ -193,13 +187,13 @@ class phpbb_request implements phpbb_request_interface * This function will always return a value of the same type as the default. * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global should be used * * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the * the same as that of $default. If the variable is not set $default is returned. */ - public function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST) + public function variable($var_name, $default, $multibyte = false, $super_global = \phpbb\request\request_interface::REQUEST) { return $this->_variable($var_name, $default, $multibyte, $super_global, true); } @@ -217,13 +211,13 @@ class phpbb_request implements phpbb_request_interface * This function will always return a value of the same type as the default. * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global should be used * * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the * the same as that of $default. If the variable is not set $default is returned. */ - public function untrimmed_variable($var_name, $default, $multibyte, $super_global = phpbb_request_interface::REQUEST) + public function untrimmed_variable($var_name, $default, $multibyte = false, $super_global = \phpbb\request\request_interface::REQUEST) { return $this->_variable($var_name, $default, $multibyte, $super_global, false); } @@ -234,8 +228,8 @@ class phpbb_request implements phpbb_request_interface * Also fall back to getenv(), some CGI setups may need it (probably not, but * whatever). * - * @param string|array $var_name See phpbb_request_interface::variable - * @param mixed $Default See phpbb_request_interface::variable + * @param string|array $var_name See \phpbb\request\request_interface::variable + * @param mixed $Default See \phpbb\request\request_interface::variable * * @return mixed The server variable value. */ @@ -243,9 +237,9 @@ class phpbb_request implements phpbb_request_interface { $multibyte = true; - if ($this->is_set($var_name, phpbb_request_interface::SERVER)) + if ($this->is_set($var_name, \phpbb\request\request_interface::SERVER)) { - return $this->variable($var_name, $default, $multibyte, phpbb_request_interface::SERVER); + return $this->variable($var_name, $default, $multibyte, \phpbb\request\request_interface::SERVER); } else { @@ -259,7 +253,7 @@ class phpbb_request implements phpbb_request_interface * Shortcut method to retrieve the value of client HTTP headers. * * @param string|array $header_name The name of the header to retrieve. - * @param mixed $default See phpbb_request_interface::variable + * @param mixed $default See \phpbb\request\request_interface::variable * * @return mixed The header value. */ @@ -279,7 +273,7 @@ class phpbb_request implements phpbb_request_interface */ public function file($form_name) { - return $this->variable($form_name, array('name' => 'none'), false, phpbb_request_interface::FILES); + return $this->variable($form_name, array('name' => 'none'), false, \phpbb\request\request_interface::FILES); } /** @@ -294,7 +288,7 @@ class phpbb_request implements phpbb_request_interface */ public function is_set_post($name) { - return $this->is_set($name, phpbb_request_interface::POST); + return $this->is_set($name, \phpbb\request\request_interface::POST); } /** @@ -302,12 +296,12 @@ class phpbb_request implements phpbb_request_interface * arrays. * * @param string $var Name of the variable - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies the super global which shall be checked * * @return bool True if the variable was sent as input */ - public function is_set($var, $super_global = phpbb_request_interface::REQUEST) + public function is_set($var, $super_global = \phpbb\request\request_interface::REQUEST) { return isset($this->input[$super_global][$var]); } @@ -335,13 +329,13 @@ class phpbb_request implements phpbb_request_interface /** * Returns all variable names for a given super global * - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * The super global from which names shall be taken * * @return array All variable names that are set for the super global. * Pay attention when using these, they are unsanitised! */ - public function variable_names($super_global = phpbb_request_interface::REQUEST) + public function variable_names($super_global = \phpbb\request\request_interface::REQUEST) { if (!isset($this->input[$super_global])) { @@ -362,14 +356,14 @@ class phpbb_request implements phpbb_request_interface * This function will always return a value of the same type as the default. * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global should be used * @param bool $trim Indicates whether trim() should be applied to string values. * * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the * the same as that of $default. If the variable is not set $default is returned. */ - protected function _variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST, $trim = true) + protected function _variable($var_name, $default, $multibyte = false, $super_global = \phpbb\request\request_interface::REQUEST, $trim = true) { $path = false; @@ -412,4 +406,12 @@ class phpbb_request implements phpbb_request_interface return $var; } + + /** + * {@inheritdoc} + */ + public function get_super_global($super_global = \phpbb\request\request_interface::REQUEST) + { + return $this->input[$super_global]; + } } diff --git a/phpBB/phpbb/request/interface.php b/phpBB/phpbb/request/request_interface.php index 741db35917..1f9978b276 100644 --- a/phpBB/phpbb/request/interface.php +++ b/phpBB/phpbb/request/request_interface.php @@ -1,26 +1,20 @@ <?php /** * -* @package phpbb_request +* @package \phpbb\request\request * @copyright (c) 2010 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\request; /** * An interface through which all application input can be accessed. * -* @package phpbb_request +* @package \phpbb\request\request */ -interface phpbb_request_interface +interface request_interface { /**#@+ * Constant identifying the super global with the same name. @@ -43,10 +37,10 @@ interface phpbb_request_interface * @param string $var_name The name of the variable that shall be overwritten * @param mixed $value The value which the variable shall contain. * If this is null the variable will be unset. - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global shall be changed */ - public function overwrite($var_name, $value, $super_global = phpbb_request_interface::REQUEST); + public function overwrite($var_name, $value, $super_global = \phpbb\request\request_interface::REQUEST); /** * Central type safe input handling function. @@ -60,19 +54,19 @@ interface phpbb_request_interface * This function will always return a value of the same type as the default. * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies which super global should be used * * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the * the same as that of $default. If the variable is not set $default is returned. */ - public function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST); + public function variable($var_name, $default, $multibyte = false, $super_global = \phpbb\request\request_interface::REQUEST); /** * Shortcut method to retrieve SERVER variables. * - * @param string|array $var_name See phpbb_request_interface::variable - * @param mixed $default See phpbb_request_interface::variable + * @param string|array $var_name See \phpbb\request\request_interface::variable + * @param mixed $default See \phpbb\request\request_interface::variable * * @return mixed The server variable value. */ @@ -82,7 +76,7 @@ interface phpbb_request_interface * Shortcut method to retrieve the value of client HTTP headers. * * @param string|array $header_name The name of the header to retrieve. - * @param mixed $default See phpbb_request_interface::variable + * @param mixed $default See \phpbb\request\request_interface::variable * * @return mixed The header value. */ @@ -105,12 +99,12 @@ interface phpbb_request_interface * arrays. * * @param string $var Name of the variable - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * Specifies the super global which shall be checked * * @return bool True if the variable was sent as input */ - public function is_set($var, $super_global = phpbb_request_interface::REQUEST); + public function is_set($var, $super_global = \phpbb\request\request_interface::REQUEST); /** * Checks whether the current request is an AJAX request (XMLHttpRequest) @@ -129,11 +123,21 @@ interface phpbb_request_interface /** * Returns all variable names for a given super global * - * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global * The super global from which names shall be taken * * @return array All variable names that are set for the super global. * Pay attention when using these, they are unsanitised! */ - public function variable_names($super_global = phpbb_request_interface::REQUEST); + public function variable_names($super_global = \phpbb\request\request_interface::REQUEST); + + /** + * Returns the original array of the requested super global + * + * @param \phpbb\request\request_interface::POST|GET|REQUEST|COOKIE $super_global + * The super global which will be returned + * + * @return array The original array of the requested super global. + */ + public function get_super_global($super_global = \phpbb\request\request_interface::REQUEST); } diff --git a/phpBB/phpbb/request/type_cast_helper.php b/phpBB/phpbb/request/type_cast_helper.php index 1a5274ed14..e9b55663af 100644 --- a/phpBB/phpbb/request/type_cast_helper.php +++ b/phpBB/phpbb/request/type_cast_helper.php @@ -1,26 +1,20 @@ <?php /** * -* @package phpbb_request +* @package \phpbb\request\request * @copyright (c) 2010 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\request; /** * A helper class that provides convenience methods for type casting. * -* @package phpbb_request +* @package \phpbb\request\request */ -class phpbb_request_type_cast_helper implements phpbb_request_type_cast_helper_interface +class type_cast_helper implements \phpbb\request\type_cast_helper_interface { /** diff --git a/phpBB/phpbb/request/type_cast_helper_interface.php b/phpBB/phpbb/request/type_cast_helper_interface.php index 3920d16fc7..f12795eef9 100644 --- a/phpBB/phpbb/request/type_cast_helper_interface.php +++ b/phpBB/phpbb/request/type_cast_helper_interface.php @@ -1,26 +1,20 @@ <?php /** * -* @package phpbb_request +* @package \phpbb\request\request * @copyright (c) 2010 phpBB Group * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\request; /** * An interface for type cast operations. * -* @package phpbb_request +* @package \phpbb\request\request */ -interface phpbb_request_type_cast_helper_interface +interface type_cast_helper_interface { /** * Recursively applies addslashes to a variable. diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/base.php index 914cef9167..9ecf3751d0 100644 --- a/phpBB/phpbb/search/base.php +++ b/phpBB/phpbb/search/base.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search; /** * @ignore @@ -23,12 +17,12 @@ define('SEARCH_RESULT_IN_CACHE', 1); define('SEARCH_RESULT_INCOMPLETE', 2); /** -* phpbb_search_base +* \phpbb\search\base * optional base class for search plugins providing simple caching based on ACM * and functions to retrieve ignore_words and synonyms * @package search */ -class phpbb_search_base +class base { var $ignore_words = array(); var $match_synonym = array(); diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index a1e1b089b9..e5b0c89cb6 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search; /** * fulltext_mysql * Fulltext search for MySQL * @package search */ -class phpbb_search_fulltext_mysql extends phpbb_search_base +class fulltext_mysql extends \phpbb\search\base { /** * Associative array holding index stats @@ -36,19 +30,19 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base /** * Config object - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; - + /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; - + /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; @@ -74,7 +68,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base /** * Constructor - * Creates a new phpbb_search_fulltext_mysql, which is used as a search backend + * Creates a new \phpbb\search\fulltext_mysql, which is used as a search backend * * @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false */ @@ -222,7 +216,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base // We limit the number of allowed keywords to minimize load on the database if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords']) { - trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], sizeof($this->split_words))); + trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], sizeof($this->split_words))); } // to allow phrase search, we need to concatenate quoted words @@ -779,7 +773,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base $alter[] = 'ADD FULLTEXT (post_subject)'; } - if (!isset($this->stats['post_text'])) + if (!isset($this->stats['post_content'])) { if ($this->db->sql_layer == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) { @@ -789,12 +783,8 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base { $alter[] = 'MODIFY post_text mediumtext NOT NULL'; } - $alter[] = 'ADD FULLTEXT (post_text)'; - } - if (!isset($this->stats['post_content'])) - { - $alter[] = 'ADD FULLTEXT post_content (post_subject, post_text)'; + $alter[] = 'ADD FULLTEXT post_content (post_text, post_subject)'; } if (sizeof($alter)) @@ -832,11 +822,6 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base $alter[] = 'DROP INDEX post_subject'; } - if (isset($this->stats['post_text'])) - { - $alter[] = 'DROP INDEX post_text'; - } - if (isset($this->stats['post_content'])) { $alter[] = 'DROP INDEX post_content'; @@ -862,7 +847,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base $this->get_stats(); } - return (isset($this->stats['post_text']) && isset($this->stats['post_subject']) && isset($this->stats['post_content'])) ? true : false; + return isset($this->stats['post_subject']) && isset($this->stats['post_content']); } /** @@ -902,11 +887,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base if ($index_type == 'FULLTEXT') { - if ($row['Key_name'] == 'post_text') - { - $this->stats['post_text'] = $row; - } - else if ($row['Key_name'] == 'post_subject') + if ($row['Key_name'] == 'post_subject') { $this->stats['post_subject'] = $row; } diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 730c3a6c2d..7d51d164c7 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search; /** * fulltext_native * phpBB's own db driven fulltext search, version 2 * @package search */ -class phpbb_search_fulltext_native extends phpbb_search_base +class fulltext_native extends \phpbb\search\base { /** * Associative array holding index stats @@ -80,19 +74,19 @@ class phpbb_search_fulltext_native extends phpbb_search_base /** * Config object - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; @@ -283,7 +277,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base // We limit the number of allowed keywords to minimize load on the database if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords']) { - trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], $num_keywords)); + trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], $num_keywords)); } // $keywords input format: each word separated by a space, words in a bracket are not separated @@ -331,7 +325,12 @@ class phpbb_search_fulltext_native extends phpbb_search_base } $this->db->sql_freeresult($result); } - unset($exact_words); + + // Handle +, - without preceeding whitespace character + $match = array('#(\S)\+#', '#(\S)-#'); + $replace = array('$1 +', '$1 +'); + + $keywords = preg_replace($match, $replace, $keywords); // now analyse the search query, first split it using the spaces $query = explode(' ', $keywords); @@ -457,39 +456,21 @@ class phpbb_search_fulltext_native extends phpbb_search_base $this->{$mode . '_ids'}[] = $words[$word]; } } - // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id) + else { if (!isset($common_ids[$word])) { $len = utf8_strlen($word); - if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) - { - trigger_error(sprintf($this->user->lang['WORD_IN_NO_POST'], $word)); - } - else + if ($len < $this->word_length['min'] || $len > $this->word_length['max']) { $this->common_words[] = $word; } } } - else - { - $len = utf8_strlen($word); - if ($len < $this->word_length['min'] || $len > $this->word_length['max']) - { - $this->common_words[] = $word; - } - } - } - - // we can't search for negatives only - if (!sizeof($this->must_contain_ids)) - { - return false; } - if (!empty($this->search_query)) + // Return true if all words are not common words + if (sizeof($exact_words) - sizeof($this->common_words) > 0) { return true; } @@ -524,6 +505,12 @@ class phpbb_search_fulltext_native extends phpbb_search_base return false; } + // we can't search for negatives only + if (empty($this->must_contain_ids)) + { + return false; + } + $must_contain_ids = $this->must_contain_ids; $must_not_contain_ids = $this->must_not_contain_ids; $must_exclude_one_ids = $this->must_exclude_one_ids; @@ -848,7 +835,6 @@ class phpbb_search_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) { @@ -1187,8 +1173,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base * we know that it will also be lower than CJK ranges */ if ((strncmp($word, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0) - && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0) - && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0)) + && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0) + && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0)) { $word = strtok(' '); continue; @@ -1556,7 +1542,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base * @param string $encoding Text encoding * @return string Cleaned up text, only alphanumeric chars are left * - * @todo normalizer::cleanup being able to be used? + * @todo \normalizer::cleanup being able to be used? */ protected function cleanup($text, $allowed_chars = null, $encoding = 'utf-8') { @@ -1588,7 +1574,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base * If we use it more widely, an instance of that class should be held in a * a global variable instead */ - utf_normalizer::nfc($text); + \utf_normalizer::nfc($text); /** * The first thing we do is: @@ -1682,8 +1668,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base $pos += $utf_len; if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST) - || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST) - || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST)) + || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST) + || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST)) { /** * All characters within these ranges are valid diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php index 6b4b310f2e..864a53e642 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/fulltext_postgres.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search; /** * fulltext_postgres * Fulltext search for PostgreSQL * @package search */ -class phpbb_search_fulltext_postgres extends phpbb_search_base +class fulltext_postgres extends \phpbb\search\base { /** * Associative array holding index stats @@ -61,19 +55,19 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base /** * Config object - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; @@ -99,7 +93,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base /** * Constructor - * Creates a new phpbb_search_fulltext_postgres, which is used as a search backend + * Creates a new \phpbb\search\fulltext_postgres, which is used as a search backend * * @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false */ @@ -463,15 +457,13 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $sql_where_options .= $sql_match_where; $tmp_sql_match = array(); - foreach (explode(',', $sql_match) as $sql_match_column) - { - $tmp_sql_match[] = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')"; - } + $sql_match = str_replace(',', " || ' ' ||", $sql_match); + $tmp_sql_match = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')"; $this->db->sql_transaction('begin'); $sql_from = "FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p"; - $sql_where = "WHERE (" . implode(' OR ', $tmp_sql_match) . ") + $sql_where = "WHERE (" . $tmp_sql_match . ") $sql_where_options"; $sql = "SELECT $sql_select $sql_from @@ -799,9 +791,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))"); } - if (!isset($this->stats['post_text'])) + if (!isset($this->stats['post_content'])) { - $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_text ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text))"); + $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))"); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); @@ -832,9 +824,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $this->db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']); } - if (isset($this->stats['post_text'])) + if (isset($this->stats['post_content'])) { - $this->db->sql_query('DROP INDEX ' . $this->stats['post_text']['relname']); + $this->db->sql_query('DROP INDEX ' . $this->stats['post_content']['relname']); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); @@ -852,7 +844,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $this->get_stats(); } - return (isset($this->stats['post_text']) && isset($this->stats['post_subject'])) ? true : false; + return (isset($this->stats['post_subject']) && isset($this->stats['post_content'])) ? true : false; } /** @@ -894,13 +886,13 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base // deal with older PostgreSQL versions which didn't use Index_type if (strpos($row['indexdef'], 'to_tsvector') !== false) { - if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_text' || $row['relname'] == POSTS_TABLE . '_post_text') + if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject') { - $this->stats['post_text'] = $row; + $this->stats['post_subject'] = $row; } - else if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject') + else if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_content' || $row['relname'] == POSTS_TABLE . '_post_content') { - $this->stats['post_subject'] = $row; + $this->stats['post_content'] = $row; } } } diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 4f3f852664..1501dcdc31 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -7,16 +7,8 @@ * */ -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search; -/** -* @ignore -*/ define('SPHINX_MAX_MATCHES', 20000); define('SPHINX_CONNECT_RETRIES', 3); define('SPHINX_CONNECT_WAIT_TIME', 300); @@ -26,7 +18,7 @@ define('SPHINX_CONNECT_WAIT_TIME', 300); * Fulltext search based on the sphinx search deamon * @package search */ -class phpbb_search_fulltext_sphinx +class fulltext_sphinx { /** * Associative array holding index stats @@ -73,25 +65,25 @@ class phpbb_search_fulltext_sphinx /** * Auth object - * @var phpbb_auth + * @var \phpbb\auth\auth */ protected $auth; /** * Config object - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * Database connection - * @var phpbb_db_driver + * @var \phpbb\db\driver\driver_interface */ protected $db; /** * Database Tools object - * @var phpbb_db_tools + * @var \phpbb\db\tools */ protected $db_tools; @@ -103,7 +95,7 @@ class phpbb_search_fulltext_sphinx /** * User object - * @var phpbb_user + * @var \phpbb\user */ protected $user; @@ -122,7 +114,7 @@ class phpbb_search_fulltext_sphinx /** * Constructor - * Creates a new phpbb_search_fulltext_postgres, which is used as a search backend + * Creates a new \phpbb\search\fulltext_postgres, which is used as a search backend * * @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false */ @@ -135,8 +127,8 @@ class phpbb_search_fulltext_sphinx $this->db = $db; $this->auth = $auth; - // Initialize phpbb_db_tools object - $this->db_tools = new phpbb_db_tools($this->db); + // Initialize \phpbb\db\tools object + $this->db_tools = new \phpbb\db\tools($this->db); if(!$this->config['fulltext_sphinx_id']) { @@ -151,7 +143,7 @@ class phpbb_search_fulltext_sphinx } // Initialize sphinx client - $this->sphinx = new SphinxClient(); + $this->sphinx = new \SphinxClient(); $this->sphinx->SetServer(($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost'), ($this->config['fulltext_sphinx_port'] ? (int) $this->config['fulltext_sphinx_port'] : 9312)); @@ -250,7 +242,7 @@ class phpbb_search_fulltext_sphinx /* Now that we're sure everything was entered correctly, generate a config for the index. We use a config value fulltext_sphinx_id for this, as it should be unique. */ - $config_object = new phpbb_search_sphinx_config($this->config_file_data); + $config_object = new \phpbb\search\sphinx\config($this->config_file_data); $config_data = array( 'source source_phpbb_' . $this->id . '_main' => array( array('type', $this->dbtype . ' # mysql or pgsql'), @@ -290,9 +282,9 @@ class phpbb_search_fulltext_sphinx array('sql_attr_uint', 'post_visibility'), array('sql_attr_bool', 'topic_first_post'), array('sql_attr_bool', 'deleted'), - array('sql_attr_timestamp' , 'post_time'), - array('sql_attr_timestamp' , 'topic_last_post_time'), - array('sql_attr_str2ordinal', 'post_subject'), + array('sql_attr_timestamp', 'post_time'), + array('sql_attr_timestamp', 'topic_last_post_time'), + array('sql_attr_string', 'post_subject'), ), 'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array( array('sql_query_pre', ''), diff --git a/phpBB/phpbb/search/sphinx/config.php b/phpBB/phpbb/search/sphinx/config.php index f1864f0c8c..cb8e4524df 100644 --- a/phpBB/phpbb/search/sphinx/config.php +++ b/phpBB/phpbb/search/sphinx/config.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search\sphinx; /** -* phpbb_search_sphinx_config +* \phpbb\search\sphinx\config * An object representing the sphinx configuration * Can read it from file and write it back out after modification * @package search */ -class phpbb_search_sphinx_config +class config { private $sections = array(); @@ -44,7 +38,7 @@ class phpbb_search_sphinx_config * Get a section object by its name * * @param string $name The name of the section that shall be returned - * @return phpbb_search_sphinx_config_section The section object or null if none was found + * @return \phpbb\search\sphinx\config_section The section object or null if none was found * * @access public */ @@ -53,7 +47,7 @@ class phpbb_search_sphinx_config for ($i = 0, $size = sizeof($this->sections); $i < $size; $i++) { // Make sure this is really a section object and not a comment - if (($this->sections[$i] instanceof phpbb_search_sphinx_config_section) && $this->sections[$i]->get_name() == $name) + if (($this->sections[$i] instanceof \phpbb\search\sphinx\config_section) && $this->sections[$i]->get_name() == $name) { return $this->sections[$i]; } @@ -64,13 +58,13 @@ class phpbb_search_sphinx_config * Appends a new empty section to the end of the config * * @param string $name The name for the new section - * @return phpbb_search_sphinx_config_section The newly created section object + * @return \phpbb\search\sphinx\config_section The newly created section object * * @access public */ function add_section($name) { - $this->sections[] = new phpbb_search_sphinx_config_section($name, ''); + $this->sections[] = new \phpbb\search\sphinx\config_section($name, ''); return $this->sections[sizeof($this->sections) - 1]; } @@ -109,7 +103,7 @@ class phpbb_search_sphinx_config // that way they're not deleted when reassembling the file from the sections if (!$line || $line[0] == '#') { - $this->sections[] = new phpbb_search_sphinx_config_comment($config_file[$i]); + $this->sections[] = new \phpbb\search\sphinx\config_comment($config_file[$i]); continue; } else @@ -143,7 +137,7 @@ class phpbb_search_sphinx_config // And then we create the new section object $section_name = trim($section_name); - $section = new phpbb_search_sphinx_config_section($section_name, $section_name_comment); + $section = new \phpbb\search\sphinx\config_section($section_name, $section_name_comment); } } else @@ -158,10 +152,10 @@ class phpbb_search_sphinx_config // of this section so they're not deleted on reassembly if (!$line || $line[0] == '#') { - $section->add_variable(new phpbb_search_sphinx_config_comment($config_file[$i])); + $section->add_variable(new \phpbb\search\sphinx\config_comment($config_file[$i])); continue; } - + // As long as we haven't yet actually found an opening bracket for this section // we treat everything as comments so it's not deleted either if (!$found_opening_bracket) @@ -174,13 +168,13 @@ class phpbb_search_sphinx_config } else { - $section->add_variable(new phpbb_search_sphinx_config_comment($config_file[$i])); + $section->add_variable(new \phpbb\search\sphinx\config_comment($config_file[$i])); continue; } } } - // If we did not find a comment in this line or still add to the previous + // If we did not find a comment in this line or still add to the previous // line's value ... if ($line || $in_value) { @@ -239,16 +233,16 @@ class phpbb_search_sphinx_config } } - // If a name and an equal sign were found then we have append a + // If a name and an equal sign were found then we have append a // new variable object to the section if ($name && $found_assignment) { - $section->add_variable(new phpbb_search_sphinx_config_variable(trim($name), trim($value), ($end_section) ? '' : $comment)); + $section->add_variable(new \phpbb\search\sphinx\config_variable(trim($name), trim($value), ($end_section) ? '' : $comment)); continue; } /* If we found a closing curly bracket this section has been completed - and we can append it to the section list and continue with looking for + and we can append it to the section list and continue with looking for the next section */ if ($end_section) { @@ -262,7 +256,7 @@ class phpbb_search_sphinx_config // If we did not find anything meaningful up to here, then just treat it // as a comment $comment = ($skip_first) ? "\t" . substr(ltrim($config_file[$i]), 1) : $config_file[$i]; - $section->add_variable(new phpbb_search_sphinx_config_comment($comment)); + $section->add_variable(new \phpbb\search\sphinx\config_comment($comment)); } } diff --git a/phpBB/phpbb/search/sphinx/config_comment.php b/phpBB/phpbb/search/sphinx/config_comment.php index 7f695dbf0c..20b1c19af1 100644 --- a/phpBB/phpbb/search/sphinx/config_comment.php +++ b/phpBB/phpbb/search/sphinx/config_comment.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search\sphinx; /** -* phpbb_search_sphinx_config_comment +* \phpbb\search\sphinx\config_comment * Represents a comment inside the sphinx configuration */ -class phpbb_search_sphinx_config_comment +class config_comment { private $exact_string; diff --git a/phpBB/phpbb/search/sphinx/config_section.php b/phpBB/phpbb/search/sphinx/config_section.php index 79c9c8563d..8f9253ec56 100644 --- a/phpBB/phpbb/search/sphinx/config_section.php +++ b/phpBB/phpbb/search/sphinx/config_section.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search\sphinx; /** -* phpbb_search_sphinx_config_section +* \phpbb\search\sphinx\config_section * Represents a single section inside the sphinx configuration */ -class phpbb_search_sphinx_config_section +class config_section { private $name; private $comment; @@ -45,7 +39,7 @@ class phpbb_search_sphinx_config_section /** * Add a variable object to the list of variables in this section * - * @param phpbb_search_sphinx_config_variable $variable The variable object + * @param \phpbb\search\sphinx\config_variable $variable The variable object * * @access public */ @@ -82,7 +76,7 @@ class phpbb_search_sphinx_config_section * Get a variable object by its name * * @param string $name The name of the variable that shall be returned - * @return phpbb_search_sphinx_config_section The first variable object from this section with the + * @return \phpbb\search\sphinx\config_section The first variable object from this section with the * given name or null if none was found * * @access public @@ -92,7 +86,7 @@ class phpbb_search_sphinx_config_section for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++) { // Make sure this is a variable object and not a comment - if (($this->variables[$i] instanceof phpbb_search_sphinx_config_variable) && $this->variables[$i]->get_name() == $name) + if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name) { return $this->variables[$i]; } @@ -111,7 +105,7 @@ class phpbb_search_sphinx_config_section for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++) { // Make sure this is a variable object and not a comment - if (($this->variables[$i] instanceof phpbb_search_sphinx_config_variable) && $this->variables[$i]->get_name() == $name) + if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name) { array_splice($this->variables, $i, 1); $i--; @@ -124,13 +118,13 @@ class phpbb_search_sphinx_config_section * * @param string $name The name for the new variable * @param string $value The value for the new variable - * @return phpbb_search_sphinx_config_variable Variable object that was created + * @return \phpbb\search\sphinx\config_variable Variable object that was created * * @access public */ function create_variable($name, $value) { - $this->variables[] = new phpbb_search_sphinx_config_variable($name, $value, ''); + $this->variables[] = new \phpbb\search\sphinx\config_variable($name, $value, ''); return $this->variables[sizeof($this->variables) - 1]; } diff --git a/phpBB/phpbb/search/sphinx/config_variable.php b/phpBB/phpbb/search/sphinx/config_variable.php index 2c1d35a49c..c0f6d28dcc 100644 --- a/phpBB/phpbb/search/sphinx/config_variable.php +++ b/phpBB/phpbb/search/sphinx/config_variable.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\search\sphinx; /** -* phpbb_search_sphinx_config_variable +* \phpbb\search\sphinx\config_variable * Represents a single variable inside the sphinx configuration */ -class phpbb_search_sphinx_config_variable +class config_variable { private $name; private $value; diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index dc33786666..f530d30f1f 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * Session class * @package phpBB3 */ -class phpbb_session +class session { var $cookie_data = array(); var $page = array(); @@ -40,13 +34,13 @@ class phpbb_session */ static function extract_current_page($root_path) { - global $request; + global $request, $symfony_request, $phpbb_filesystem; $page_array = array(); // First of all, get the request uri... - $script_name = htmlspecialchars_decode($request->server('PHP_SELF')); - $args = explode('&', htmlspecialchars_decode($request->server('QUERY_STRING'))); + $script_name = $symfony_request->getScriptName(); + $args = explode('&', $symfony_request->getQueryString()); // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... if (!$script_name) @@ -87,6 +81,12 @@ class phpbb_session $page_name = (substr($script_name, -1, 1) == '/') ? '' : basename($script_name); $page_name = urlencode(htmlspecialchars($page_name)); + $symfony_request_path = $phpbb_filesystem->clean_path($symfony_request->getPathInfo()); + if ($symfony_request_path !== '/') + { + $page_name .= $symfony_request_path; + } + // current directory within the phpBB root (for example: adm) $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path))); $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./'))); @@ -103,10 +103,14 @@ class phpbb_session } // Current page from phpBB root (for example: adm/index.php?i=10&b=2) - $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : ''); + $page = (($page_dir) ? $page_dir . '/' : '') . $page_name; + if ($query_string) + { + $page .= '?' . $query_string; + } // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in / - $script_path = trim(str_replace('\\', '/', dirname($script_name))); + $script_path = $symfony_request->getBasePath(); // The script path from the webroot to the phpBB root (for example: /phpBB3/) $script_dirs = explode('/', $script_path); @@ -243,7 +247,7 @@ class phpbb_session $this->forwarded_for = ''; } - if ($request->is_set($config['cookie_name'] . '_sid', phpbb_request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u', phpbb_request_interface::COOKIE)) + if ($request->is_set($config['cookie_name'] . '_sid', \phpbb\request\request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u', \phpbb\request\request_interface::COOKIE)) { $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true); $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true); @@ -405,9 +409,9 @@ class phpbb_session $provider = $phpbb_container->get('auth.provider.' . $method); - if (!($provider instanceof phpbb_auth_provider_interface)) + if (!($provider instanceof \phpbb\auth\provider\provider_interface)) { - throw new \RuntimeException($provider . ' must implement phpbb_auth_provider_interface'); + throw new \RuntimeException($provider . ' must implement \phpbb\auth\provider\provider_interface'); } $ret = $provider->validate_session($this->data); @@ -1022,7 +1026,7 @@ class phpbb_session { include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx); } - $captcha_factory = new phpbb_captcha_factory(); + $captcha_factory = new \phpbb_captcha_factory(); $captcha_factory->garbage_collect($config['captcha_plugin']); $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . ' @@ -1223,7 +1227,6 @@ class phpbb_session $this->session_create(ANONYMOUS); } - // Determine which message to output $till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : ''; $message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; diff --git a/phpBB/phpbb/symfony_request.php b/phpBB/phpbb/symfony_request.php new file mode 100644 index 0000000000..ebe862a565 --- /dev/null +++ b/phpBB/phpbb/symfony_request.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb; + +use Symfony\Component\HttpFoundation\Request; + +class symfony_request extends Request +{ + /** + * Constructor + * + * @param phpbb\request\request_interface $phpbb_request + */ + public function __construct(\phpbb\request\request_interface $phpbb_request) + { + // This function is meant to sanitize the global input arrays + $sanitizer = function(&$value, $key) { + $type_cast_helper = new \phpbb\request\type_cast_helper(); + $type_cast_helper->set_var($value, $value, gettype($value), true); + }; + + $get_parameters = $phpbb_request->get_super_global(\phpbb\request\request_interface::GET); + $post_parameters = $phpbb_request->get_super_global(\phpbb\request\request_interface::POST); + $server_parameters = $phpbb_request->get_super_global(\phpbb\request\request_interface::SERVER); + $files_parameters = $phpbb_request->get_super_global(\phpbb\request\request_interface::FILES); + $cookie_parameters = $phpbb_request->get_super_global(\phpbb\request\request_interface::COOKIE); + + array_walk_recursive($get_parameters, $sanitizer); + array_walk_recursive($post_parameters, $sanitizer); + + parent::__construct($get_parameters, $post_parameters, array(), $cookie_parameters, $files_parameters, $server_parameters); + } +} diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index 7c322cd971..24e0d6698d 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -7,25 +7,24 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template; -class phpbb_template_asset +class asset { protected $components = array(); + /** @var \phpbb\path_helper **/ + protected $path_helper; + /** * Constructor * * @param string $url URL */ - public function __construct($url) + public function __construct($url, \phpbb\path_helper $path_helper) { + $this->path_helper = $path_helper; + $this->set_url($url); } @@ -112,7 +111,7 @@ class phpbb_template_asset */ public function get_url() { - return $this->join_url($this->components); + return $this->path_helper->update_web_root_path($this->join_url($this->components)); } /** diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php index 3778424a96..5bce79fd85 100644 --- a/phpBB/phpbb/template/base.php +++ b/phpBB/phpbb/template/base.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template; -abstract class phpbb_template_base implements phpbb_template +abstract class base implements template { /** * Template context. * Stores template data used during template rendering. * - * @var phpbb_template_context + * @var \phpbb\template\context */ protected $context; @@ -119,6 +113,16 @@ abstract class phpbb_template_base implements phpbb_template /** * {@inheritdoc} */ + public function assign_block_vars_array($blockname, array $block_vars_array) + { + $this->context->assign_block_vars_array($blockname, $block_vars_array); + + return $this; + } + + /** + * {@inheritdoc} + */ public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { return $this->context->alter_block_array($blockname, $vararray, $key, $mode); diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index c5ce7422b9..a222fbb69e 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template; /** * Stores variables assigned to template. * * @package phpBB3 */ -class phpbb_template_context +class context { /** * variable that holds all the data we'll be substituting into @@ -86,7 +80,7 @@ class phpbb_template_context * Returns a reference to template data array. * * This function is public so that template renderer may invoke it. - * Users should alter template variables via functions in phpbb_template. + * Users should alter template variables via functions in \phpbb\template\template. * * Note: modifying returned array will affect data stored in the context. * @@ -161,11 +155,12 @@ class phpbb_template_context // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount]][] = $vararray; + $s_num_rows = sizeof($str[$blocks[$blockcount]]); // Set S_NUM_ROWS foreach ($str[$blocks[$blockcount]] as &$mod_block) { - $mod_block['S_NUM_ROWS'] = sizeof($str[$blocks[$blockcount]]); + $mod_block['S_NUM_ROWS'] = $s_num_rows; } } else @@ -192,11 +187,12 @@ class phpbb_template_context // Add a new iteration to this block with the variable assignments we were given. $this->tpldata[$blockname][] = $vararray; + $s_num_rows = sizeof($this->tpldata[$blockname]); // Set S_NUM_ROWS foreach ($this->tpldata[$blockname] as &$mod_block) { - $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); + $mod_block['S_NUM_ROWS'] = $s_num_rows; } } @@ -204,6 +200,22 @@ class phpbb_template_context } /** + * Assign key variable pairs from an array to a whole specified block loop + * + * @param string $blockname Name of block to assign $block_vars_array to + * @param array $block_vars_array An array of hashes of variable name => value pairs + */ + public function assign_block_vars_array($blockname, array $block_vars_array) + { + foreach ($block_vars_array as $vararray) + { + $this->assign_block_vars($blockname, $vararray); + } + + return true; + } + + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * * An example of how to use this function: @@ -223,7 +235,7 @@ class phpbb_template_context * @param string $mode Mode to execute (valid modes are 'insert' and 'change') * * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new \value). * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) @@ -283,7 +295,7 @@ class phpbb_template_context // Search array to get correct position list($search_key, $search_value) = @each($key); - $key = NULL; + $key = null; foreach ($block as $i => $val_ary) { if ($val_ary[$search_key] === $search_value) @@ -294,7 +306,7 @@ class phpbb_template_context } // key/value pair not found - if ($key === NULL) + if ($key === null) { return false; } diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 6b9c331a3e..87ae7a9766 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template; -interface phpbb_template +interface template { /** * Clear the cache * - * @return phpbb_template + * @return \phpbb\template\template */ public function clear_cache(); @@ -29,7 +23,7 @@ interface phpbb_template * Sets the template filenames for handles. * * @param array $filename_array Should be a hash of handle => filename pairs. - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function set_filenames(array $filename_array); @@ -46,7 +40,7 @@ interface phpbb_template * @param array $style_directories The directories to add style paths for * E.g. array('ext/foo/bar/styles', 'styles') * Default: array('styles') (phpBB's style directory) - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function set_style($style_directories = array('styles')); @@ -57,14 +51,14 @@ interface phpbb_template * * @param string|array $names Array of names or string of name of template(s) in inheritance tree order, used by extensions. * @param string|array or string $paths Array of style paths, relative to current root directory - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function set_custom_style($names, $paths); /** * Clears all variables and blocks assigned to this template. * - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function destroy(); @@ -72,7 +66,7 @@ interface phpbb_template * Reset/empty complete block * * @param string $blockname Name of block to destroy - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function destroy_block_vars($blockname); @@ -84,7 +78,7 @@ interface phpbb_template * This function calls hooks. * * @param string $handle Handle to display - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function display($handle); @@ -95,7 +89,7 @@ interface phpbb_template * @param string $handle Handle to operate on * @param string $template_var Template variable to assign compiled handle to * @param bool $return_content If true return compiled handle, otherwise assign to $template_var - * @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this + * @return \phpbb\template\template|string if $return_content is true return string of the compiled handle, otherwise return $this */ public function assign_display($handle, $template_var = '', $return_content = true); @@ -103,7 +97,7 @@ interface phpbb_template * Assign key variable pairs from an array * * @param array $vararray A hash of variable name => value pairs - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function assign_vars(array $vararray); @@ -114,7 +108,7 @@ interface phpbb_template * * @param string $varname Variable name * @param string $varval Value to assign to variable - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function assign_var($varname, $varval); @@ -125,7 +119,7 @@ interface phpbb_template * * @param string $varname Variable name * @param string $varval Value to append to variable - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function append_var($varname, $varval); @@ -133,11 +127,19 @@ interface phpbb_template * Assign key variable pairs from an array to a specified block * @param string $blockname Name of block to assign $vararray to * @param array $vararray A hash of variable name => value pairs - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function assign_block_vars($blockname, array $vararray); /** + * Assign key variable pairs from an array to a whole specified block loop + * @param string $blockname Name of block to assign $block_vars_array to + * @param array $block_vars_array An array of hashes of variable name => value pairs + * @return \phpbb\template\template $this + */ + public function assign_block_vars_array($blockname, array $block_vars_array); + + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * * An example of how to use this function: @@ -157,7 +159,7 @@ interface phpbb_template * @param string $mode Mode to execute (valid modes are 'insert' and 'change') * * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * If change, the current block gets merged with the vararray (resulting in new \key/value pairs be added and existing keys be replaced by the new \value). * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) diff --git a/phpBB/phpbb/template/twig/definition.php b/phpBB/phpbb/template/twig/definition.php index 6557b209eb..945c46675e 100644 --- a/phpBB/phpbb/template/twig/definition.php +++ b/phpBB/phpbb/template/twig/definition.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig; /** * This class holds all DEFINE variables from the current page load */ -class phpbb_template_twig_definition +class definition { /** @var array **/ protected $definitions = array(); @@ -39,7 +33,7 @@ class phpbb_template_twig_definition * * @param string $name * @param mixed $value - * @return phpbb_template_twig_definition + * @return \phpbb\template\twig\definition */ public function set($name, $value) { @@ -53,7 +47,7 @@ class phpbb_template_twig_definition * * @param string $name * @param string $value - * @return phpbb_template_twig_definition + * @return \phpbb\template\twig\definition */ public function append($name, $value) { diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index b60cd72325..aa55f1e011 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -7,42 +7,47 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig; -class phpbb_template_twig_environment extends Twig_Environment +class environment extends \Twig_Environment { - /** @var array */ - protected $phpbb_extensions; - - /** @var phpbb_config */ + /** @var \phpbb\config\config */ protected $phpbb_config; + /** @var \phpbb\path_helper */ + protected $phpbb_path_helper; + + /** @var \phpbb\extension\manager */ + protected $extension_manager; + /** @var string */ protected $phpbb_root_path; + /** @var string */ + protected $web_root_path; + /** @var array **/ protected $namespace_look_up_order = array('__main__'); /** * Constructor * - * @param phpbb_config $phpbb_config - * @param array $phpbb_extensions Array of enabled extensions (name => path) + * @param \phpbb\config\config $phpbb_config + * @param \phpbb\path_helper + * @param \phpbb\extension\manager * @param string $phpbb_root_path * @param Twig_LoaderInterface $loader * @param array $options Array of options to pass to Twig */ - public function __construct($phpbb_config, $phpbb_extensions, $phpbb_root_path, Twig_LoaderInterface $loader = null, $options = array()) + public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array()) { $this->phpbb_config = $phpbb_config; - $this->phpbb_extensions = $phpbb_extensions; - $this->phpbb_root_path = $phpbb_root_path; + + $this->phpbb_path_helper = $path_helper; + $this->extension_manager = $extension_manager; + + $this->phpbb_root_path = $this->phpbb_path_helper->get_phpbb_root_path(); + $this->web_root_path = $this->phpbb_path_helper->get_web_root_path(); return parent::__construct($loader, $options); } @@ -56,13 +61,13 @@ class phpbb_template_twig_environment extends Twig_Environment */ public function get_phpbb_extensions() { - return $this->phpbb_extensions; + return ($this->extension_manager) ? $this->extension_manager->all_enabled() : array(); } /** * Get phpBB config * - * @return phpbb_config + * @return \phpbb\config\config */ public function get_phpbb_config() { @@ -80,6 +85,26 @@ class phpbb_template_twig_environment extends Twig_Environment } /** + * Get the web root path + * + * @return string + */ + public function get_web_root_path() + { + return $this->web_root_path; + } + + /** + * Get the phpbb path helper object + * + * @return \phpbb\path_helper + */ + public function get_path_helper() + { + return $this->phpbb_path_helper; + } + + /** * Get the namespace look up order * * @return array @@ -124,7 +149,7 @@ class phpbb_template_twig_environment extends Twig_Environment return parent::loadTemplate('@' . $namespace . '/' . $name, $index); } - catch (Twig_Error_Loader $e) + catch (\Twig_Error_Loader $e) { } } @@ -137,4 +162,39 @@ class phpbb_template_twig_environment extends Twig_Environment return parent::loadTemplate($name, $index); } } + + /** + * Finds a template by name. + * + * @param string $name The template name + * @return string + */ + public function findTemplate($name) + { + if (strpos($name, '@') === false) + { + foreach ($this->getNamespaceLookUpOrder() as $namespace) + { + try + { + if ($namespace === '__main__') + { + return parent::getLoader()->getCacheKey($name); + } + + return parent::getLoader()->getCacheKey('@' . $namespace . '/' . $name); + } + catch (Twig_Error_Loader $e) + { + } + } + + // We were unable to load any templates + throw $e; + } + else + { + return parent::getLoader()->getCacheKey($name); + } + } } diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index c279726434..6847dbd9f8 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -7,30 +7,24 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig; -class phpbb_template_twig_extension extends Twig_Extension +class extension extends \Twig_Extension { - /** @var phpbb_template_context */ + /** @var \phpbb\template\context */ protected $context; - /** @var phpbb_user */ + /** @var \phpbb\user */ protected $user; /** * Constructor * - * @param phpbb_template_context $context - * @param phpbb_user $user - * @return phpbb_template_twig_extension + * @param \phpbb\template\context $context + * @param \phpbb\user $user + * @return \phpbb\template\twig\extension */ - public function __construct(phpbb_template_context $context, $user) + public function __construct(\phpbb\template\context $context, $user) { $this->context = $context; $this->user = $user; @@ -46,54 +40,54 @@ class phpbb_template_twig_extension extends Twig_Extension return 'phpbb'; } - /** - * Returns the token parser instance to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ public function getTokenParsers() { return array( - new phpbb_template_twig_tokenparser_define, - new phpbb_template_twig_tokenparser_include, - new phpbb_template_twig_tokenparser_includejs, - new phpbb_template_twig_tokenparser_includecss, - new phpbb_template_twig_tokenparser_event, - new phpbb_template_twig_tokenparser_includephp, - new phpbb_template_twig_tokenparser_php, + new \phpbb\template\twig\tokenparser\defineparser, + new \phpbb\template\twig\tokenparser\includeparser, + new \phpbb\template\twig\tokenparser\includejs, + new \phpbb\template\twig\tokenparser\includecss, + new \phpbb\template\twig\tokenparser\event, + new \phpbb\template\twig\tokenparser\includephp, + new \phpbb\template\twig\tokenparser\php, ); } - /** - * Returns a list of filters to add to the existing list. - * - * @return array An array of filters - */ - public function getFilters() - { + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { return array( - new Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)), - new Twig_SimpleFilter('addslashes', 'addslashes'), + new \Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)), + new \Twig_SimpleFilter('addslashes', 'addslashes'), ); - } - - /** - * Returns a list of global functions to add to the existing list. - * - * @return array An array of global functions - */ - public function getFunctions() - { + } + + /** + * Returns a list of global functions to add to the existing list. + * + * @return array An array of global functions + */ + public function getFunctions() + { return array( - new Twig_SimpleFunction('lang', array($this, 'lang')), + new \Twig_SimpleFunction('lang', array($this, 'lang')), ); } - /** - * Returns a list of operators to add to the existing list. - * - * @return array An array of operators - */ + /** + * Returns a list of operators to add to the existing list. + * + * @return array An array of operators + */ public function getOperators() { return array( @@ -102,42 +96,42 @@ class phpbb_template_twig_extension extends Twig_Extension ), array( // precedence settings are copied from similar operators in Twig core extension - '||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + '&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), - 'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), - 'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'neq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '<>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'neq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + '<>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), - '===' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_equalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '!==' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_notequalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '===' => array('precedence' => 20, 'class' => '\phpbb\template\twig\node\expression\binary\equalequal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + '!==' => array('precedence' => 20, 'class' => '\phpbb\template\twig\node\expression\binary\notequalequal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), - 'gt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'gte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'ge' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'lt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'lte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'le' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'gt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'gte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'ge' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'lt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'lte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), + 'le' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), - 'mod' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'mod' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), ), ); - } + } /** - * Grabs a subset of a loop - * - * @param Twig_Environment $env A Twig_Environment instance - * @param mixed $item A variable - * @param integer $start Start of the subset - * @param integer $end End of the subset - * @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array) - * - * @return mixed The sliced variable - */ - function loop_subset(Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false) + * Grabs a subset of a loop + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $item A variable + * @param integer $start Start of the subset + * @param integer $end End of the subset + * @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array) + * + * @return mixed The sliced variable + */ + function loop_subset(\Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false) { // We do almost the same thing as Twig's slice (array_slice), except when $end is positive if ($end >= 1) diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php index 7ab569313c..f4efc58540 100644 --- a/phpBB/phpbb/template/twig/lexer.php +++ b/phpBB/phpbb/template/twig/lexer.php @@ -7,15 +7,9 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig; -class phpbb_template_twig_lexer extends Twig_Lexer +class lexer extends \Twig_Lexer { public function tokenize($code, $filename = null) { @@ -74,8 +68,20 @@ class phpbb_template_twig_lexer extends Twig_Lexer ); // Fix tokens that may have inline variables (e.g. <!-- DEFINE $TEST = '{FOO}') + $code = $this->strip_surrounding_quotes(array( + 'INCLUDE', + 'INCLUDEPHP', + 'INCLUDEJS', + 'INCLUDECSS', + ), $code); $code = $this->fix_inline_variable_tokens(array( - 'DEFINE.+=', + 'DEFINE \$[a-zA-Z0-9_]+ =', + 'INCLUDE', + 'INCLUDEPHP', + 'INCLUDEJS', + 'INCLUDECSS', + ), $code); + $code = $this->add_surrounding_quotes(array( 'INCLUDE', 'INCLUDEPHP', 'INCLUDEJS', @@ -114,9 +120,29 @@ class phpbb_template_twig_lexer extends Twig_Lexer } /** + * Strip surrounding quotes + * + * First step to fix tokens that may have inline variables + * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE {TEST}.html + * + * @param array $tokens array of tokens to search for (imploded to a regular expression) + * @param string $code + * @return string + */ + protected function strip_surrounding_quotes($tokens, $code) + { + // Remove matching quotes at the beginning/end if a statement; + // E.g. 'asdf'"' -> asdf'" + // E.g. "asdf'"" -> asdf'" + // E.g. 'asdf'" -> 'asdf'" + return preg_replace('#<!-- (' . implode('|', $tokens) . ') (([\'"])?(.*?)\1) -->#', '<!-- $1 $2 -->', $code); + } + + /** * Fix tokens that may have inline variables * - * E.g. <!-- INCLUDE {TEST}.html + * Second step to fix tokens that may have inline variables + * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE ' ~ {TEST} ~ '.html * * @param array $tokens array of tokens to search for (imploded to a regular expression) * @param string $code @@ -126,23 +152,31 @@ class phpbb_template_twig_lexer extends Twig_Lexer { $callback = function($matches) { - // Remove matching quotes at the beginning/end if a statement; - // E.g. 'asdf'"' -> asdf'" - // E.g. "asdf'"" -> asdf'" - // E.g. 'asdf'" -> 'asdf'" - $matches[2] = preg_replace('#^([\'"])?(.*?)\1$#', '$2', $matches[2]); - // Replace template variables with start/end to parse variables (' ~ TEST ~ '.html) $matches[2] = preg_replace('#{([a-zA-Z0-9_\.$]+)}#', "'~ \$1 ~'", $matches[2]); - // Surround the matches in single quotes ('' ~ TEST ~ '.html') - return "<!-- {$matches[1]} '{$matches[2]}' -->"; + return "<!-- {$matches[1]} {$matches[2]} -->"; }; return preg_replace_callback('#<!-- (' . implode('|', $tokens) . ') (.+?) -->#', $callback, $code); } /** + * Add surrounding quotes + * + * Last step to fix tokens that may have inline variables + * E.g. <!-- INCLUDE '{TEST}.html' to <!-- INCLUDE '' ~ {TEST} ~ '.html' + * + * @param array $tokens array of tokens to search for (imploded to a regular expression) + * @param string $code + * @return string + */ + protected function add_surrounding_quotes($tokens, $code) + { + return preg_replace('#<!-- (' . implode('|', $tokens) . ') (.+?) -->#', '<!-- $1 \'$2\' -->', $code); + } + + /** * Fix begin tokens (convert our BEGIN to Twig for) * * Not meant to be used outside of this context, public because the anonymous function calls this @@ -161,6 +195,9 @@ class phpbb_template_twig_lexer extends Twig_Lexer $subset = trim(substr($matches[2], 1, -1)); // Remove parenthesis $body = $matches[3]; + // Replace <!-- BEGINELSE --> + $body = str_replace('<!-- BEGINELSE -->', '{% else %}', $body); + // Is the designer wanting to call another loop in a loop? // <!-- BEGIN loop --> // <!-- BEGIN !loop2 --> @@ -205,9 +242,6 @@ class phpbb_template_twig_lexer extends Twig_Lexer return "{% for {$name} in {$parent}{$name}{$subset} %}{$body}{% endfor %}"; }; - // Replace <!-- BEGINELSE --> correctly, only needs to be done once - $code = str_replace('<!-- BEGINELSE -->', '{% else %}', $code); - return preg_replace_callback('#<!-- BEGIN ([!a-zA-Z0-9_]+)(\([0-9,\-]+\))? -->(.+?)<!-- END \1 -->#s', $callback, $code); } @@ -229,18 +263,18 @@ class phpbb_template_twig_lexer extends Twig_Lexer { $inner = $matches[2]; // Replace $TEST with definition.TEST - $inner = preg_replace('#\s\$([a-zA-Z_0-9]+)#', ' definition.$1', $inner); + $inner = preg_replace('#(\s\(*!?)\$([a-zA-Z_0-9]+)#', '$1definition.$2', $inner); // Replace .foo with loops.foo|length - $inner = preg_replace('#\s\.([a-zA-Z_0-9]+)([^a-zA-Z_0-9\.])#', ' loops.$1|length$2', $inner); + $inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9]+)([^a-zA-Z_0-9\.])#', '$1loops.$2|length$3', $inner); // Replace .foo.bar with foo.bar|length - $inner = preg_replace('#\s\.([a-zA-Z_0-9\.]+)([^a-zA-Z_0-9\.])#', ' $1|length$2', $inner); + $inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9\.]+)([^a-zA-Z_0-9\.])#', '$1$2|length$3', $inner); return "<!-- {$matches[1]}IF{$inner}-->"; }; - return preg_replace_callback('#<!-- (ELSE)?IF((.*)[\s][\$|\.|!]([^\s]+)(.*))-->#', $callback, $code); + return preg_replace_callback('#<!-- (ELSE)?IF((.*?) \(*!?[\$|\.]([^\s]+)(.*?))-->#', $callback, $code); } /** @@ -264,10 +298,10 @@ class phpbb_template_twig_lexer extends Twig_Lexer */ // Replace <!-- DEFINE $NAME with {% DEFINE definition.NAME - $code = preg_replace('#<!-- DEFINE \$(.*)-->#', '{% DEFINE $1 %}', $code); + $code = preg_replace('#<!-- DEFINE \$(.*?) -->#', '{% DEFINE $1 %}', $code); // Changing UNDEFINE NAME to DEFINE NAME = null to save from creating an extra token parser/node - $code = preg_replace('#<!-- UNDEFINE \$(.*)-->#', '{% DEFINE $1= null %}', $code); + $code = preg_replace('#<!-- UNDEFINE \$(.*?)-->#', '{% DEFINE $1= null %}', $code); // Replace all of our variables, {$VARNAME}, with Twig style, {{ definition.VARNAME }} $code = preg_replace('#{\$([a-zA-Z0-9_\.]+)}#', '{{ definition.$1 }}', $code); diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php new file mode 100644 index 0000000000..e01e9de467 --- /dev/null +++ b/phpBB/phpbb/template/twig/loader.php @@ -0,0 +1,144 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\template\twig; + +/** +* Twig Template loader +* @package phpBB3 +*/ +class loader extends \Twig_Loader_Filesystem +{ + protected $safe_directories = array(); + + /** + * Set safe directories + * + * @param array $directories Array of directories that are safe (empty to clear) + * @return Twig_Loader_Filesystem + */ + public function setSafeDirectories($directories = array()) + { + $this->safe_directories = array(); + + if (!empty($directories)) + { + foreach ($directories as $directory) + { + $this->addSafeDirectory($directory); + } + } + + return $this; + } + + /** + * Add safe directory + * + * @param string $directory Directory that should be added + * @return Twig_Loader_Filesystem + */ + public function addSafeDirectory($directory) + { + $directory = phpbb_realpath($directory); + + if ($directory !== false) + { + $this->safe_directories[] = $directory; + } + + return $this; + } + + /** + * Get current safe directories + * + * @return array + */ + public function getSafeDirectories() + { + return $this->safe_directories; + } + + /** + * Override for parent::validateName() + * + * This is done because we added support for safe directories, and when Twig + * findTemplate() is called, validateName() is called first, which would + * always throw an exception if the file is outside of the configured + * template directories. + */ + protected function validateName($name) + { + return; + } + + /** + * Find the template + * + * Override for Twig_Loader_Filesystem::findTemplate to add support + * for loading from safe directories. + */ + protected function findTemplate($name) + { + $name = (string) $name; + + // normalize name + $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/')); + + // 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])) { + return $this->cache[$name]; + } + + // First, find the template name. The override above of validateName + // causes the validateName process to be skipped for this call + $file = parent::findTemplate($name); + + try + { + // Try validating the name (which may throw an exception) + parent::validateName($name); + } + catch (Twig_Error_Loader $e) + { + if (strpos($e->getRawMessage(), 'Looks like you try to load a template outside configured directories') === 0) + { + // Ok, so outside of the configured template directories, we + // can now check if we're within a "safe" directory + + // Find the real path of the directory the file is in + $directory = phpbb_realpath(dirname($file)); + + if ($directory === false) + { + // Some sort of error finding the actual path, must throw the exception + throw $e; + } + + foreach ($this->safe_directories as $safe_directory) + { + if (strpos($directory, $safe_directory) === 0) + { + // The directory being loaded is below a directory + // that is "safe". We're good to load it! + return $file; + } + } + } + + // Not within any safe directories + throw $e; + } + + // No exception from validateName, safe to load. + return $file; + } +} diff --git a/phpBB/phpbb/template/twig/node/define.php b/phpBB/phpbb/template/twig/node/definenode.php index fcb19cc773..6a9969f8c6 100644 --- a/phpBB/phpbb/template/twig/node/define.php +++ b/phpBB/phpbb/template/twig/node/definenode.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node; -class phpbb_template_twig_node_define extends Twig_Node +class definenode extends \Twig_Node { - public function __construct($capture, Twig_NodeInterface $name, Twig_NodeInterface $value, $lineno, $tag = null) + public function __construct($capture, \Twig_NodeInterface $name, \Twig_NodeInterface $value, $lineno, $tag = null) { parent::__construct(array('name' => $name, 'value' => $value), array('capture' => $capture, 'safe' => false), $lineno, $tag); } @@ -28,7 +22,7 @@ class phpbb_template_twig_node_define extends Twig_Node * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -38,7 +32,7 @@ class phpbb_template_twig_node_define extends Twig_Node ->subcompile($this->getNode('value')) ; - $compiler->write("\$value = ('' === \$value = ob_get_clean()) ? '' : new Twig_Markup(\$value, \$this->env->getCharset());\n"); + $compiler->write("\$value = ('' === \$value = ob_get_clean()) ? '' : new \Twig_Markup(\$value, \$this->env->getCharset());\n"); } else { diff --git a/phpBB/phpbb/template/twig/node/event.php b/phpBB/phpbb/template/twig/node/event.php index c94e5fdf20..7a1181a866 100644 --- a/phpBB/phpbb/template/twig/node/event.php +++ b/phpBB/phpbb/template/twig/node/event.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node; -class phpbb_template_twig_node_event extends Twig_Node +class event extends \Twig_Node { - /** + /** * The subdirectory in which all template listener files must be placed * @var string */ @@ -27,7 +21,7 @@ class phpbb_template_twig_node_event extends Twig_Node /** @var Twig_Environment */ protected $environment; - public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null) + public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) { $this->environment = $environment; @@ -39,7 +33,7 @@ class phpbb_template_twig_node_event extends Twig_Node * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -55,10 +49,10 @@ class phpbb_template_twig_node_event extends Twig_Node // templates on page load rather than at compile. This is // slower, but makes developing extensions easier (no need to // purge the cache when a new event template file is added) - $compiler - ->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n") - ->indent() - ; + $compiler + ->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n") + ->indent() + ; } if (defined('DEBUG') || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html')) @@ -77,7 +71,7 @@ class phpbb_template_twig_node_event extends Twig_Node { $compiler ->outdent() - ->write("}\n\n") + ->write("}\n\n") ; } } diff --git a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php index 8ec2069114..f3bbfa6691 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node\expression\binary; -class phpbb_template_twig_node_expression_binary_equalequal extends Twig_Node_Expression_Binary +class equalequal extends \Twig_Node_Expression_Binary { - public function operator(Twig_Compiler $compiler) + public function operator(\Twig_Compiler $compiler) { return $compiler->raw('==='); } diff --git a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php index 96f32c502e..c9c2687e08 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php @@ -7,18 +7,12 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node\expression\binary; -class phpbb_template_twig_node_expression_binary_notequalequal extends Twig_Node_Expression_Binary +class notequalequal extends \Twig_Node_Expression_Binary { - public function operator(Twig_Compiler $compiler) + public function operator(\Twig_Compiler $compiler) { return $compiler->raw('!=='); } diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 1cab416c79..f6c9dc9c58 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -7,12 +7,14 @@ * */ -abstract class phpbb_template_twig_node_includeasset extends Twig_Node +namespace phpbb\template\twig\node; + +abstract class includeasset extends \Twig_Node { /** @var Twig_Environment */ protected $environment; - public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null) + public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) { $this->environment = $environment; @@ -23,7 +25,7 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -33,17 +35,17 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node ->write("\$asset_file = ") ->subcompile($this->getNode('expr')) ->raw(";\n") - ->write("\$asset = new phpbb_template_asset(\$asset_file);\n") + ->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper());\n") ->write("if (substr(\$asset_file, 0, 2) !== './' && \$asset->is_relative()) {\n") ->indent() ->write("\$asset_path = \$asset->get_path();") ->write("\$local_file = \$this->getEnvironment()->get_phpbb_root_path() . \$asset_path;\n") ->write("if (!file_exists(\$local_file)) {\n") ->indent() - ->write("\$local_file = \$this->getEnvironment()->getLoader()->getCacheKey(\$asset_path);\n") + ->write("\$local_file = \$this->getEnvironment()->findTemplate(\$asset_path);\n") ->write("\$asset->set_path(\$local_file, true);\n") ->outdent() - ->write("\$asset->add_assets_version({$config['assets_version']});\n") + ->write("\$asset->add_assets_version('{$config['assets_version']}');\n") ->write("\$asset_file = \$asset->get_url();\n") ->write("}\n") ->outdent() @@ -71,5 +73,5 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node * @param Twig_Compiler A Twig_Compiler instance * @return null */ - abstract protected function append_asset(Twig_Compiler $compiler); + abstract protected function append_asset(\Twig_Compiler $compiler); } diff --git a/phpBB/phpbb/template/twig/node/includecss.php b/phpBB/phpbb/template/twig/node/includecss.php index a9d9b46d69..deb279fa4a 100644 --- a/phpBB/phpbb/template/twig/node/includecss.php +++ b/phpBB/phpbb/template/twig/node/includecss.php @@ -7,7 +7,9 @@ * */ -class phpbb_template_twig_node_includecss extends phpbb_template_twig_node_includeasset +namespace phpbb\template\twig\node; + +class includecss extends \phpbb\template\twig\node\includeasset { /** * {@inheritdoc} @@ -20,7 +22,7 @@ class phpbb_template_twig_node_includecss extends phpbb_template_twig_node_inclu /** * {@inheritdoc} */ - public function append_asset(Twig_Compiler $compiler) + public function append_asset(\Twig_Compiler $compiler) { $compiler ->raw("<link href=\"' . ") diff --git a/phpBB/phpbb/template/twig/node/includejs.php b/phpBB/phpbb/template/twig/node/includejs.php index 2b4b55fb0a..696b640eac 100644 --- a/phpBB/phpbb/template/twig/node/includejs.php +++ b/phpBB/phpbb/template/twig/node/includejs.php @@ -7,7 +7,9 @@ * */ -class phpbb_template_twig_node_includejs extends phpbb_template_twig_node_includeasset +namespace phpbb\template\twig\node; + +class includejs extends \phpbb\template\twig\node\includeasset { /** * {@inheritdoc} @@ -20,7 +22,7 @@ class phpbb_template_twig_node_includejs extends phpbb_template_twig_node_includ /** * {@inheritdoc} */ - protected function append_asset(Twig_Compiler $compiler) + protected function append_asset(\Twig_Compiler $compiler) { $config = $this->environment->get_phpbb_config(); diff --git a/phpBB/phpbb/template/twig/node/include.php b/phpBB/phpbb/template/twig/node/includenode.php index 5c6ae1bbcf..d9b45d6407 100644 --- a/phpBB/phpbb/template/twig/node/include.php +++ b/phpBB/phpbb/template/twig/node/includenode.php @@ -7,23 +7,17 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node; -class phpbb_template_twig_node_include extends Twig_Node_Include +class includenode extends \Twig_Node_Include { /** * Compiles the node to PHP. * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); diff --git a/phpBB/phpbb/template/twig/node/includephp.php b/phpBB/phpbb/template/twig/node/includephp.php index dbe54f0e1a..3f4621c0a9 100644 --- a/phpBB/phpbb/template/twig/node/includephp.php +++ b/phpBB/phpbb/template/twig/node/includephp.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node; -class phpbb_template_twig_node_includephp extends Twig_Node +class includephp extends \Twig_Node { /** @var Twig_Environment */ protected $environment; - public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $ignoreMissing = false, $lineno, $tag = null) + public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $ignoreMissing = false, $tag = null) { $this->environment = $environment; @@ -33,7 +27,7 @@ class phpbb_template_twig_node_includephp extends Twig_Node * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -80,7 +74,7 @@ class phpbb_template_twig_node_includephp extends Twig_Node if ($this->getAttribute('ignore_missing')) { $compiler ->outdent() - ->write("} catch (Twig_Error_Loader \$e) {\n") + ->write("} catch (\Twig_Error_Loader \$e) {\n") ->indent() ->write("// ignore missing template\n") ->outdent() diff --git a/phpBB/phpbb/template/twig/node/php.php b/phpBB/phpbb/template/twig/node/php.php index c11539ea7f..2b18551266 100644 --- a/phpBB/phpbb/template/twig/node/php.php +++ b/phpBB/phpbb/template/twig/node/php.php @@ -7,21 +7,15 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\node; -class phpbb_template_twig_node_php extends Twig_Node +class php extends \Twig_Node { /** @var Twig_Environment */ protected $environment; - public function __construct(Twig_Node_Text $text, phpbb_template_twig_environment $environment, $lineno, $tag = null) + public function __construct(\Twig_Node_Text $text, \phpbb\template\twig\environment $environment, $lineno, $tag = null) { $this->environment = $environment; @@ -33,7 +27,7 @@ class phpbb_template_twig_node_php extends Twig_Node * * @param Twig_Compiler A Twig_Compiler instance */ - public function compile(Twig_Compiler $compiler) + public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); diff --git a/phpBB/phpbb/template/twig/tokenparser/define.php b/phpBB/phpbb/template/twig/tokenparser/defineparser.php index 4ea15388c4..8484f2e81a 100644 --- a/phpBB/phpbb/template/twig/tokenparser/define.php +++ b/phpBB/phpbb/template/twig/tokenparser/defineparser.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_define extends Twig_TokenParser +class defineparser extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -25,31 +19,38 @@ class phpbb_template_twig_tokenparser_define extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $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(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + if ($value instanceof \Twig_Node_Expression_Name) + { + // This would happen if someone improperly formed their DEFINE syntax + // e.g. <!-- DEFINE $VAR = foo --> + throw new \Twig_Error_Syntax('Invalid DEFINE', $token->getLine(), $this->parser->getFilename()); + } + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); } else { $capture = true; - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); $value = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); } - return new phpbb_template_twig_node_define($capture, $name, $value, $lineno, $this->getTag()); + return new \phpbb\template\twig\node\definenode($capture, $name, $value, $lineno, $this->getTag()); } - public function decideBlockEnd(Twig_Token $token) + public function decideBlockEnd(\Twig_Token $token) { return $token->test('ENDDEFINE'); } diff --git a/phpBB/phpbb/template/twig/tokenparser/event.php b/phpBB/phpbb/template/twig/tokenparser/event.php index e4dddd6dcc..8864e879f8 100644 --- a/phpBB/phpbb/template/twig/tokenparser/event.php +++ b/phpBB/phpbb/template/twig/tokenparser/event.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_event extends Twig_TokenParser +class event extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -25,14 +19,14 @@ class phpbb_template_twig_tokenparser_event extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return new phpbb_template_twig_node_event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); } /** diff --git a/phpBB/phpbb/template/twig/tokenparser/includecss.php b/phpBB/phpbb/template/twig/tokenparser/includecss.php index 6c24dda647..7bf4c610b1 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includecss.php +++ b/phpBB/phpbb/template/twig/tokenparser/includecss.php @@ -7,7 +7,9 @@ * */ -class phpbb_template_twig_tokenparser_includecss extends Twig_TokenParser +namespace phpbb\template\twig\tokenparser; + +class includecss extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -16,14 +18,14 @@ class phpbb_template_twig_tokenparser_includecss extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return new phpbb_template_twig_node_includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); } /** diff --git a/phpBB/phpbb/template/twig/tokenparser/includejs.php b/phpBB/phpbb/template/twig/tokenparser/includejs.php index b02b2f89ba..0e46915b86 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includejs.php +++ b/phpBB/phpbb/template/twig/tokenparser/includejs.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_includejs extends Twig_TokenParser +class includejs extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -25,14 +19,14 @@ class phpbb_template_twig_tokenparser_includejs extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return new phpbb_template_twig_node_includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); } /** diff --git a/phpBB/phpbb/template/twig/tokenparser/include.php b/phpBB/phpbb/template/twig/tokenparser/includeparser.php index 520f9fd1a0..d351f1b4cd 100644 --- a/phpBB/phpbb/template/twig/tokenparser/include.php +++ b/phpBB/phpbb/template/twig/tokenparser/includeparser.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include +class includeparser extends \Twig_TokenParser_Include { /** * Parses a token and returns a node. @@ -25,13 +19,13 @@ class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); list($variables, $only, $ignoreMissing) = $this->parseArguments(); - return new phpbb_template_twig_node_include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\includenode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); } /** diff --git a/phpBB/phpbb/template/twig/tokenparser/includephp.php b/phpBB/phpbb/template/twig/tokenparser/includephp.php index 13fe6de8a6..1b3d1742e3 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includephp.php +++ b/phpBB/phpbb/template/twig/tokenparser/includephp.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_includephp extends Twig_TokenParser +class includephp extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -25,23 +19,23 @@ class phpbb_template_twig_tokenparser_includephp extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); $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'); + $stream->expect(\Twig_Token::NAME_TYPE, 'missing'); $ignoreMissing = true; } - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return new phpbb_template_twig_node_includephp($expr, $this->parser->getEnvironment(), $ignoreMissing, $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\includephp($expr, $this->parser->getEnvironment(), $token->getLine(), $ignoreMissing, $this->getTag()); } /** diff --git a/phpBB/phpbb/template/twig/tokenparser/php.php b/phpBB/phpbb/template/twig/tokenparser/php.php index 197980a59a..b427969e2d 100644 --- a/phpBB/phpbb/template/twig/tokenparser/php.php +++ b/phpBB/phpbb/template/twig/tokenparser/php.php @@ -7,16 +7,10 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig\tokenparser; -class phpbb_template_twig_tokenparser_php extends Twig_TokenParser +class php extends \Twig_TokenParser { /** * Parses a token and returns a node. @@ -25,20 +19,20 @@ class phpbb_template_twig_tokenparser_php extends Twig_TokenParser * * @return Twig_NodeInterface A Twig_NodeInterface instance */ - public function parse(Twig_Token $token) + public function parse(\Twig_Token $token) { $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return new phpbb_template_twig_node_php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); } - public function decideEnd(Twig_Token $token) + public function decideEnd(\Twig_Token $token) { return $token->test('ENDPHP'); } @@ -51,5 +45,5 @@ class phpbb_template_twig_tokenparser_php extends Twig_TokenParser public function getTag() { return 'PHP'; - } + } } diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 1ed89d3ccc..83630f5992 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -7,19 +7,13 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\template\twig; /** * Twig Template class. * @package phpBB3 */ -class phpbb_template_twig extends phpbb_template_base +class twig extends \phpbb\template\base { /** * Path of the cache directory for the template @@ -31,6 +25,12 @@ class phpbb_template_twig extends phpbb_template_base private $cachepath = ''; /** + * phpBB path helper + * @var \phpbb\path_helper + */ + protected $path_helper; + + /** * phpBB root path * @var string */ @@ -44,20 +44,20 @@ class phpbb_template_twig extends phpbb_template_base /** * phpBB config instance - * @var phpbb_config + * @var \phpbb\config\config */ protected $config; /** * Current user - * @var phpbb_user + * @var \phpbb\user */ protected $user; /** * Extension manager. * - * @var phpbb_extension_manager + * @var \phpbb\extension\manager */ protected $extension_manager; @@ -71,32 +71,31 @@ class phpbb_template_twig extends phpbb_template_base /** * Constructor. * - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext php extension (typically 'php') - * @param phpbb_config $config - * @param phpbb_user $user - * @param phpbb_template_context $context template context - * @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked - * @param string $adm_relative_path relative path to adm directory + * @param \phpbb\path_helper $path_helper + * @param \phpbb\config\config $config + * @param \phpbb\user $user + * @param \phpbb\template\context $context template context + * @param \phpbb\extension\manager $extension_manager extension manager, if null then template events will not be invoked */ - public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null, $adm_relative_path = null) + public function __construct(\phpbb\path_helper $path_helper, $config, $user, \phpbb\template\context $context, \phpbb\extension\manager $extension_manager = null) { - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; + $this->path_helper = $path_helper; + $this->phpbb_root_path = $path_helper->get_phpbb_root_path(); + $this->php_ext = $path_helper->get_php_ext(); $this->config = $config; $this->user = $user; $this->context = $context; $this->extension_manager = $extension_manager; - $this->cachepath = $phpbb_root_path . 'cache/twig/'; + $this->cachepath = $this->phpbb_root_path . 'cache/twig/'; // Initiate the loader, __main__ namespace paths will be setup later in set_style_names() - $loader = new Twig_Loader_Filesystem(''); + $loader = new \phpbb\template\twig\loader(''); - $this->twig = new phpbb_template_twig_environment( + $this->twig = new \phpbb\template\twig\environment( $this->config, - ($this->extension_manager) ? $this->extension_manager->all_enabled() : array(), - $this->phpbb_root_path, + $this->path_helper, + $this->extension_manager, $loader, array( 'cache' => (defined('IN_INSTALL')) ? false : $this->cachepath, @@ -107,27 +106,27 @@ class phpbb_template_twig extends phpbb_template_base ); $this->twig->addExtension( - new phpbb_template_twig_extension( + new \phpbb\template\twig\extension( $this->context, $this->user ) ); - $lexer = new phpbb_template_twig_lexer($this->twig); + $lexer = new \phpbb\template\twig\lexer($this->twig); $this->twig->setLexer($lexer); // Add admin namespace - if ($adm_relative_path !== null && is_dir($this->phpbb_root_path . $adm_relative_path . 'style/')) + if ($this->path_helper->get_adm_relative_path() !== null && is_dir($this->phpbb_root_path . $this->path_helper->get_adm_relative_path() . 'style/')) { - $this->twig->getLoader()->setPaths($this->phpbb_root_path . $adm_relative_path . 'style/', 'admin'); + $this->twig->getLoader()->setPaths($this->phpbb_root_path . $this->path_helper->get_adm_relative_path() . 'style/', 'admin'); } } /** * Clear the cache * - * @return phpbb_template + * @return \phpbb\template\template */ public function clear_cache() { @@ -164,7 +163,7 @@ class phpbb_template_twig extends phpbb_template_base * @param array $style_directories The directories to add style paths for * E.g. array('ext/foo/bar/styles', 'styles') * Default: array('styles') (phpBB's style directory) - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function set_style($style_directories = array('styles')) { @@ -181,11 +180,15 @@ class phpbb_template_twig extends phpbb_template_base { foreach ($names as $name) { - $path = $this->phpbb_root_path . trim($directory, '/') . "/{$name}/template/"; + $path = $this->phpbb_root_path . trim($directory, '/') . "/{$name}/"; + $template_path = $path . 'template/'; - if (is_dir($path)) + if (is_dir($template_path)) { - $paths[] = $path; + // Add the base style directory as a safe directory + $this->twig->getLoader()->addSafeDirectory($path); + + $paths[] = $template_path; } } } @@ -221,7 +224,7 @@ class phpbb_template_twig extends phpbb_template_base $this->twig->getLoader()->setPaths($paths); // Add all namespaces for all extensions - if ($this->extension_manager instanceof phpbb_extension_manager) + if ($this->extension_manager instanceof \phpbb\extension\manager) { $names[] = 'all'; @@ -233,11 +236,15 @@ class phpbb_template_twig extends phpbb_template_base foreach ($names as $style_name) { - $ext_style_path = $ext_path . 'styles/' . $style_name . '/template'; + $ext_style_path = $ext_path . 'styles/' . $style_name . '/'; + $ext_style_template_path = $ext_style_path . 'template/'; - if (is_dir($ext_style_path)) + if (is_dir($ext_style_template_path)) { - $paths[] = $ext_style_path; + // Add the base style directory as a safe directory + $this->twig->getLoader()->addSafeDirectory($ext_style_path); + + $paths[] = $ext_style_template_path; } } @@ -256,7 +263,7 @@ class phpbb_template_twig extends phpbb_template_base * This function calls hooks. * * @param string $handle Handle to display - * @return phpbb_template $this + * @return \phpbb\template\template $this */ public function display($handle) { @@ -278,7 +285,7 @@ class phpbb_template_twig extends phpbb_template_base * @param string $handle Handle to operate on * @param string $template_var Template variable to assign compiled handle to * @param bool $return_content If true return compiled handle, otherwise assign to $template_var - * @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this + * @return \phpbb\template\template|string if $return_content is true return string of the compiled handle, otherwise return $this */ public function assign_display($handle, $template_var = '', $return_content = true) { @@ -304,7 +311,7 @@ class phpbb_template_twig extends phpbb_template_base $vars = array_merge( $context_vars['.'][0], // To get normal vars array( - 'definition' => new phpbb_template_twig_definition(), + 'definition' => new \phpbb\template\twig\definition(), 'user' => $this->user, 'loops' => $context_vars, // To get loops ) diff --git a/phpBB/phpbb/tree/nestedset.php b/phpBB/phpbb/tree/nestedset.php index 4d851a87a8..9aaee9e468 100644 --- a/phpBB/phpbb/tree/nestedset.php +++ b/phpBB/phpbb/tree/nestedset.php @@ -7,20 +7,14 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\tree; -abstract class phpbb_tree_nestedset implements phpbb_tree_interface +abstract class nestedset implements \phpbb\tree\tree_interface { - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var phpbb_lock_db */ + /** @var \phpbb\lock\db */ protected $lock; /** @var string */ @@ -58,15 +52,15 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface /** * Construct * - * @param phpbb_db_driver $db Database connection - * @param phpbb_lock_db $lock Lock class used to lock the table when moving forums around + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\lock\db $lock Lock class used to lock the table when moving forums around * @param string $table_name Table name * @param string $message_prefix Prefix for the messages thrown by exceptions * @param string $sql_where Additional SQL restrictions for the queries * @param array $item_basic_data Array with basic item data that is stored in item_parents * @param array $columns Array with column names to overwrite */ - public function __construct(phpbb_db_driver $db, phpbb_lock_db $lock, $table_name, $message_prefix = '', $sql_where = '', $item_basic_data = array(), $columns = array()) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\lock\db $lock, $table_name, $message_prefix = '', $sql_where = '', $item_basic_data = array(), $columns = array()) { $this->db = $db; $this->lock = $lock; @@ -116,7 +110,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!$this->lock->acquire()) { - throw new RuntimeException($this->message_prefix . 'LOCK_FAILED_ACQUIRE'); + throw new \RuntimeException($this->message_prefix . 'LOCK_FAILED_ACQUIRE'); } return true; @@ -184,7 +178,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface $item_id = (int) $item_id; if (!$item_id) { - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $items = $this->get_subtree_data($item_id); @@ -192,7 +186,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (empty($items) || !isset($items[$item_id])) { - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $this->remove_subset($item_ids, $items[$item_id]); @@ -242,7 +236,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!$item) { $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } /** @@ -364,7 +358,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!$current_parent_id) { - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $this->acquire_lock(); @@ -373,7 +367,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!isset($item_data[$current_parent_id])) { $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $current_parent = $item_data[$current_parent_id]; @@ -389,7 +383,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (in_array($new_parent_id, $move_items)) { $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); } $diff = sizeof($move_items) * 2; @@ -413,7 +407,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface { $this->db->sql_transaction('rollback'); $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); } $new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true); @@ -470,7 +464,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!$item_id) { - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $this->acquire_lock(); @@ -479,7 +473,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (!isset($item_data[$item_id])) { $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_ITEM'); } $item = $item_data[$item_id]; @@ -488,7 +482,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface if (in_array($new_parent_id, $move_items)) { $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); } $diff = sizeof($move_items) * 2; @@ -512,7 +506,7 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface { $this->db->sql_transaction('rollback'); $this->lock->release(); - throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); + throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT'); } $new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true); @@ -670,6 +664,32 @@ abstract class phpbb_tree_nestedset implements phpbb_tree_interface } /** + * Get all items from the tree + * + * @param bool $order_asc Order the items ascending by their left_id + * @return array Array of items (containing all columns from the item table) + * ID => Item data + */ + public function get_all_tree_data($order_asc = true) + { + $rows = array(); + + $sql = 'SELECT * + FROM ' . $this->table_name . ' ' . + $this->get_sql_where('WHERE') . ' + ORDER BY ' . $this->column_left_id . ' ' . ($order_asc ? 'ASC' : 'DESC'); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $rows[(int) $row[$this->column_item_id]] = $row; + } + $this->db->sql_freeresult($result); + + return $rows; + } + + /** * Remove a subset from the nested set * * @param array $subset_items Subset of items to remove diff --git a/phpBB/phpbb/tree/nestedset_forum.php b/phpBB/phpbb/tree/nestedset_forum.php index ff09ef55d0..5973b0b6d9 100644 --- a/phpBB/phpbb/tree/nestedset_forum.php +++ b/phpBB/phpbb/tree/nestedset_forum.php @@ -7,24 +7,18 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\tree; -class phpbb_tree_nestedset_forum extends phpbb_tree_nestedset +class nestedset_forum extends \phpbb\tree\nestedset { /** * Construct * - * @param phpbb_db_driver $db Database connection - * @param phpbb_lock_db $lock Lock class used to lock the table when moving forums around + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\lock\db $lock Lock class used to lock the table when moving forums around * @param string $table_name Table name */ - public function __construct(phpbb_db_driver $db, phpbb_lock_db $lock, $table_name) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\lock\db $lock, $table_name) { parent::__construct( $db, diff --git a/phpBB/phpbb/tree/interface.php b/phpBB/phpbb/tree/tree_interface.php index cc8aab2115..90ec27e024 100644 --- a/phpBB/phpbb/tree/interface.php +++ b/phpBB/phpbb/tree/tree_interface.php @@ -7,15 +7,9 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb\tree; -interface phpbb_tree_interface +interface tree_interface { /** * Inserts an item into the database table and into the tree. @@ -79,7 +73,7 @@ interface phpbb_tree_interface /** * Change parent item * - * Moves the item to the bottom of the new parent's list of children + * Moves the item to the bottom of the new \parent's list of children * * @param int $item_id The item to be moved * @param int $new_parent_id The new parent item diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index 36120798e5..18b7a3d096 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -7,13 +7,7 @@ * */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * Base user class @@ -23,7 +17,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_user extends phpbb_session +class user extends \phpbb\session { var $lang = array(); var $help = array(); @@ -42,7 +36,7 @@ class phpbb_user extends phpbb_session var $img_array = array(); // Able to add new options (up to id 31) - var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); + var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); /** * Constructor to set the lang path @@ -149,9 +143,17 @@ class phpbb_user extends phpbb_session * that are absolutely needed globally using this * event. Use local events otherwise. * @var mixed style_id Style we are going to display - * @since 3.1-A1 + * @since 3.1.0-a1 */ - $vars = array('user_data', 'user_lang_name', 'user_date_format', 'user_timezone', 'lang_set', 'lang_set_ext', 'style_id'); + $vars = array( + 'user_data', + 'user_lang_name', + 'user_date_format', + 'user_timezone', + 'lang_set', + 'lang_set_ext', + 'style_id', + ); extract($phpbb_dispatcher->trigger_event('core.user_setup', compact($vars))); $this->data = $user_data; @@ -160,12 +162,12 @@ class phpbb_user extends phpbb_session try { - $this->timezone = new DateTimeZone($user_timezone); + $this->timezone = new \DateTimeZone($user_timezone); } - catch (Exception $e) + catch (\Exception $e) { // If the timezone the user has selected is invalid, we fall back to UTC. - $this->timezone = new DateTimeZone('UTC'); + $this->timezone = new \DateTimeZone('UTC'); } // We include common language file here to not load it every time a custom language file is included @@ -189,7 +191,7 @@ class phpbb_user extends phpbb_session unset($lang_set_ext); $style_request = request_var('style', 0); - if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START')) + if ($style_request && (!$config['override_user_style'] || $auth->acl_get('a_styles')) && !defined('ADMIN_START')) { global $SID, $_EXTRA_URL; @@ -210,6 +212,19 @@ class phpbb_user extends phpbb_session $this->style = $db->sql_fetchrow($result); $db->sql_freeresult($result); + // Fallback to user's standard style + if (!$this->style && $style_id != $this->data['user_style']) + { + $style_id = $this->data['user_style']; + + $sql = 'SELECT * + FROM ' . STYLES_TABLE . " s + WHERE s.style_id = $style_id"; + $result = $db->sql_query($sql, 3600); + $this->style = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + // User has wrong style if (!$this->style && $style_id == $this->data['user_style']) { @@ -341,7 +356,6 @@ class phpbb_user extends phpbb_session } } - // Does the user need to change their password? If so, redirect to the // ucp profile reg_details page ... of course do not redirect if we're already in the ucp if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) @@ -625,18 +639,20 @@ class phpbb_user extends phpbb_session else if ($this->lang_name == basename($config['default_lang'])) { // Fall back to the English Language + $reset_lang_name = $this->lang_name; $this->lang_name = 'en'; $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); + $this->lang_name = $reset_lang_name; } else if ($this->lang_name == $this->data['user_lang']) { // Fall back to the board default language + $reset_lang_name = $this->lang_name; $this->lang_name = basename($config['default_lang']); $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); + $this->lang_name = $reset_lang_name; } - // Reset the lang name - $this->lang_name = (file_exists($lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); return; } @@ -671,27 +687,27 @@ class phpbb_user extends phpbb_session if (!isset($utc)) { - $utc = new DateTimeZone('UTC'); + $utc = new \DateTimeZone('UTC'); } - $time = new phpbb_datetime($this, "@$gmepoch", $utc); + $time = new \phpbb\datetime($this, "@$gmepoch", $utc); $time->setTimezone($this->timezone); return $time->format($format, $forcedate); } /** - * Create a phpbb_datetime object in the context of the current user + * Create a \phpbb\datetime object in the context of the current user * * @since 3.1 * @param string $time String in a format accepted by strtotime(). * @param DateTimeZone $timezone Time zone of the time. - * @return phpbb_datetime Date time object linked to the current users locale + * @return \phpbb\datetime Date time object linked to the current users locale */ - public function create_datetime($time = 'now', DateTimeZone $timezone = null) + public function create_datetime($time = 'now', \DateTimeZone $timezone = null) { $timezone = $timezone ?: $this->timezone; - return new phpbb_datetime($this, $time, $timezone); + return new \phpbb\datetime($this, $time, $timezone); } /** @@ -702,10 +718,10 @@ class phpbb_user extends phpbb_session * @param DateTimeZone $timezone Timezone of the date/time, falls back to timezone of current user * @return int Returns the unix timestamp */ - public function get_timestamp_from_format($format, $time, DateTimeZone $timezone = null) + public function get_timestamp_from_format($format, $time, \DateTimeZone $timezone = null) { $timezone = $timezone ?: $this->timezone; - $date = DateTime::createFromFormat($format, $time, $timezone); + $date = \DateTime::createFromFormat($format, $time, $timezone); return ($date !== false) ? $date->format('U') : false; } diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php index 37bf9648c1..9179572277 100644 --- a/phpBB/phpbb/user_loader.php +++ b/phpBB/phpbb/user_loader.php @@ -7,12 +7,7 @@ * */ -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} +namespace phpbb; /** * User loader class @@ -22,9 +17,9 @@ if (!defined('IN_PHPBB')) * have to query the same user multiple times in * different services. */ -class phpbb_user_loader +class user_loader { - /** @var phpbb_db_driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db = null; /** @var string */ @@ -46,12 +41,12 @@ class phpbb_user_loader /** * User loader constructor * - * @param phpbb_db_driver $db A database connection + * @param \phpbb\db\driver\driver_interface $db A database connection * @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $php_ext php file extension * @param string $users_table The name of the database table (phpbb_users) */ - public function __construct(phpbb_db_driver $db, $phpbb_root_path, $php_ext, $users_table) + public function __construct(\phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $users_table) { $this->db = $db; diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php new file mode 100644 index 0000000000..e2fdf6ce63 --- /dev/null +++ b/phpBB/phpbb/version_helper.php @@ -0,0 +1,271 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb; + +/** + * Class to handle version checking and comparison + */ +class version_helper +{ + /** + * @var string Host + */ + protected $host = 'version.phpbb.com'; + + /** + * @var string Path to file + */ + protected $path = '/phpbb'; + + /** + * @var string File name + */ + protected $file = 'versions.json'; + + /** + * @var string Current version installed + */ + protected $current_version; + + /** + * @var null|string Null to not force stability, 'unstable' or 'stable' to + * force the corresponding stability + */ + protected $force_stability; + + /** @var \phpbb\cache\service */ + protected $cache; + + /** @var \phpbb\config\config */ + protected $config; + + /** @var \phpbb\user */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\cache\service $cache + * @param \phpbb\config\config $config + * @param \phpbb\user $user + */ + public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\user $user) + { + $this->cache = $cache; + $this->config = $config; + $this->user = $user; + + if (defined('PHPBB_QA')) + { + $this->force_stability = 'unstable'; + } + + $this->current_version = $this->config['version']; + } + + /** + * Set location to the file + * + * @param string $host Host (e.g. version.phpbb.com) + * @param string $path Path to file (e.g. /phpbb) + * @param string $file File name (Default: versions.json) + * @return version_helper + */ + public function set_file_location($host, $path, $file = 'versions.json') + { + $this->host = $host; + $this->path = $path; + $this->file = $file; + + return $this; + } + + /** + * Set current version + * + * @param string $version The current version + * @return version_helper + */ + public function set_current_version($version) + { + $this->current_version = $version; + + return $this; + } + + /** + * Over-ride the stability to force check to include unstable versions + * + * @param null|string Null to not force stability, 'unstable' or 'stable' to + * force the corresponding stability + * @return version_helper + */ + public function force_stability($stability) + { + $this->force_stability = $stability; + + return $this; + } + + /** + * Wrapper for version_compare() that allows using uppercase A and B + * for alpha and beta releases. + * + * See http://www.php.net/manual/en/function.version-compare.php + * + * @param string $version1 First version number + * @param string $version2 Second version number + * @param string $operator Comparison operator (optional) + * + * @return mixed Boolean (true, false) if comparison operator is specified. + * Integer (-1, 0, 1) otherwise. + */ + public function compare($version1, $version2, $operator = null) + { + return phpbb_version_compare($version1, $version2, $operator); + } + + /** + * Check whether or not a version is "stable" + * + * Stable means only numbers OR a pl release + * + * @param string $version + * @return bool Bool true or false + */ + public function is_stable($version) + { + $matches = false; + preg_match('/^[\d\.]+/', $version, $matches); + + if (empty($matches[0])) + { + return false; + } + + return $this->compare($version, $matches[0], '>='); + } + + /** + * Gets the latest version for the current branch the user is on + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @return string + * @throws \RuntimeException + */ + public function get_latest_on_current_branch($force_update = false) + { + $versions = $this->get_versions_matching_stability($force_update); + + $self = $this; + $current_version = $this->current_version; + + // Filter out any versions less than to the current version + $versions = array_filter($versions, function($data) use ($self, $current_version) { + return $self->compare($data['current'], $current_version, '>='); + }); + + // Get the lowest version from the previous list. + return array_reduce($versions, function($value, $data) use ($self) { + if ($value === null || $self->compare($data['current'], $value, '<')) + { + return $data['current']; + } + + return $value; + }); + } + + /** + * Obtains the latest version information + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @return string + * @throws \RuntimeException + */ + public function get_suggested_updates($force_update = false) + { + $versions = $this->get_versions_matching_stability($force_update); + + $self = $this; + $current_version = $this->current_version; + + // Filter out any versions less than or equal to the current version + return array_filter($versions, function($data) use ($self, $current_version) { + return $self->compare($data['current'], $current_version, '>'); + }); + } + + /** + * Obtains the latest version information matching the stability of the current install + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @return string Version info + * @throws \RuntimeException + */ + public function get_versions_matching_stability($force_update = false) + { + $info = $this->get_versions($force_update); + + if ($this->force_stability !== null) + { + return ($this->force_stability === 'unstable') ? $info['unstable'] : $info['stable']; + } + + return ($this->is_stable($this->current_version)) ? $info['stable'] : $info['unstable']; + } + + /** + * Obtains the latest version information + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @return string Version info, includes stable and unstable data + * @throws \RuntimeException + */ + public function get_versions($force_update = false) + { + $cache_file = 'versioncheck_' . $this->host . $this->path . $this->file; + + $info = $this->cache->get($cache_file); + + if ($info === false || $force_update) + { + $errstr = $errno = ''; + $info = get_remote_file($this->host, $this->path, $this->file, $errstr, $errno); + + if (!empty($errstr)) + { + throw new \RuntimeException($errstr); + } + + $info = json_decode($info, true); + + if (empty($info['stable']) || empty($info['unstable'])) + { + $this->user->add_lang('acp/common'); + + throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); + } + + // Replace & with & on announcement links + foreach ($info as $stability => $branches) + { + foreach ($branches as $branch => $branch_data) + { + $info[$stability][$branch]['announcement'] = str_replace('&', '&', $branch_data['announcement']); + } + } + + $this->cache->put($cache_file, $info, 86400); // 24 hours + } + + return $info; + } +} |