diff options
Diffstat (limited to 'phpBB/phpbb')
98 files changed, 2780 insertions, 1036 deletions
diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php index 20c60364d8..65249275d4 100644 --- a/phpBB/phpbb/auth/auth.php +++ b/phpBB/phpbb/auth/auth.php @@ -1043,7 +1043,7 @@ class auth { if (strpos($auth_options, '%') !== false) { - $sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->any_char, $auth_options)); + $sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->get_any_char(), $auth_options)); } else { @@ -1074,7 +1074,7 @@ class auth { if (strpos($option, '%') !== false) { - $sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->any_char, $option)); + $sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->get_any_char(), $option)); } else { diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php index fe1a376cfe..023cf402ca 100644 --- a/phpBB/phpbb/auth/provider/oauth/token_storage.php +++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php @@ -266,7 +266,7 @@ class token_storage implements TokenStorageInterface // Ensure that the token was serialized/unserialized correctly if (!($token instanceof TokenInterface)) { - $this->clearToken(); + $this->clearToken($data['provider']); throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED'); } diff --git a/phpBB/phpbb/auth/provider_collection.php b/phpBB/phpbb/auth/provider_collection.php index fe32a34e12..a74a2135dc 100644 --- a/phpBB/phpbb/auth/provider_collection.php +++ b/phpBB/phpbb/auth/provider_collection.php @@ -29,7 +29,7 @@ class provider_collection extends \phpbb\di\service_collection * @param ContainerInterface $container Container object * @param \phpbb\config\config $config phpBB config */ - public function __construct($container, \phpbb\config\config $config) + public function __construct(ContainerInterface $container, \phpbb\config\config $config) { $this->container = $container; $this->config = $config; diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index c43004f340..edc5941602 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -19,6 +19,32 @@ namespace phpbb\avatar\driver; class upload extends \phpbb\avatar\driver\driver { /** + * @var \phpbb\mimetype\guesser + */ + protected $mimetype_guesser; + + /** + * Construct a driver 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_path_helper $path_helper phpBB path helper + * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser + * @param \phpbb\cache\driver\driver_interface $cache Cache driver + */ + public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) + { + $this->config = $config; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->path_helper = $path_helper; + $this->mimetype_guesser = $mimetype_guesser; + $this->cache = $cache; + } + + /** * {@inheritdoc} */ public function get_data($row, $ignore_config = false) @@ -70,7 +96,7 @@ class upload extends \phpbb\avatar\driver\driver if (!empty($upload_file['name'])) { - $file = $upload->form_upload('avatar_upload_file'); + $file = $upload->form_upload('avatar_upload_file', $this->mimetype_guesser); } else if (!empty($this->config['allow_avatar_remote_upload']) && !empty($url)) { @@ -100,7 +126,7 @@ class upload extends \phpbb\avatar\driver\driver return false; } - $file = $upload->remote_upload($url); + $file = $upload->remote_upload($url, $this->mimetype_guesser); } else { diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php index c9aa6525c0..d6bf150384 100644 --- a/phpBB/phpbb/cache/service.php +++ b/phpBB/phpbb/cache/service.php @@ -305,7 +305,7 @@ class service { if (($bots = $this->driver->get('_bots')) === false) { - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'mssql': case 'mssql_odbc': @@ -316,13 +316,6 @@ class service ORDER BY LEN(bot_agent) DESC'; break; - case 'firebird': - $sql = 'SELECT user_id, bot_agent, bot_ip - FROM ' . BOTS_TABLE . ' - WHERE bot_active = 1 - ORDER BY CHAR_LENGTH(bot_agent) DESC'; - break; - // LENGTH supported by MySQL, IBM DB2 and Oracle for sure... default: $sql = 'SELECT user_id, bot_agent, bot_ip diff --git a/phpBB/phpbb/config_php_file.php b/phpBB/phpbb/config_php_file.php new file mode 100644 index 0000000000..1a562e470d --- /dev/null +++ b/phpBB/phpbb/config_php_file.php @@ -0,0 +1,175 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb; + +class config_php_file +{ + /** @var string phpBB Root Path */ + protected $phpbb_root_path; + + /** @var string php file extension */ + protected $php_ext; + + /** + * Indicates whether the php config file has been loaded. + * + * @var bool + */ + protected $config_loaded = false; + + /** + * The content of the php config file + * + * @var array + */ + protected $config_data = array(); + + /** + * The path to the config file. (Default: $phpbb_root_path . 'config.' . $php_ext) + * + * @var string + */ + protected $config_file; + + private $defined_vars; + + /** + * Constructor + * + * @param string $phpbb_root_path phpBB Root Path + * @param string $php_ext php file extension + */ + function __construct($phpbb_root_path, $php_ext) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->config_file = $this->phpbb_root_path . 'config.' . $this->php_ext; + } + + /** + * Set the path to the config file. + * + * @param string $config_file + */ + public function set_config_file($config_file) + { + $this->config_file = $config_file; + $this->config_loaded = false; + } + + /** + * Returns an associative array containing the variables defined by the config file. + * + * @return bool|array Return the content of the config file or false if the file does not exists. + */ + public function get_all() + { + if (!$this->load_config_file()) + { + return false; + } + + return $this->config_data; + } + + /** + * Return the value of a variable defined into the config.php file and false if the variable does not exist. + * + * @param string $variable The name of the variable + * @return mixed + */ + public function get($variable) + { + if (!$this->load_config_file()) + { + return false; + } + + return isset($this->config_data[$variable]) ? $this->config_data[$variable] : false; + } + + /** + * Load the config file and store the information. + * + * @return bool True if the file was correctly loaded, false otherwise. + */ + protected function load_config_file() + { + if (!$this->config_loaded) + { + if (file_exists($this->config_file)) + { + $this->defined_vars = get_defined_vars(); + + require($this->config_file); + $this->config_data = array_diff_key(get_defined_vars(), $this->defined_vars); + + $this->config_loaded = true; + } + else + { + return false; + } + } + + return true; + } + + /** + * Convert either 3.0 dbms or 3.1 db driver class name to 3.1 db driver class name. + * + * If $dbms is a valid 3.1 db driver class name, returns it unchanged. + * Otherwise prepends phpbb\db\driver\ to the dbms to convert a 3.0 dbms + * to 3.1 db driver class name. + * + * @param string $dbms dbms parameter + * @return string driver class + * @throws \RuntimeException + */ + public function convert_30_dbms_to_31($dbms) + { + // Note: this check is done first because mysqli extension + // supplies a mysqli class, and class_exists($dbms) would return + // true for mysqli class. + // However, per the docblock any valid 3.1 driver name should be + // recognized by this function, and have priority over 3.0 dbms. + if (strpos($dbms, 'phpbb\db\driver') === false && class_exists('phpbb\db\driver\\' . $dbms)) + { + return 'phpbb\db\driver\\' . $dbms; + } + + if (class_exists($dbms)) + { + // Additionally we could check that $dbms extends phpbb\db\driver\driver. + // http://php.net/manual/en/class.reflectionclass.php + // Beware of possible performance issues: + // http://stackoverflow.com/questions/294582/php-5-reflection-api-performance + // We could check for interface implementation in all paths or + // only when we do not prepend phpbb\db\driver\. + + /* + $reflection = new \ReflectionClass($dbms); + + if ($reflection->isSubclassOf('phpbb\db\driver\driver')) + { + return $dbms; + } + */ + + return $dbms; + } + + throw new \RuntimeException("You have specified an invalid dbms driver: $dbms"); + } +} diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index b1f0635913..bc4897af18 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -17,7 +17,6 @@ use Symfony\Component\Console\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\TaggedContainerInterface; class application extends \Symfony\Component\Console\Application { @@ -38,9 +37,26 @@ class application extends \Symfony\Component\Console\Application */ public function __construct($name, $version, \phpbb\user $user) { + $this->user = $user; + parent::__construct($name, $version); + } - $this->user = $user; + /** + * {@inheritdoc} + */ + protected function getDefaultInputDefinition() + { + $input_definition = parent::getDefaultInputDefinition(); + + $input_definition->addOption(new InputOption( + 'safe-mode', + null, + InputOption::VALUE_NONE, + $this->user->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE') + )); + + return $input_definition; } /** @@ -73,14 +89,13 @@ class application extends \Symfony\Component\Console\Application /** * Register a set of commands from the container * - * @param TaggedContainerInterface $container The container - * @param string $tag The tag used to register the commands + * @param \phpbb\di\service_collection $command_collection The console service collection */ - public function register_container_commands(TaggedContainerInterface $container, $tag = 'console.command') + public function register_container_commands(\phpbb\di\service_collection $command_collection) { - foreach($container->findTaggedServiceIds($tag) as $id => $void) + foreach ($command_collection as $service_command) { - $this->add($container->get($id)); + $this->add($service_command); } } diff --git a/phpBB/phpbb/console/command/cache/purge.php b/phpBB/phpbb/console/command/cache/purge.php index 379d2aa1ca..ec8229200c 100644 --- a/phpBB/phpbb/console/command/cache/purge.php +++ b/phpBB/phpbb/console/command/cache/purge.php @@ -29,31 +29,27 @@ class purge extends \phpbb\console\command\command /** @var \phpbb\log\log */ protected $log; - /** @var \phpbb\user */ - protected $user; - /** @var \phpbb\config\config */ protected $config; /** * Constructor * + * @param \phpbb\user $user User instance * @param \phpbb\cache\driver\driver_interface $cache Cache instance * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\auth\auth $auth Auth instance * @param \phpbb\log\log $log Logger instance - * @param \phpbb\user $user User instance * @param \phpbb\config\config $config Config instance */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\auth\auth $auth, \phpbb\log\log $log, \phpbb\user $user, \phpbb\config\config $config) + public function __construct(\phpbb\user $user, \phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\auth\auth $auth, \phpbb\log\log $log, \phpbb\config\config $config) { $this->cache = $cache; $this->db = $db; $this->auth = $auth; $this->log = $log; - $this->user = $user; $this->config = $config; - parent::__construct(); + parent::__construct($user); } /** @@ -63,7 +59,7 @@ class purge extends \phpbb\console\command\command { $this ->setName('cache:purge') - ->setDescription('Purge the cache.') + ->setDescription($this->user->lang('PURGE_CACHE')) ; } diff --git a/phpBB/phpbb/console/command/command.php b/phpBB/phpbb/console/command/command.php index d3449c0c38..638c989da2 100644 --- a/phpBB/phpbb/console/command/command.php +++ b/phpBB/phpbb/console/command/command.php @@ -15,4 +15,17 @@ namespace phpbb\console\command; abstract class command extends \Symfony\Component\Console\Command\Command { + /** @var \phpbb\user */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\user $user User instance (mostly for translation) + */ + public function __construct(\phpbb\user $user) + { + $this->user = $user; + parent::__construct(); + } } diff --git a/phpBB/phpbb/console/command/config/command.php b/phpBB/phpbb/console/command/config/command.php index de3fbd7fa7..f0ad5d4d19 100644 --- a/phpBB/phpbb/console/command/config/command.php +++ b/phpBB/phpbb/console/command/config/command.php @@ -17,10 +17,10 @@ abstract class command extends \phpbb\console\command\command /** @var \phpbb\config\config */ protected $config; - function __construct(\phpbb\config\config $config) + function __construct(\phpbb\user $user, \phpbb\config\config $config) { $this->config = $config; - parent::__construct(); + parent::__construct($user); } } diff --git a/phpBB/phpbb/console/command/config/delete.php b/phpBB/phpbb/console/command/config/delete.php index 1310bb18b4..efd276d7e3 100644 --- a/phpBB/phpbb/console/command/config/delete.php +++ b/phpBB/phpbb/console/command/config/delete.php @@ -25,11 +25,11 @@ class delete extends command { $this ->setName('config:delete') - ->setDescription('Deletes a configuration option') + ->setDescription($this->user->lang('CLI_DESCRIPTION_DELETE_CONFIG')) ->addArgument( 'key', InputArgument::REQUIRED, - "The configuration option's name" + $this->user->lang('CLI_CONFIG_OPTION_NAME') ) ; } @@ -53,11 +53,11 @@ class delete extends command { $this->config->delete($key); - $output->writeln("<info>Successfully deleted config $key</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_CONFIG_DELETE_SUCCESS', $key) . '</info>'); } else { - $output->writeln("<error>Config $key does not exist</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_CONFIG_NOT_EXISTS', $key) . '</error>'); } } } diff --git a/phpBB/phpbb/console/command/config/get.php b/phpBB/phpbb/console/command/config/get.php index ee8c65110e..9c03b49a3d 100644 --- a/phpBB/phpbb/console/command/config/get.php +++ b/phpBB/phpbb/console/command/config/get.php @@ -26,17 +26,17 @@ class get extends command { $this ->setName('config:get') - ->setDescription("Gets a configuration option's value") + ->setDescription($this->user->lang('CLI_DESCRIPTION_GET_CONFIG')) ->addArgument( 'key', InputArgument::REQUIRED, - "The configuration option's name" + $this->user->lang('CLI_CONFIG_OPTION_NAME') ) ->addOption( 'no-newline', null, InputOption::VALUE_NONE, - 'Set this option if the value should be printed without a new line at the end.' + $this->user->lang('CLI_CONFIG_PRINT_WITHOUT_NEWLINE') ) ; } @@ -66,7 +66,7 @@ class get extends command } else { - $output->writeln("<error>Could not get config $key</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_CONFIG_NOT_EXISTS', $key) . '</error>'); } } } diff --git a/phpBB/phpbb/console/command/config/increment.php b/phpBB/phpbb/console/command/config/increment.php index 21f0660e61..b4d7438b66 100644 --- a/phpBB/phpbb/console/command/config/increment.php +++ b/phpBB/phpbb/console/command/config/increment.php @@ -26,22 +26,22 @@ class increment extends command { $this ->setName('config:increment') - ->setDescription("Increments a configuration option's value") + ->setDescription($this->user->lang('CLI_DESCRIPTION_INCREMENT_CONFIG')) ->addArgument( 'key', InputArgument::REQUIRED, - "The configuration option's name" + $this->user->lang('CLI_CONFIG_OPTION_NAME') ) ->addArgument( 'increment', InputArgument::REQUIRED, - 'Amount to increment by' + $this->user->lang('CLI_CONFIG_INCREMENT_BY') ) ->addOption( 'dynamic', 'd', InputOption::VALUE_NONE, - 'Set this option if the configuration option changes too frequently to be efficiently cached.' + $this->user->lang('CLI_CONFIG_CANNOT_CACHED') ) ; } @@ -65,6 +65,6 @@ class increment extends command $this->config->increment($key, $increment, $use_cache); - $output->writeln("<info>Successfully incremented config $key</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_CONFIG_INCREMENT_SUCCESS', $key) . '</info>'); } } diff --git a/phpBB/phpbb/console/command/config/set.php b/phpBB/phpbb/console/command/config/set.php index 587b7fb0de..695de31013 100644 --- a/phpBB/phpbb/console/command/config/set.php +++ b/phpBB/phpbb/console/command/config/set.php @@ -26,22 +26,22 @@ class set extends command { $this ->setName('config:set') - ->setDescription("Sets a configuration option's value") + ->setDescription($this->user->lang('CLI_DESCRIPTION_SET_CONFIG')) ->addArgument( 'key', InputArgument::REQUIRED, - "The configuration option's name" + $this->user->lang('CLI_CONFIG_OPTION_NAME') ) ->addArgument( 'value', InputArgument::REQUIRED, - 'New configuration value, use 0 and 1 to specify boolean values' + $this->user->lang('CLI_CONFIG_NEW') ) ->addOption( 'dynamic', 'd', InputOption::VALUE_NONE, - 'Set this option if the configuration option changes too frequently to be efficiently cached.' + $this->user->lang('CLI_CONFIG_CANNOT_CACHED') ) ; } @@ -65,6 +65,6 @@ class set extends command $this->config->set($key, $value, $use_cache); - $output->writeln("<info>Successfully set config $key</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_CONFIG_SET_SUCCESS', $key) . '</info>'); } } diff --git a/phpBB/phpbb/console/command/config/set_atomic.php b/phpBB/phpbb/console/command/config/set_atomic.php index a7a52155f9..e8c69a0885 100644 --- a/phpBB/phpbb/console/command/config/set_atomic.php +++ b/phpBB/phpbb/console/command/config/set_atomic.php @@ -26,27 +26,27 @@ class set_atomic extends command { $this ->setName('config:set-atomic') - ->setDescription("Sets a configuration option's value only if the old matches the current value.") + ->setDescription($this->user->lang('CLI_DESCRIPTION_SET_ATOMIC_CONFIG')) ->addArgument( 'key', InputArgument::REQUIRED, - "The configuration option's name" + $this->user->lang('CLI_CONFIG_OPTION_NAME') ) ->addArgument( 'old', InputArgument::REQUIRED, - 'Current configuration value, use 0 and 1 to specify boolean values' + $this->user->lang('CLI_CONFIG_CURRENT') ) ->addArgument( 'new', InputArgument::REQUIRED, - 'New configuration value, use 0 and 1 to specify boolean values' + $this->user->lang('CLI_CONFIG_NEW') ) ->addOption( 'dynamic', 'd', InputOption::VALUE_NONE, - 'Set this option if the configuration option changes too frequently to be efficiently cached.' + $this->user->lang('CLI_CONFIG_CANNOT_CACHED') ) ; } @@ -72,12 +72,12 @@ class set_atomic extends command if ($this->config->set_atomic($key, $old_value, $new_value, $use_cache)) { - $output->writeln("<info>Successfully set config $key</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_CONFIG_SET_SUCCESS', $key) . '</info>'); return 0; } else { - $output->writeln("<error>Could not set config $key</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_CONFIG_SET_FAILURE', $key) . '</error>'); return 1; } } diff --git a/phpBB/phpbb/console/command/cron/cron_list.php b/phpBB/phpbb/console/command/cron/cron_list.php index 4f4228d9b3..c515fd9e80 100644 --- a/phpBB/phpbb/console/command/cron/cron_list.php +++ b/phpBB/phpbb/console/command/cron/cron_list.php @@ -20,20 +20,16 @@ class cron_list extends \phpbb\console\command\command /** @var \phpbb\cron\manager */ protected $cron_manager; - /** @var \phpbb\user */ - protected $user; - /** * Constructor * - * @param \phpbb\cron\manager $cron_manager Cron manager * @param \phpbb\user $user User instance + * @param \phpbb\cron\manager $cron_manager Cron manager */ - public function __construct(\phpbb\cron\manager $cron_manager, \phpbb\user $user) + public function __construct(\phpbb\user $user, \phpbb\cron\manager $cron_manager) { $this->cron_manager = $cron_manager; - $this->user = $user; - parent::__construct(); + parent::__construct($user); } /** diff --git a/phpBB/phpbb/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php index 0b365ece67..72ad1205ef 100644 --- a/phpBB/phpbb/console/command/cron/run.php +++ b/phpBB/phpbb/console/command/cron/run.php @@ -25,23 +25,19 @@ class run extends \phpbb\console\command\command /** @var \phpbb\lock\db */ protected $lock_db; - /** @var \phpbb\user */ - protected $user; - /** * Construct method * + * @param \phpbb\user $user The user object (used to get language information) * @param \phpbb\cron\manager $cron_manager The cron manager containing * the cron tasks to be executed. * @param \phpbb\lock\db $lock_db The lock for accessing database. - * @param \phpbb\user $user The user object (used to get language information) */ - public function __construct(\phpbb\cron\manager $cron_manager, \phpbb\lock\db $lock_db, \phpbb\user $user) + public function __construct(\phpbb\user $user, \phpbb\cron\manager $cron_manager, \phpbb\lock\db $lock_db) { $this->cron_manager = $cron_manager; $this->lock_db = $lock_db; - $this->user = $user; - parent::__construct(); + parent::__construct($user); } /** diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php index 2abeaf5268..c3caae5f70 100644 --- a/phpBB/phpbb/console/command/db/migrate.php +++ b/phpBB/phpbb/console/command/db/migrate.php @@ -32,31 +32,29 @@ class migrate extends \phpbb\console\command\command /** @var \phpbb\log\log */ protected $log; - /** @var \phpbb\user */ - protected $user; - - function __construct(\phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\user $user) + function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log) { $this->migrator = $migrator; $this->extension_manager = $extension_manager; $this->config = $config; $this->cache = $cache; $this->log = $log; - $this->user = $user; + parent::__construct($user); $this->user->add_lang(array('common', 'install', 'migrator')); - parent::__construct(); } protected function configure() { $this ->setName('db:migrate') - ->setDescription('Updates the database by applying migrations.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_DB_MIGRATE')) ; } protected function execute(InputInterface $input, OutputInterface $output) { + $this->migrator->create_migrations_table(); + $this->load_migrations(); $orig_version = $this->config['version']; while (!$this->migrator->finished()) diff --git a/phpBB/phpbb/console/command/dev/migration_tips.php b/phpBB/phpbb/console/command/dev/migration_tips.php index c2f61568ea..f9047bdac8 100644 --- a/phpBB/phpbb/console/command/dev/migration_tips.php +++ b/phpBB/phpbb/console/command/dev/migration_tips.php @@ -20,17 +20,17 @@ class migration_tips extends \phpbb\console\command\command /** @var \phpbb\extension\manager */ protected $extension_manager; - function __construct(\phpbb\extension\manager $extension_manager) + function __construct(\phpbb\user $user, \phpbb\extension\manager $extension_manager) { $this->extension_manager = $extension_manager; - parent::__construct(); + parent::__construct($user); } protected function configure() { $this ->setName('dev:migration-tips') - ->setDescription('Finds migrations that are not depended on.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_FIND_MIGRATIONS')) ; } diff --git a/phpBB/phpbb/console/command/extension/command.php b/phpBB/phpbb/console/command/extension/command.php index 21bb640504..364d954082 100644 --- a/phpBB/phpbb/console/command/extension/command.php +++ b/phpBB/phpbb/console/command/extension/command.php @@ -20,11 +20,11 @@ abstract class command extends \phpbb\console\command\command /** @var \phpbb\log\log */ protected $log; - public function __construct(\phpbb\extension\manager $manager, \phpbb\log\log $log) + public function __construct(\phpbb\user $user, \phpbb\extension\manager $manager, \phpbb\log\log $log) { $this->manager = $manager; $this->log = $log; - parent::__construct(); + parent::__construct($user); } } diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index 5f0e74b984..1eee16cbd9 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -22,11 +22,11 @@ class disable extends command { $this ->setName('extension:disable') - ->setDescription('Disables the specified extension.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_DISABLE_EXTENSION')) ->addArgument( 'extension-name', InputArgument::REQUIRED, - 'Name of the extension' + $this->user->lang('CLI_EXTENSION_NAME') ) ; } @@ -37,15 +37,15 @@ class disable extends command $this->manager->disable($name); $this->manager->load_extensions(); - if ($this->manager->enabled($name)) + if ($this->manager->is_enabled($name)) { - $output->writeln("<error>Could not disable extension $name</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_EXTENSION_DISABLE_FAILURE', $name) . '</error>'); return 1; } else { $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_DISABLE', time(), array($name)); - $output->writeln("<info>Successfully disabled extension $name</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_EXTENSION_DISABLE_SUCCESS', $name) . '</info>'); return 0; } } diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index 0cdf26d4db..59ff11e9b7 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -22,11 +22,11 @@ class enable extends command { $this ->setName('extension:enable') - ->setDescription('Enables the specified extension.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_ENABLE_EXTENSION')) ->addArgument( 'extension-name', InputArgument::REQUIRED, - 'Name of the extension' + $this->user->lang('CLI_EXTENSION_NAME') ) ; } @@ -37,15 +37,15 @@ class enable extends command $this->manager->enable($name); $this->manager->load_extensions(); - if ($this->manager->enabled($name)) + if ($this->manager->is_enabled($name)) { - $this->log->add('admin', ANONYMOUS, '', 'LOG_EXTENSION_ENABLE', time(), array($name)); - $output->writeln("<info>Successfully enabled extension $name</info>"); + $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($name)); + $output->writeln('<info>' . $this->user->lang('CLI_EXTENSION_ENABLE_SUCCESS', $name) . '</info>'); return 0; } else { - $output->writeln("<error>Could not enable extension $name</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_EXTENSION_ENABLE_FAILURE', $name) . '</error>'); return 1; } } diff --git a/phpBB/phpbb/console/command/extension/purge.php b/phpBB/phpbb/console/command/extension/purge.php index 4e57641d83..517e9a74c9 100644 --- a/phpBB/phpbb/console/command/extension/purge.php +++ b/phpBB/phpbb/console/command/extension/purge.php @@ -22,11 +22,11 @@ class purge extends command { $this ->setName('extension:purge') - ->setDescription('Purges the specified extension.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_PURGE_EXTENSION')) ->addArgument( 'extension-name', InputArgument::REQUIRED, - 'Name of the extension' + $this->user->lang('CLI_EXTENSION_NAME') ) ; } @@ -37,15 +37,15 @@ class purge extends command $this->manager->purge($name); $this->manager->load_extensions(); - if ($this->manager->enabled($name)) + if ($this->manager->is_enabled($name)) { - $output->writeln("<error>Could not purge extension $name</error>"); + $output->writeln('<error>' . $this->user->lang('CLI_EXTENSION_PURGE_FAILURE', $name) . '</error>'); return 1; } else { $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_PURGE', time(), array($name)); - $output->writeln("<info>Successfully purge extension $name</info>"); + $output->writeln('<info>' . $this->user->lang('CLI_EXTENSION_PURGE_SUCCESS', $name) . '</info>'); return 0; } } diff --git a/phpBB/phpbb/console/command/extension/show.php b/phpBB/phpbb/console/command/extension/show.php index 2db1c59e24..6ce9607098 100644 --- a/phpBB/phpbb/console/command/extension/show.php +++ b/phpBB/phpbb/console/command/extension/show.php @@ -21,7 +21,7 @@ class show extends command { $this ->setName('extension:show') - ->setDescription('Lists all extensions in the database and on the filesystem.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_LIST_EXTENSIONS')) ; } @@ -32,7 +32,7 @@ class show extends command if (empty($all)) { - $output->writeln('<comment>No extensions were found.</comment>'); + $output->writeln('<comment>' . $this->user->lang('CLI_EXTENSION_NOT_FOUND') . '</comment>'); return 3; } diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php index ec04da4267..ec4e1b0ee7 100644 --- a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php +++ b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php @@ -20,18 +20,18 @@ 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) + function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db) { $this->db = $db; - parent::__construct(); + parent::__construct($user); } protected function configure() { $this ->setName('fixup:recalculate-email-hash') - ->setDescription('Recalculates the user_email_hash column of the users table.') + ->setDescription($this->user->lang('CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH')) ; } @@ -70,6 +70,6 @@ class recalculate_email_hash extends \phpbb\console\command\command } $this->db->sql_freeresult($result); - $output->writeln('<info>Successfully recalculated all email hashes.</info>'); + $output->writeln('<info>' . $this->user->lang('CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS') . '</info>'); } } diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 930bc42a98..e330fb5b6d 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -40,6 +40,9 @@ class helper */ protected $config; + /* @var \phpbb\symfony_request */ + protected $symfony_request; + /** * phpBB root path * @var string @@ -60,14 +63,16 @@ class helper * @param \phpbb\config\config $config Config object * @param \phpbb\controller\provider $provider Path provider * @param \phpbb\extension\manager $manager Extension manager object + * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP extension */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; $this->config = $config; + $this->symfony_request = $symfony_request; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; $provider->find_routing_files($manager->get_finder()); @@ -151,4 +156,14 @@ class helper return $this->render('message_body.html', $this->user->lang('INFORMATION'), $code); } + + /** + * Return the current url + * + * @return string + */ + public function get_current_url() + { + return generate_board_url(true) . $this->symfony_request->getRequestUri(); + } } diff --git a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php index 381483c798..83a2460454 100644 --- a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php +++ b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php @@ -45,11 +45,11 @@ class prune_shadow_topics extends \phpbb\cron\task\base implements \phpbb\cron\t * @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\db\driver\driver_interface $db The db connection * @param \phpbb\log\log $log The phpBB log system * @param \phpbb\user $user The phpBB user object */ - public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\log\log $log, \phpbb\user $user) + public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\log\log $log, \phpbb\user $user) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; diff --git a/phpBB/phpbb/cron/task/core/tidy_search.php b/phpBB/phpbb/cron/task/core/tidy_search.php index 2de744b7c1..2c30274dfa 100644 --- a/phpBB/phpbb/cron/task/core/tidy_search.php +++ b/phpBB/phpbb/cron/task/core/tidy_search.php @@ -54,8 +54,7 @@ class tidy_search extends \phpbb\cron\task\base */ public function run() { - // Select the search method - $search_type = basename($this->config['search_type']); + $search_type = $this->config['search_type']; // We do some additional checks in the module to ensure it can actually be utilised $error = false; @@ -78,10 +77,7 @@ class tidy_search extends \phpbb\cron\task\base */ public function is_runnable() { - // Select the search method - $search_type = basename($this->config['search_type']); - - return class_exists($search_type); + return class_exists($this->config['search_type']); } /** diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 3c23f8fa36..ab126168b6 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -87,6 +87,102 @@ abstract class driver implements driver_interface } /** + * {@inheritdoc} + */ + public function get_sql_layer() + { + return $this->sql_layer; + } + + /** + * {@inheritdoc} + */ + public function get_db_name() + { + return $this->dbname; + } + + /** + * {@inheritdoc} + */ + public function get_any_char() + { + return $this->any_char; + } + + /** + * {@inheritdoc} + */ + public function get_one_char() + { + return $this->one_char; + } + + /** + * {@inheritdoc} + */ + public function get_db_connect_id() + { + return $this->db_connect_id; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_triggered() + { + return $this->sql_error_triggered; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_sql() + { + return $this->sql_error_sql; + } + + /** + * {@inheritdoc} + */ + public function get_transaction() + { + return $this->transaction; + } + + /** + * {@inheritdoc} + */ + public function get_sql_time() + { + return $this->sql_time; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_returned() + { + return $this->sql_error_returned; + } + + /** + * {@inheritdoc} + */ + public function get_multi_insert() + { + return $this->multi_insert; + } + + /** + * {@inheritdoc} + */ + public function set_multi_insert($multi_insert) + { + $this->multi_insert = $multi_insert; + } + + /** * {@inheritDoc} */ function sql_return_on_error($fail = false) diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 7f7d341e2d..6722d059a5 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -16,6 +16,90 @@ namespace phpbb\db\driver; interface driver_interface { /** + * Gets the name of the sql layer. + * + * @return string + */ + public function get_sql_layer(); + + /** + * Gets the name of the database. + * + * @return string + */ + public function get_db_name(); + + /** + * Wildcards for matching any (%) character within LIKE expressions + * + * @return string + */ + public function get_any_char(); + + /** + * Wildcards for matching exactly one (_) character within LIKE expressions + * + * @return string + */ + public function get_one_char(); + + /** + * Gets the time spent into the queries + * + * @return int + */ + public function get_sql_time(); + + /** + * Gets the connect ID. + * + * @return mixed + */ + public function get_db_connect_id(); + + /** + * Indicates if an error was triggered. + * + * @return bool + */ + public function get_sql_error_triggered(); + + /** + * Gets the last faulty query + * + * @return string + */ + public function get_sql_error_sql(); + + /** + * Indicates if we are in a transaction. + * + * @return bool + */ + public function get_transaction(); + + /** + * Gets the returned error. + * + * @return array + */ + public function get_sql_error_returned(); + + /** + * Indicates if multiple insertion can be used + * + * @return bool + */ + public function get_multi_insert(); + + /** + * Set if multiple insertion can be used + * + * @param bool $multi_insert + */ + public function set_multi_insert($multi_insert); + + /** * Gets the exact number of rows in a specified table. * * @param string $table_name Table name diff --git a/phpBB/phpbb/db/driver/factory.php b/phpBB/phpbb/db/driver/factory.php new file mode 100644 index 0000000000..f0fa18051b --- /dev/null +++ b/phpBB/phpbb/db/driver/factory.php @@ -0,0 +1,435 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\driver; + +use \Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* Database Abstraction Layer +*/ +class factory implements driver_interface +{ + /** + * @var driver_interface + */ + protected $driver = null; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Return the current driver (and retrieved it from the container if necessary) + * + * @return driver_interface + */ + protected function get_driver() + { + if ($this->driver === null) + { + $this->driver = $this->container->get('dbal.conn.driver'); + } + + return $this->driver; + } + + /** + * Set the current driver + * + * @param driver_interface $driver + */ + public function set_driver(driver_interface $driver) + { + $this->driver = $driver; + } + + /** + * {@inheritdoc} + */ + public function get_sql_layer() + { + return $this->get_driver()->get_sql_layer(); + } + + /** + * {@inheritdoc} + */ + public function get_db_name() + { + return $this->get_driver()->get_db_name(); + } + + /** + * {@inheritdoc} + */ + public function get_any_char() + { + return $this->get_driver()->get_any_char(); + } + + /** + * {@inheritdoc} + */ + public function get_one_char() + { + return $this->get_driver()->get_one_char(); + } + + /** + * {@inheritdoc} + */ + public function get_db_connect_id() + { + return $this->get_driver()->get_db_connect_id(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_triggered() + { + return $this->get_driver()->get_sql_error_triggered(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_sql() + { + return $this->get_driver()->get_sql_error_sql(); + } + + /** + * {@inheritdoc} + */ + public function get_transaction() + { + return $this->get_driver()->get_transaction(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_time() + { + return $this->get_driver()->get_sql_time(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_returned() + { + return $this->get_driver()->get_sql_error_returned(); + } + + /** + * {@inheritdoc} + */ + public function get_multi_insert() + { + return $this->get_driver()->get_multi_insert(); + } + + /** + * {@inheritdoc} + */ + public function set_multi_insert($multi_insert) + { + $this->get_driver()->set_multi_insert($multi_insert); + } + + /** + * {@inheritdoc} + */ + public function get_row_count($table_name) + { + return $this->get_driver()->get_row_count($table_name); + } + + /** + * {@inheritdoc} + */ + public function get_estimated_row_count($table_name) + { + return $this->get_driver()->get_estimated_row_count($table_name); + } + + /** + * {@inheritdoc} + */ + public function sql_lower_text($column_name) + { + return $this->get_driver()->sql_lower_text($column_name); + } + + /** + * {@inheritdoc} + */ + public function sql_error($sql = '') + { + return $this->get_driver()->sql_error($sql); + } + + /** + * {@inheritdoc} + */ + public function sql_buffer_nested_transactions() + { + return $this->get_driver()->sql_buffer_nested_transactions(); + } + + /** + * {@inheritdoc} + */ + public function sql_bit_or($column_name, $bit, $compare = '') + { + return $this->get_driver()->sql_bit_or($column_name, $bit, $compare); + } + + /** + * {@inheritdoc} + */ + public function sql_server_info($raw = false, $use_cache = true) + { + return $this->get_driver()->sql_server_info($raw, $use_cache); + } + + /** + * {@inheritdoc} + */ + public function sql_return_on_error($fail = false) + { + return $this->get_driver()->sql_return_on_error($fail); + } + + /** + * {@inheritdoc} + */ + public function sql_build_array($query, $assoc_ary = array()) + { + return $this->get_driver()->sql_build_array($query, $assoc_ary); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchrowset($query_id = false) + { + return $this->get_driver()->sql_fetchrowset($query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_transaction($status = 'begin') + { + return $this->get_driver()->sql_transaction($status); + } + + /** + * {@inheritdoc} + */ + public function sql_concatenate($expr1, $expr2) + { + return $this->get_driver()->sql_concatenate($expr1, $expr2); + } + + /** + * {@inheritdoc} + */ + public function sql_case($condition, $action_true, $action_false = false) + { + return $this->get_driver()->sql_case($condition, $action_true, $action_false); + } + + /** + * {@inheritdoc} + */ + public function sql_build_query($query, $array) + { + return $this->get_driver()->sql_build_query($query, $array); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchfield($field, $rownum = false, $query_id = false) + { + return $this->get_driver()->sql_fetchfield($field, $rownum, $query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchrow($query_id = false) + { + return $this->get_driver()->sql_fetchrow($query_id); + } + + /** + * {@inheritdoc} + */ + public function cast_expr_to_bigint($expression) + { + return $this->get_driver()->cast_expr_to_bigint($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_nextid() + { + return $this->get_driver()->sql_nextid(); + } + + /** + * {@inheritdoc} + */ + public function sql_add_num_queries($cached = false) + { + return $this->get_driver()->sql_add_num_queries($cached); + } + + /** + * {@inheritdoc} + */ + public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + return $this->get_driver()->sql_query_limit($query, $total, $offset, $cache_ttl); + } + + /** + * {@inheritdoc} + */ + public function sql_query($query = '', $cache_ttl = 0) + { + return $this->get_driver()->sql_query($query, $cache_ttl); + } + + /** + * {@inheritdoc} + */ + public function cast_expr_to_string($expression) + { + return $this->get_driver()->cast_expr_to_string($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + throw new \Exception('Disabled method.'); + } + + /** + * {@inheritdoc} + */ + public function sql_bit_and($column_name, $bit, $compare = '') + { + return $this->get_driver()->sql_bit_and($column_name, $bit, $compare); + } + + /** + * {@inheritdoc} + */ + public function sql_freeresult($query_id = false) + { + return $this->get_driver()->sql_freeresult($query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_num_queries($cached = false) + { + return $this->get_driver()->sql_num_queries($cached); + } + + /** + * {@inheritdoc} + */ + public function sql_multi_insert($table, $sql_ary) + { + return $this->get_driver()->sql_multi_insert($table, $sql_ary); + } + + /** + * {@inheritdoc} + */ + public function sql_affectedrows() + { + return $this->get_driver()->sql_affectedrows(); + } + + /** + * {@inheritdoc} + */ + public function sql_close() + { + return $this->get_driver()->sql_close(); + } + + /** + * {@inheritdoc} + */ + public function sql_rowseek($rownum, &$query_id) + { + return $this->get_driver()->sql_rowseek($rownum, $query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_escape($msg) + { + return $this->get_driver()->sql_escape($msg); + } + + /** + * {@inheritdoc} + */ + public function sql_like_expression($expression) + { + return $this->get_driver()->sql_like_expression($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_report($mode, $query = '') + { + return $this->get_driver()->sql_report($mode, $query); + } + + /** + * {@inheritdoc} + */ + public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) + { + return $this->get_driver()->sql_in_set($field, $array, $negate, $allow_empty_set); + } +} diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php deleted file mode 100644 index c7b185a577..0000000000 --- a/phpBB/phpbb/db/driver/firebird.php +++ /dev/null @@ -1,526 +0,0 @@ -<?php -/** -* -* This file is part of the phpBB Forum Software package. -* -* @copyright (c) phpBB Limited <https://www.phpbb.com> -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -namespace phpbb\db\driver; - -/** -* Firebird/Interbase Database Abstraction Layer -* Minimum Requirement is Firebird 2.1 -*/ -class firebird extends \phpbb\db\driver\driver -{ - var $last_query_text = ''; - var $service_handle = false; - var $affected_rows = 0; - var $connect_error = ''; - - /** - * {@inheritDoc} - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = str_replace('\\', '/', $database); - - // There are three possibilities to connect to an interbase db - if (!$this->server) - { - $use_database = $this->dbname; - } - else if (strpos($this->server, '//') === 0) - { - $use_database = $this->server . $this->dbname; - } - else - { - $use_database = $this->server . ':' . $this->dbname; - } - - if ($this->persistency) - { - if (!function_exists('ibase_pconnect')) - { - $this->connect_error = 'ibase_pconnect function does not exist, is interbase extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3); - } - else - { - if (!function_exists('ibase_connect')) - { - $this->connect_error = 'ibase_connect function does not exist, is interbase extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); - } - - // Do not call ibase_service_attach if connection failed, - // otherwise error message from ibase_(p)connect call will be clobbered. - if ($this->db_connect_id && function_exists('ibase_service_attach') && $this->server) - { - $this->service_handle = @ibase_service_attach($this->server, $this->user, $sqlpassword); - } - else - { - $this->service_handle = false; - } - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * {@inheritDoc} - */ - function sql_server_info($raw = false, $use_cache = true) - { - /** - * force $use_cache false. I didn't research why the caching code there is no caching code - * but I assume its because the IB extension provides a direct method to access it - * without a query. - */ - - $use_cache = false; - - if ($this->service_handle !== false && function_exists('ibase_server_info')) - { - return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); - } - - return ($raw) ? '2.1' : 'Firebird/Interbase'; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return true; - break; - - case 'commit': - return @ibase_commit(); - break; - - case 'rollback': - return @ibase_rollback(); - break; - } - - return true; - } - - /** - * {@inheritDoc} - */ - function sql_query($query = '', $cache_ttl = 0) - { - if ($query != '') - { - global $cache; - - // EXPLAIN only in extra debug mode - if (defined('DEBUG')) - { - $this->sql_report('start', $query); - } - - $this->last_query_text = $query; - $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; - $this->sql_add_num_queries($this->query_result); - - if ($this->query_result === false) - { - $array = array(); - // We overcome Firebird's 32767 char limit by binding vars - if (strlen($query) > 32767) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) - { - if (strlen($regs[3]) > 32767) - { - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - if (!empty($value) && $value[0] === "'" && strlen($value) > 32769) // check to see if this thing is greater than the max + 'x2 - { - $inserts[$key] = '?'; - $array[] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data)) - { - if (strlen($data[3]) > 32767) - { - $update = $data[1]; - $where = $data[4]; - preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[3], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) // check to see if this thing is greater than the max + 'x2 - { - $array[] = str_replace("''", "'", substr($value[2], 1, -1)); - $cols[] = $value[1] . '=?'; - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - if (!function_exists('ibase_affected_rows') && (preg_match('/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+\s+(WHERE.*)?$/s', $query, $regs) || preg_match('/^DELETE FROM ([\w_]++)\s*(WHERE\s*.*)?$/s', $query, $regs))) - { - $affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs[1]; - if (!empty($regs[2])) - { - $affected_sql .= ' ' . $regs[2]; - } - - if (!($temp_q_id = @ibase_query($this->db_connect_id, $affected_sql))) - { - return false; - } - - $temp_result = @ibase_fetch_assoc($temp_q_id); - @ibase_free_result($temp_q_id); - - $this->affected_rows = ($temp_result) ? $temp_result['NUM_ROWS_AFFECTED'] : false; - } - - if (sizeof($array)) - { - $p_query = @ibase_prepare($this->db_connect_id, $query); - array_unshift($array, $p_query); - $this->query_result = call_user_func_array('ibase_execute', $array); - unset($array); - - if ($this->query_result === false) - { - $this->sql_error($query); - } - } - else if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false) - { - $this->sql_error($query); - } - - if (defined('DEBUG')) - { - $this->sql_report('stop', $query); - } - - if (!$this->transaction) - { - if (function_exists('ibase_commit_ret')) - { - @ibase_commit_ret(); - } - else - { - // way cooler than ibase_commit_ret :D - @ibase_query('COMMIT RETAIN;'); - } - } - - if ($cache && $cache_ttl) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); - } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - } - } - else if (defined('DEBUG')) - { - $this->sql_report('fromcache', $query); - } - } - else - { - return false; - } - - return $this->query_result; - } - - /** - * Build LIMIT query - */ - function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) - { - $this->query_result = false; - - $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6); - - return $this->sql_query($query, $cache_ttl); - } - - /** - * {@inheritDoc} - */ - function sql_affectedrows() - { - // PHP 5+ function - if (function_exists('ibase_affected_rows')) - { - return ($this->db_connect_id) ? @ibase_affected_rows($this->db_connect_id) : false; - } - else - { - return $this->affected_rows; - } - } - - /** - * {@inheritDoc} - */ - function sql_fetchrow($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($cache && $cache->sql_exists($query_id)) - { - return $cache->sql_fetchrow($query_id); - } - - if ($query_id === false) - { - return false; - } - - $row = array(); - $cur_row = @ibase_fetch_object($query_id, IBASE_TEXT); - - if (!$cur_row) - { - return false; - } - - foreach (get_object_vars($cur_row) as $key => $value) - { - $row[strtolower($key)] = (is_string($value)) ? trim(str_replace(array("\\0", "\\n"), array("\0", "\n"), $value)) : $value; - } - - return (sizeof($row)) ? $row : false; - } - - /** - * {@inheritDoc} - */ - function sql_nextid() - { - $query_id = $this->query_result; - - if ($query_id !== false && $this->last_query_text != '') - { - if ($this->query_result && preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#i', $this->last_query_text, $tablename)) - { - $sql = 'SELECT GEN_ID(' . $tablename[1] . '_gen, 0) AS new_id FROM RDB$DATABASE'; - - if (!($temp_q_id = @ibase_query($this->db_connect_id, $sql))) - { - return false; - } - - $temp_result = @ibase_fetch_assoc($temp_q_id); - @ibase_free_result($temp_q_id); - - return ($temp_result) ? $temp_result['NEW_ID'] : false; - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - function sql_freeresult($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) - { - return $cache->sql_freeresult($query_id); - } - - if (isset($this->open_queries[(int) $query_id])) - { - unset($this->open_queries[(int) $query_id]); - return @ibase_free_result($query_id); - } - - return false; - } - - /** - * {@inheritDoc} - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - function _sql_bit_and($column_name, $bit, $compare = '') - { - return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - function _sql_bit_or($column_name, $bit, $compare = '') - { - return 'BIN_OR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - /** - * {@inheritDoc} - */ - function cast_expr_to_bigint($expression) - { - // Precision must be from 1 to 18 - return 'CAST(' . $expression . ' as DECIMAL(18, 0))'; - } - - /** - * {@inheritDoc} - */ - function cast_expr_to_string($expression) - { - return 'CAST(' . $expression . ' as VARCHAR(255))'; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - // Need special handling here because ibase_errmsg returns - // connection errors, however if the interbase extension - // is not installed then ibase_errmsg does not exist and - // we cannot call it. - if (function_exists('ibase_errmsg')) - { - $msg = @ibase_errmsg(); - if (!$msg) - { - $msg = $this->connect_error; - } - } - else - { - $msg = $this->connect_error; - } - return array( - 'message' => $msg, - 'code' => (@function_exists('ibase_errcode') ? @ibase_errcode() : '') - ); - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - if ($this->service_handle !== false) - { - @ibase_service_detach($this->service_handle); - } - - return @ibase_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @ibase_query($this->db_connect_id, $query); - while ($void = @ibase_fetch_object($result, IBASE_TEXT)) - { - // Take the time spent on parsing rows into account - } - @ibase_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 0809703b48..fd13eefad0 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -137,6 +137,10 @@ class mssql extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -152,6 +156,10 @@ class mssql extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index 0a15148e1d..9d9ad603e0 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -156,6 +156,10 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -172,6 +176,10 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 3bc9ecda75..50dce35baa 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -127,6 +127,10 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -145,6 +149,10 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index ed8f16fa5f..a94e88b331 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -176,6 +176,10 @@ class mysql extends \phpbb\db\driver\mysql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -191,6 +195,10 @@ class mysql extends \phpbb\db\driver\mysql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 4c6963673e..debc3cc523 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -61,7 +61,11 @@ class mysqli extends \phpbb\db\driver\mysql_base } $this->db_connect_id = mysqli_init(); - @mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS); + + if (!@mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS)) + { + $this->db_connect_id = ''; + } if ($this->db_connect_id && $this->dbname != '') { @@ -175,6 +179,10 @@ class mysqli extends \phpbb\db\driver\mysql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -190,6 +198,10 @@ class mysqli extends \phpbb\db\driver\mysql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index cacee3ef41..28fea59d8f 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -253,6 +253,10 @@ class oracle extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -430,6 +434,10 @@ class oracle extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 78825de73c..c8f8416caf 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -15,10 +15,11 @@ namespace phpbb\db\driver; /** * PostgreSQL Database Abstraction Layer -* Minimum Requirement is Version 7.3+ +* Minimum Requirement is Version 8.3+ */ class postgres extends \phpbb\db\driver\driver { + var $multi_insert = true; var $last_query_text = ''; var $connect_error = ''; @@ -101,11 +102,6 @@ class postgres extends \phpbb\db\driver\driver if ($this->db_connect_id) { - if (version_compare($this->sql_server_info(true), '8.2', '>=')) - { - $this->multi_insert = true; - } - if ($schema !== '') { @pg_query($this->db_connect_id, 'SET search_path TO ' . $schema); @@ -182,6 +178,10 @@ class postgres extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -198,6 +198,10 @@ class postgres extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 9130b2b292..bff456cb94 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -124,6 +124,10 @@ class sqlite extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -139,6 +143,10 @@ class sqlite extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 4ca3d8f91d..5548105006 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -52,7 +52,8 @@ class sqlite3 extends \phpbb\db\driver\driver } catch (\Exception $e) { - return array('message' => $e->getMessage()); + $this->connect_error = $e->getMessage(); + return array('message' => $this->connect_error); } return true; @@ -121,6 +122,10 @@ class sqlite3 extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -137,6 +142,10 @@ class sqlite3 extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->query_result) { @@ -277,7 +286,7 @@ class sqlite3 extends \phpbb\db\driver\driver */ protected function _sql_error() { - if (class_exists('SQLite3', false)) + if (class_exists('SQLite3', false) && isset($this->dbo)) { $error = array( 'message' => $this->dbo->lastErrorMsg(), diff --git a/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php b/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php index edcc69e1bf..648ae9ce96 100644 --- a/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php +++ b/phpBB/phpbb/db/migration/data/v30x/local_url_bbcode.php @@ -37,7 +37,7 @@ class local_url_bbcode extends \phpbb\db\migration\migration { $sql = 'SELECT * FROM ' . BBCODES_TABLE . ' - WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->any_char . 'LOCAL_URL' . $this->db->any_char); + WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->get_any_char() . 'LOCAL_URL' . $this->db->get_any_char()); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php index db3c587f82..9b08da0125 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php @@ -36,7 +36,7 @@ class release_3_0_4 extends \phpbb\db\migration\migration public function rename_log_delete_topic() { - if ($this->db->sql_layer == 'oracle') + if ($this->db->get_sql_layer() == 'oracle') { // log_operation is CLOB - but we can change this later $sql = 'UPDATE ' . $this->table_prefix . "log diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php index d86c4d6986..1843c3f262 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php @@ -76,7 +76,7 @@ class release_3_0_7_rc1 extends \phpbb\db\migration\migration { // Delete all text-templates from the template_data $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' - WHERE template_filename ' . $this->db->sql_like_expression($this->db->any_char . '.txt'); + WHERE template_filename ' . $this->db->sql_like_expression($this->db->get_any_char() . '.txt'); $this->sql_query($sql); } } diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php index 24340c8cf1..06e46d522f 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php @@ -89,7 +89,7 @@ class release_3_0_9_rc1 extends \phpbb\db\migration\migration // Update file extension group names to use language strings, again. $sql = 'SELECT group_id, group_name FROM ' . EXTENSION_GROUPS_TABLE . ' - WHERE group_name ' . $this->db->sql_like_expression('EXT_GROUP_' . $this->db->any_char); + WHERE group_name ' . $this->db->sql_like_expression('EXT_GROUP_' . $this->db->get_any_char()); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) diff --git a/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php index df1560f5b1..4530ebe285 100644 --- a/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php +++ b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php @@ -18,7 +18,7 @@ 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; + return strpos($this->db->get_sql_layer(), 'mysql') === false; } static public function depends_on() diff --git a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php index ca784656e7..ea442dfb1b 100644 --- a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php +++ b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php @@ -18,7 +18,7 @@ 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; + return strpos($this->db->get_sql_layer(), 'postgres') === false; } static public function depends_on() diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php b/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php new file mode 100644 index 0000000000..9bef0a4c0b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/profilefield_googleplus.php @@ -0,0 +1,60 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class profilefield_googleplus 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', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'create_custom_field'))), + ); + } + + protected $profilefield_name = 'phpbb_googleplus'; + + protected $profilefield_database_type = array('VCHAR', ''); + + protected $profilefield_data = array( + 'field_name' => 'phpbb_googleplus', + 'field_type' => 'profilefields.type.googleplus', + 'field_ident' => 'phpbb_googleplus', + 'field_length' => '20', + 'field_minlen' => '3', + 'field_maxlen' => '255', + 'field_novalue' => '', + 'field_default_value' => '', + 'field_validation' => '[\w]+', + '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' => 'VIEW_GOOGLEPLUS_PROFILE', + 'field_contact_url' => 'http://plus.google.com/%s', + ); +} diff --git a/phpBB/phpbb/db/migration/data/v310/rc1.php b/phpBB/phpbb/db/migration/data/v310/rc1.php new file mode 100644 index 0000000000..10ba7fefff --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/rc1.php @@ -0,0 +1,39 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class rc1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\beta4', + '\phpbb\db\migration\data\v310\contact_admin_acp_module', + '\phpbb\db\migration\data\v310\contact_admin_form', + '\phpbb\db\migration\data\v310\passwords_convert_p2', + '\phpbb\db\migration\data\v310\profilefield_facebook', + '\phpbb\db\migration\data\v310\profilefield_googleplus', + '\phpbb\db\migration\data\v310\profilefield_skype', + '\phpbb\db\migration\data\v310\profilefield_twitter', + '\phpbb\db\migration\data\v310\profilefield_youtube', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/rc2.php b/phpBB/phpbb/db/migration/data/v310/rc2.php new file mode 100644 index 0000000000..e1323659da --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/rc2.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class rc2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.0-RC2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/search_type.php b/phpBB/phpbb/db/migration/data/v310/search_type.php new file mode 100644 index 0000000000..f89456ae19 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/search_type.php @@ -0,0 +1,34 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class search_type extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v310\dev', + ); + } + + public function update_data() + { + return array( + array('if', array( + (is_file($this->phpbb_root_path . 'phpbb/search/' . $this->config['search_type'] . $this->php_ext)), + array('config.update', array('search_type', '\\phpbb\\search\\' . $this->config['search_type'])), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php index fdfc31da3a..5f120333e1 100644 --- a/phpBB/phpbb/db/migration/migration.php +++ b/phpBB/phpbb/db/migration/migration.php @@ -160,11 +160,11 @@ abstract class migration else { $result = $this->db->sql_query($sql); - if ($this->db->sql_error_triggered) + if ($this->db->get_sql_error_triggered()) { $this->errors[] = array( - 'sql' => $this->db->sql_error_sql, - 'code' => $this->db->sql_error_returned, + 'sql' => $this->db->get_sql_error_sql(), + 'code' => $this->db->get_sql_error_returned(), ); } } diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php index 9cdd5d0927..9000949a7d 100644 --- a/phpBB/phpbb/db/migration/profilefield_base_migration.php +++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php @@ -21,6 +21,23 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration protected $profilefield_data; + /** + * Language data should be in array -> each language_data in separate key + * array( + * array( + * 'option_id' => value, + * 'field_type' => value, + * 'lang_value' => value, + * ), + * array( + * 'option_id' => value, + * 'field_type' => value, + * 'lang_value' => value, + * ), + * ) + */ + protected $profilefield_language_data; + protected $user_column_name; public function effectively_installed() @@ -58,6 +75,13 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration ); } + public function revert_data() + { + return array( + array('custom', array(array($this, 'delete_custom_profile_field_data'))), + ); + } + public function create_custom_field() { $sql = 'SELECT MAX(field_order) as max_field_order @@ -79,12 +103,13 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration $sql = 'SELECT lang_id FROM ' . LANG_TABLE; $result = $this->db->sql_query($sql); + $lang_name = (strpos($this->profilefield_name, 'phpbb_') === 0) ? strtoupper(substr($this->profilefield_name, 6)) : strtoupper($this->profilefield_name); 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 + 'field_id' => (int) $field_id, + 'lang_id' => (int) $lang_id, + 'lang_name' => $lang_name, 'lang_explain' => '', 'lang_default_value' => '', )); @@ -95,6 +120,69 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration } /** + * Create Custom profile fields languguage entries + */ + public function create_language_entries() + { + $field_id = $this->get_custom_profile_field_id(); + + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_FIELDS_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')) + { + foreach ($this->profilefield_language_data as $language_data) + { + $insert_buffer->insert(array_merge(array( + 'field_id' => (int) $field_id, + 'lang_id' => (int) $lang_id, + ), $language_data)); + } + } + $this->db->sql_freeresult($result); + + $insert_buffer->flush(); + } + + /** + * Clean database when reverting the migration + */ + public function delete_custom_profile_field_data() + { + $field_id = $this->get_custom_profile_field_id(); + + $sql = 'DELETE FROM ' . PROFILE_FIELDS_TABLE . ' + WHERE field_id = ' . (int) $field_id; + $this->db->sql_query($sql); + + $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' + WHERE field_id = ' . (int) $field_id; + $this->db->sql_query($sql); + + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE field_id = ' . (int) $field_id; + $this->db->sql_query($sql); + } + + /** + * Get custom profile field id + * @return int custom profile filed id + */ + public function get_custom_profile_field_id() + { + $sql = 'SELECT field_id + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_name = '" . $this->profilefield_name . "'"; + $result = $this->db->sql_query($sql); + $field_id = (int) $this->db->sql_fetchfield('field_id'); + $this->db->sql_freeresult($result); + + return $field_id; + } + + /** * @param int $start Start of staggering step * @return mixed int start of the next step, null if the end was reached */ diff --git a/phpBB/phpbb/db/migration/tool/config_text.php b/phpBB/phpbb/db/migration/tool/config_text.php new file mode 100644 index 0000000000..bf8ac55023 --- /dev/null +++ b/phpBB/phpbb/db/migration/tool/config_text.php @@ -0,0 +1,125 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\tool; + +/** +* Migration config_text tool +*/ +class config_text implements \phpbb\db\migration\tool\tool_interface +{ + /** @var \phpbb\config\db_text */ + protected $config_text; + + /** + * Constructor + * + * @param \phpbb\config\db_text $config_text + */ + public function __construct(\phpbb\config\db_text $config_text) + { + $this->config_text = $config_text; + } + + /** + * {@inheritdoc} + */ + public function get_name() + { + return 'config_text'; + } + + /** + * Add a config_text setting. + * + * @param string $config_name The name of the config_text setting + * you would like to add + * @param mixed $config_value The value of the config_text setting + * @return null + */ + public function add($config_name, $config_value) + { + if (!is_null($this->config_text->get($config_name))) + { + return; + } + + $this->config_text->set($config_name, $config_value); + } + + /** + * Update an existing config_text setting. + * + * @param string $config_name The name of the config_text setting you would + * like to update + * @param mixed $config_value The value of the config_text setting + * @return null + * @throws \phpbb\db\migration\exception + */ + public function update($config_name, $config_value) + { + if (is_null($this->config_text->get($config_name))) + { + throw new \phpbb\db\migration\exception('CONFIG_NOT_EXIST', $config_name); + } + + $this->config_text->set($config_name, $config_value); + } + + /** + * Remove an existing config_text setting. + * + * @param string $config_name The name of the config_text setting you would + * like to remove + * @return null + */ + public function remove($config_name) + { + if (is_null($this->config_text->get($config_name))) + { + return; + } + + $this->config_text->delete($config_name); + } + + /** + * {@inheritdoc} + */ + public function reverse() + { + $arguments = func_get_args(); + $original_call = array_shift($arguments); + + $call = false; + switch ($original_call) + { + case 'add': + $call = 'remove'; + break; + + case 'remove': + $call = 'add'; + if (sizeof($arguments) == 1) + { + $arguments[] = ''; + } + break; + } + + if ($call) + { + return call_user_func_array(array(&$this, $call), $arguments); + } + } +} diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index c2f7b5ab23..8bc63e564a 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -110,7 +110,7 @@ class migrator FROM " . $this->migrations_table; $result = $this->db->sql_query($sql); - if (!$this->db->sql_error_triggered) + if (!$this->db->get_sql_error_triggered()) { while ($migration = $this->db->sql_fetchrow($result)) { @@ -767,4 +767,28 @@ class migrator return $this->migrations; } + + /** + * Creates the migrations table if it does not exist. + * @return null + */ + public function create_migrations_table() + { + // Make sure migrations have been installed. + if (!$this->db_tools->sql_table_exists($this->table_prefix . 'migrations')) + { + $this->db_tools->sql_create_table($this->table_prefix . 'migrations', array( + 'COLUMNS' => array( + 'migration_name' => array('VCHAR', ''), + 'migration_depends_on' => array('TEXT', ''), + 'migration_schema_done' => array('BOOL', 0), + 'migration_data_done' => array('BOOL', 0), + 'migration_data_state' => array('TEXT', ''), + 'migration_start_time' => array('TIMESTAMP', 0), + 'migration_end_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'migration_name', + )); + } + } } diff --git a/phpBB/phpbb/db/sql_insert_buffer.php b/phpBB/phpbb/db/sql_insert_buffer.php index 6b6f556571..14e3c54f09 100644 --- a/phpBB/phpbb/db/sql_insert_buffer.php +++ b/phpBB/phpbb/db/sql_insert_buffer.php @@ -92,7 +92,7 @@ class sql_insert_buffer // Flush buffer if it is full or when DB does not support multi inserts. // In the later case, the buffer will always only contain one row. - if (!$this->db->multi_insert || sizeof($this->buffer) >= $this->max_buffered_rows) + if (!$this->db->get_multi_insert() || sizeof($this->buffer) >= $this->max_buffered_rows) { return $this->flush(); } diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index 2ee842eace..ae0c695aa2 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -109,36 +109,6 @@ class tools 'VARBINARY' => 'varbinary(255)', ), - 'firebird' => array( - 'INT:' => 'INTEGER', - 'BINT' => 'DOUBLE PRECISION', - 'UINT' => 'INTEGER', - 'UINT:' => 'INTEGER', - 'TINT:' => 'INTEGER', - 'USINT' => 'INTEGER', - 'BOOL' => 'INTEGER', - 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE', - 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE', - 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE', - 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8', - 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'TIMESTAMP' => 'INTEGER', - 'DECIMAL' => 'DOUBLE PRECISION', - 'DECIMAL:' => 'DOUBLE PRECISION', - 'PDECIMAL' => 'DOUBLE PRECISION', - 'PDECIMAL:' => 'DOUBLE PRECISION', - 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8', - 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', - ), - 'mssql' => array( 'INT:' => '[int]', 'BINT' => '[float]', @@ -331,7 +301,7 @@ class tools * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. * @var array */ - var $supported_dbms = array('firebird', 'mssql', 'mssqlnative', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite', 'sqlite3'); + var $supported_dbms = array('mssql', 'mssqlnative', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite', 'sqlite3'); /** * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array). @@ -353,7 +323,7 @@ class tools $this->dbms_type_map = self::get_dbms_type_map(); // Determine mapping database type - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'mysql': $this->sql_layer = 'mysql_40'; @@ -384,7 +354,7 @@ class tools break; default: - $this->sql_layer = $this->db->sql_layer; + $this->sql_layer = $this->db->get_sql_layer(); break; } } @@ -407,7 +377,7 @@ class tools */ function sql_list_tables() { - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'mysql': case 'mysql4': @@ -441,13 +411,6 @@ class tools FROM pg_stat_user_tables'; break; - case 'firebird': - $sql = 'SELECT rdb$relation_name - FROM rdb$relations - WHERE rdb$view_source is null - AND rdb$system_flag = 0'; - break; - case 'oracle': $sql = 'SELECT table_name FROM USER_TABLES'; @@ -580,7 +543,6 @@ class tools // Close the table for two DBMS and add to the statements switch ($this->sql_layer) { - case 'firebird': case 'mssql': case 'mssqlnative': $table_sql .= "\n);"; @@ -610,7 +572,6 @@ class tools $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; break; - case 'firebird': case 'mssql': case 'mssqlnative': // We need the data here @@ -685,19 +646,6 @@ class tools $statements[] = $trigger; } break; - - case 'firebird': - if ($create_sequence) - { - $statements[] = "CREATE GENERATOR {$table_name}_gen;"; - $statements[] = "SET GENERATOR {$table_name}_gen TO 0;"; - - $trigger = "CREATE TRIGGER t_$table_name FOR $table_name\n"; - $trigger .= "BEFORE INSERT\nAS\nBEGIN\n"; - $trigger .= "\tNEW.{$create_sequence} = GEN_ID({$table_name}_gen, 1);\nEND;"; - $statements[] = $trigger; - } - break; } // Write Keys @@ -763,7 +711,7 @@ class tools $sqlite = false; // For SQLite we need to perform the schema changes in a much more different way - if (($this->db->sql_layer == 'sqlite' || $this->db->sql_layer == 'sqlite3') && $this->return_statements) + if (($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') && $this->return_statements) { $sqlite_data = array(); $sqlite = true; @@ -1174,12 +1122,6 @@ class tools WHERE LOWER(table_name) = '" . strtolower($table) . "'"; break; - case 'firebird': - $sql = "SELECT RDB\$FIELD_NAME as FNAME - FROM RDB\$RELATION_FIELDS - WHERE RDB\$RELATION_NAME = '" . strtoupper($table) . "'"; - break; - case 'sqlite': case 'sqlite3': $sql = "SELECT sql @@ -1278,15 +1220,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - case 'postgres': $sql = "SELECT ic.relname as index_name FROM pg_class bc, pg_class ic, pg_index i @@ -1332,7 +1265,6 @@ class tools // These DBMS prefix index name with the table name switch ($this->sql_layer) { - case 'firebird': case 'oracle': case 'postgres': case 'sqlite': @@ -1385,15 +1317,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NOT NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - case 'postgres': $sql = "SELECT ic.relname as index_name, i.indisunique FROM pg_class bc, pg_class ic, pg_index i @@ -1460,7 +1383,6 @@ class tools } break; - case 'firebird': case 'postgres': case 'sqlite': case 'sqlite3': @@ -1536,32 +1458,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - $sql .= " {$column_type} "; - $return_array['column_type_sql_type'] = " {$column_type} "; - - if (!is_null($column_data[1])) - { - $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - $return_array['column_type_sql_default'] = ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - } - - $sql .= 'NOT NULL'; - - // This is a UNICODE column and thus should be given it's fair share - if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0])) - { - $sql .= ' COLLATE UNICODE'; - } - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $return_array['auto_increment'] = true; - } - - break; - case 'mssql': case 'mssqlnative': $sql .= " {$column_type} "; @@ -1591,8 +1487,16 @@ class tools $return_array['textimage'] = $column_type === '[text]'; - $sql .= 'NOT NULL'; - $sql_default .= 'NOT NULL'; + if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment')) + { + $sql .= 'NOT NULL'; + $sql_default .= 'NOT NULL'; + } + else + { + $sql .= 'NULL'; + $sql_default .= 'NULL'; + } $return_array['column_type_sql_default'] = $sql_default; @@ -1607,7 +1511,15 @@ class tools { $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; } - $sql .= 'NOT NULL'; + + if (!is_null($column_data[1])) + { + $sql .= 'NOT NULL'; + } + else + { + $sql .= 'NULL'; + } if (isset($column_data[2])) { @@ -1632,7 +1544,7 @@ class tools // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) if (!preg_match('/number/i', $column_type)) { - $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; + $sql .= ($column_data[1] === '' || $column_data[1] === null) ? '' : 'NOT NULL'; } $return_array['auto_increment'] = false; @@ -1660,6 +1572,12 @@ class tools $return_array['null'] = 'NOT NULL'; $sql .= 'NOT NULL '; } + else + { + $default_val = "'" . $column_data[1] . "'"; + $return_array['null'] = 'NULL'; + $sql .= 'NULL '; + } $return_array['default'] = $default_val; @@ -1692,8 +1610,11 @@ class tools $sql .= ' ' . $column_type; } - $sql .= ' NOT NULL '; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; + if (!is_null($column_data[1])) + { + $sql .= ' NOT NULL '; + $sql .= "DEFAULT '{$column_data[1]}'"; + } break; } @@ -1772,11 +1693,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - // Does not support AFTER statement, only POSITION (and there you need the column position) - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($column_name) . '" ' . $column_data['column_type_sql']; - break; - case 'mssql': case 'mssqlnative': // Does not support AFTER, only through temporary table @@ -1894,10 +1810,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"'; - break; - case 'mssql': case 'mssqlnative': // We need the data here @@ -2036,7 +1948,6 @@ class tools $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; break; - case 'firebird': case 'oracle': case 'postgres': case 'sqlite': @@ -2065,21 +1976,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - $sql = 'SELECT RDB$GENERATOR_NAME as gen - FROM RDB$GENERATORS - WHERE RDB$SYSTEM_FLAG = 0 - AND RDB$GENERATOR_NAME = \'' . strtoupper($table_name) . "_GEN'"; - $result = $this->db->sql_query($sql); - - // does a generator exist? - if ($row = $this->db->sql_fetchrow($result)) - { - $statements[] = "DROP GENERATOR {$row['gen']};"; - } - $this->db->sql_freeresult($result); - break; - case 'oracle': $sql = 'SELECT A.REFERENCED_NAME FROM USER_DEPENDENCIES A, USER_TRIGGERS B @@ -2125,7 +2021,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': case 'postgres': case 'mysql_40': case 'mysql_41': @@ -2217,7 +2112,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': case 'postgres': case 'oracle': case 'sqlite': @@ -2261,7 +2155,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': case 'postgres': case 'oracle': case 'sqlite': @@ -2320,15 +2213,6 @@ class tools { switch ($this->sql_layer) { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - case 'postgres': $sql = "SELECT ic.relname as index_name FROM pg_class bc, pg_class ic, pg_index i @@ -2373,7 +2257,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': case 'oracle': case 'postgres': case 'sqlite': @@ -2400,20 +2283,6 @@ class tools switch ($this->sql_layer) { - case 'firebird': - // Change type... - if (!empty($column_data['column_type_sql_default'])) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type']; - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default']; - } - else - { - // TODO: try to change pkey without removing trigger, generator or constraints. ATM this query may fail. - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type']; - } - break; - case 'mssql': case 'mssqlnative': // We need the data here diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php new file mode 100644 index 0000000000..553b723cc8 --- /dev/null +++ b/phpBB/phpbb/di/container_builder.php @@ -0,0 +1,402 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\di; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; + +class container_builder +{ + /** @var string phpBB Root Path */ + protected $phpbb_root_path; + + /** @var string php file extension */ + protected $php_ext; + + /** + * The container under construction + * + * @var ContainerBuilder + */ + protected $container; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $dbal_connection = null; + + /** + * @var array the installed extensions + */ + protected $installed_exts = null; + + /** + * Indicates whether the php config file should be injected into the container (default to true). + * + * @var bool + */ + protected $inject_config = true; + + /** + * Indicates whether extensions should be used (default to true). + * + * @var bool + */ + protected $use_extensions = true; + + /** + * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config') + * + * @var string + */ + protected $config_path = null; + + /** + * Indicates whether the phpBB compile pass should be used (default to true). + * + * @var bool + */ + protected $use_custom_pass = true; + + /** + * Indicates whether the kernel compile pass should be used (default to true). + * + * @var bool + */ + protected $use_kernel_pass = true; + + /** + * Indicates whether the container should be dumped to the filesystem (default to true). + * + * If DEBUG_CONTAINER is set this option is ignored and a new container is build. + * + * @var bool + */ + protected $dump_container = true; + + /** + * Indicates if the container should be compiled automatically (default to true). + * + * @var bool + */ + protected $compile_container = true; + + /** + * Custom parameters to inject into the container. + * + * Default to true: + * array( + * 'core.root_path', $this->phpbb_root_path, + * 'core.php_ext', $this->php_ext, + * ); + * + * @var array + */ + protected $custom_parameters = null; + + /** + * @var \phpbb\config_php_file + */ + protected $config_php_file; + + /** + * Constructor + * + * @param \phpbb\config_php_file $config_php_file + * @param string $phpbb_root_path Path to the phpbb includes directory. + * @param string $php_ext php file extension + */ + function __construct(\phpbb\config_php_file $config_php_file, $phpbb_root_path, $php_ext) + { + $this->config_php_file = $config_php_file; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * Build and return a new Container respecting the current configuration + * + * @return \phpbb_cache_container|ContainerBuilder + */ + public function get_container() + { + $container_filename = $this->get_container_filename(); + if (!defined('DEBUG_CONTAINER') && $this->dump_container && file_exists($container_filename)) + { + require($container_filename); + $this->container = new \phpbb_cache_container(); + } + else + { + if ($this->config_path === null) + { + $this->config_path = $this->phpbb_root_path . 'config'; + } + $container_extensions = array(new \phpbb\di\extension\core($this->config_path)); + + if ($this->use_extensions) + { + $installed_exts = $this->get_installed_extensions(); + $container_extensions[] = new \phpbb\di\extension\ext($installed_exts); + } + + if ($this->inject_config) + { + $container_extensions[] = new \phpbb\di\extension\config($this->config_php_file); + } + + $this->container = $this->create_container($container_extensions); + + if ($this->use_custom_pass) + { + $this->container->addCompilerPass(new \phpbb\di\pass\collection_pass()); + + if ($this->use_kernel_pass) + { + $this->container->addCompilerPass(new \phpbb\di\pass\kernel_pass()); + } + } + + $this->inject_custom_parameters(); + + if ($this->compile_container) + { + $this->container->compile(); + } + + if ($this->dump_container && !defined('DEBUG_CONTAINER')) + { + $this->dump_container($container_filename); + } + } + + $this->container->set('config.php', $this->config_php_file); + + if ($this->compile_container) + { + $this->inject_dbal(); + } + + return $this->container; + } + + /** + * Set if the extensions should be used. + * + * @param bool $use_extensions + */ + public function set_use_extensions($use_extensions) + { + $this->use_extensions = $use_extensions; + } + + /** + * Set if the phpBB compile pass have to be used. + * + * @param bool $use_custom_pass + */ + public function set_use_custom_pass($use_custom_pass) + { + $this->use_custom_pass = $use_custom_pass; + } + + /** + * Set if the kernel compile pass have to be used. + * + * @param bool $use_kernel_pass + */ + public function set_use_kernel_pass($use_kernel_pass) + { + $this->use_kernel_pass = $use_kernel_pass; + } + + /** + * Set if the php config file should be injecting into the container. + * + * @param bool $inject_config + */ + public function set_inject_config($inject_config) + { + $this->inject_config = $inject_config; + } + + /** + * Set if a dump container should be used. + * + * If DEBUG_CONTAINER is set this option is ignored and a new container is build. + * + * @var bool $dump_container + */ + public function set_dump_container($dump_container) + { + $this->dump_container = $dump_container; + } + + /** + * Set if the container should be compiled automatically (default to true). + * + * @var bool $dump_container + */ + public function set_compile_container($compile_container) + { + $this->compile_container = $compile_container; + } + + /** + * Set a custom path to find the configuration of the container + * + * @param string $config_path + */ + public function set_config_path($config_path) + { + $this->config_path = $config_path; + } + + /** + * Set custom parameters to inject into the container. + * + * @param array $custom_parameters + */ + public function set_custom_parameters($custom_parameters) + { + $this->custom_parameters = $custom_parameters; + } + + /** + * Dump the container to the disk. + * + * @param string $container_filename The name of the file. + */ + protected function dump_container($container_filename) + { + $dumper = new PhpDumper($this->container); + $cached_container_dump = $dumper->dump(array( + 'class' => 'phpbb_cache_container', + 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', + )); + + file_put_contents($container_filename, $cached_container_dump); + } + + /** + * Inject the connection into the container if one was opened. + */ + protected function inject_dbal() + { + if ($this->dbal_connection !== null) + { + $this->container->get('dbal.conn')->set_driver($this->dbal_connection); + } + } + + /** + * Get DB connection. + * + * @return \phpbb\db\driver\driver_interface + */ + protected function get_dbal_connection() + { + if ($this->dbal_connection === null) + { + $dbal_driver_class = $this->config_php_file->convert_30_dbms_to_31($this->config_php_file->get('dbms')); + $this->dbal_connection = new $dbal_driver_class(); + $this->dbal_connection->sql_connect( + $this->config_php_file->get('dbhost'), + $this->config_php_file->get('dbuser'), + $this->config_php_file->get('dbpasswd'), + $this->config_php_file->get('dbname'), + $this->config_php_file->get('dbport'), + defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK + ); + } + + return $this->dbal_connection; + } + + /** + * Get enabled extensions. + * + * @return array enabled extensions + */ + protected function get_installed_extensions() + { + $db = $this->get_dbal_connection(); + $extension_table = $this->config_php_file->get('table_prefix') . 'ext'; + + $sql = 'SELECT * + FROM ' . $extension_table . ' + WHERE ext_active = 1'; + + $result = $db->sql_query($sql); + $rows = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + $exts = array(); + foreach ($rows as $row) + { + $exts[$row['ext_name']] = $this->phpbb_root_path . 'ext/' . $row['ext_name'] . '/'; + } + + return $exts; + } + + /** + * Create the ContainerBuilder object + * + * @param array $extensions Array of Container extension objects + * @return ContainerBuilder object + */ + protected function create_container(array $extensions) + { + $container = new ContainerBuilder(); + + foreach ($extensions as $extension) + { + $container->registerExtension($extension); + $container->loadFromExtension($extension->getAlias()); + } + + return $container; + } + + /** + * Inject the customs parameters into the container + */ + protected function inject_custom_parameters() + { + if ($this->custom_parameters === null) + { + $this->custom_parameters = array( + 'core.root_path' => $this->phpbb_root_path, + 'core.php_ext' => $this->php_ext, + ); + } + + foreach ($this->custom_parameters as $key => $value) + { + $this->container->setParameter($key, $value); + } + } + + /** + * Get the filename under which the dumped container will be stored. + * + * @return string Path for dumped container + */ + protected function get_container_filename() + { + $filename = str_replace(array('/', '.'), array('slash', 'dot'), $this->phpbb_root_path); + return $this->phpbb_root_path . 'cache/container_' . $filename . '.' . $this->php_ext; + } +} diff --git a/phpBB/phpbb/di/extension/config.php b/phpBB/phpbb/di/extension/config.php index a7d7284f85..27ebc94bae 100644 --- a/phpBB/phpbb/di/extension/config.php +++ b/phpBB/phpbb/di/extension/config.php @@ -21,9 +21,12 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; */ class config extends Extension { - public function __construct($config_file) + /** @var array */ + protected $config_php; + + public function __construct(\phpbb\config_php_file $config_php) { - $this->config_file = $config_file; + $this->config_php = $config_php; } /** @@ -36,17 +39,15 @@ class config extends Extension */ public function load(array $config, ContainerBuilder $container) { - require($this->config_file); - - $container->setParameter('core.adm_relative_path', (isset($phpbb_adm_relative_path) ? $phpbb_adm_relative_path : 'adm/')); - $container->setParameter('core.table_prefix', $table_prefix); - $container->setParameter('cache.driver.class', $this->convert_30_acm_type($acm_type)); - $container->setParameter('dbal.driver.class', phpbb_convert_30_dbms_to_31($dbms)); - $container->setParameter('dbal.dbhost', $dbhost); - $container->setParameter('dbal.dbuser', $dbuser); - $container->setParameter('dbal.dbpasswd', $dbpasswd); - $container->setParameter('dbal.dbname', $dbname); - $container->setParameter('dbal.dbport', $dbport); + $container->setParameter('core.adm_relative_path', ($this->config_php->get('phpbb_adm_relative_path') ? $this->config_php->get('phpbb_adm_relative_path') : 'adm/')); + $container->setParameter('core.table_prefix', $this->config_php->get('table_prefix')); + $container->setParameter('cache.driver.class', $this->convert_30_acm_type($this->config_php->get('acm_type'))); + $container->setParameter('dbal.driver.class', $this->config_php->convert_30_dbms_to_31($this->config_php->get('dbms'))); + $container->setParameter('dbal.dbhost', $this->config_php->get('dbhost')); + $container->setParameter('dbal.dbuser', $this->config_php->get('dbuser')); + $container->setParameter('dbal.dbpasswd', $this->config_php->get('dbpasswd')); + $container->setParameter('dbal.dbname', $this->config_php->get('dbname')); + $container->setParameter('dbal.dbport', $this->config_php->get('dbport')); $container->setParameter('dbal.new_link', defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK); } diff --git a/phpBB/phpbb/event/dispatcher.php b/phpBB/phpbb/event/dispatcher.php index 6a2f9008be..9a786022c2 100644 --- a/phpBB/phpbb/event/dispatcher.php +++ b/phpBB/phpbb/event/dispatcher.php @@ -29,8 +29,11 @@ use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; * extract($phpbb_dispatcher->trigger_event('core.index', compact($vars))); * */ -class dispatcher extends ContainerAwareEventDispatcher +class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_interface { + /** + * {@inheritdoc} + */ public function trigger_event($eventName, $data = array()) { $event = new \phpbb\event\data($data); diff --git a/phpBB/phpbb/event/dispatcher_interface.php b/phpBB/phpbb/event/dispatcher_interface.php new file mode 100644 index 0000000000..50a3ef9101 --- /dev/null +++ b/phpBB/phpbb/event/dispatcher_interface.php @@ -0,0 +1,40 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\event; + +/** +* Extension of the Symfony2 EventDispatcher +* +* It provides an additional `trigger_event` method, which +* gives some syntactic sugar for dispatching events. Instead +* of creating the event object, the method will do that for +* you. +* +* Example: +* +* $vars = array('page_title'); +* extract($phpbb_dispatcher->trigger_event('core.index', compact($vars))); +* +*/ +interface dispatcher_interface extends \Symfony\Component\EventDispatcher\EventDispatcherInterface +{ + /** + * Construct and dispatch an event + * + * @param string $eventName The event name + * @param array $data An array containing the variables sending with the event + * @return mixed + */ + public function trigger_event($eventName, $data = array()); +} diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index a11c2a457f..f7021875f3 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -227,7 +227,7 @@ class md_exporter */ public function validate_since($since) { - if (!preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?$#', $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}'"); } diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index 3d2819a3a1..badbbb48fd 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -550,7 +550,7 @@ class php_exporter public function validate_since($line) { $match = array(); - preg_match('#^\* @since (\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?)$#', ltrim($line, "\t"), $match); + 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 " diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 52d9395c82..4a12e9ec8c 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -77,11 +77,12 @@ class manager { $this->extensions = array(); - // Do not try to load any extensions when installing or updating + // Do not try to load any extensions if the extension table + // does not exist or when installing or updating. // Note: database updater invokes this code, and in 3.0 // there is no extension table therefore the rest of this function // fails - if (defined('IN_INSTALL')) + if (defined('IN_INSTALL') || version_compare($this->config['version'], '3.1.0-dev', '<')) { return; } @@ -423,7 +424,7 @@ class manager foreach ($iterator as $file_info) { - if ($file_info->isFile() && $file_info->getFilename() == 'ext.' . $this->php_ext) + if ($file_info->isFile() && $file_info->getFilename() == 'composer.json') { $ext_name = $iterator->getInnerIterator()->getSubPath(); $composer_file = $iterator->getPath() . '/composer.json'; @@ -515,7 +516,7 @@ class manager * @param string $name Extension name to check NOTE: Can be user input * @return bool Depending on whether or not the extension is available */ - public function available($name) + public function is_available($name) { return file_exists($this->get_extension_path($name, true)); } @@ -526,12 +527,50 @@ class manager * @param string $name Extension name to check * @return bool Depending on whether or not the extension is enabled */ - public function enabled($name) + public function is_enabled($name) { return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active']; } /** + * Check to see if a given extension is disabled + * + * @param string $name Extension name to check + * @return bool Depending on whether or not the extension is disabled + */ + public function is_disabled($name) + { + return isset($this->extensions[$name]) && !$this->extensions[$name]['ext_active']; + } + + /** + * Check to see if a given extension is configured + * + * All enabled and disabled extensions are considered configured. A purged + * extension that is no longer in the database is not configured. + * + * @param string $name Extension name to check + * @return bool Depending on whether or not the extension is configured + */ + public function is_configured($name) + { + return isset($this->extensions[$name]); + } + + /** + * Check to see if a given extension is purged + * + * An extension is purged if it is available, not enabled and not disabled. + * + * @param string $name Extension name to check + * @return bool Depending on whether or not the extension is purged + */ + public function is_purged($name) + { + return $this->is_available($name) && !$this->is_configured($name); + } + + /** * Instantiates a \phpbb\finder. * * @param bool $use_all_available Should we load all extensions, or just enabled ones diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 014d8c79c7..1051021ea7 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -306,7 +306,7 @@ class metadata_manager */ public function validate_require_phpbb() { - if (!isset($this->metadata['require']['phpbb/phpbb'])) + if (!isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) { return false; } @@ -369,7 +369,7 @@ class metadata_manager '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/phpbb'])) ? htmlspecialchars($this->metadata['require']['phpbb/phpbb']) : '', + 'META_REQUIRE_PHPBB' => (isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) ? htmlspecialchars($this->metadata['extra']['soft-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/filesystem.php b/phpBB/phpbb/filesystem.php index 683a12ab76..77517082e5 100644 --- a/phpBB/phpbb/filesystem.php +++ b/phpBB/phpbb/filesystem.php @@ -35,7 +35,7 @@ class filesystem continue; } - if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '..') + if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') { array_pop($filtered); } diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index bf0bfe0ae1..2af8b50b54 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -70,7 +70,7 @@ class log implements \phpbb\log\log_interface /** * Event dispatcher object - * @var \phpbb\event\dispatcher + * @var \phpbb\event\dispatcher_interface */ protected $dispatcher; @@ -98,7 +98,7 @@ class log implements \phpbb\log\log_interface * @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 \phpbb\event\dispatcher_interface $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 @@ -245,9 +245,9 @@ class log implements \phpbb\log\log_interface break; case 'mod': - $forum_id = (int) $additional_data['forum_id']; + $forum_id = isset($additional_data['forum_id']) ? (int) $additional_data['forum_id'] : 0; unset($additional_data['forum_id']); - $topic_id = (int) $additional_data['topic_id']; + $topic_id = isset($additional_data['topic_id']) ? (int) $additional_data['topic_id'] : 0; unset($additional_data['topic_id']); $sql_ary += array( 'log_type' => LOG_MOD, @@ -737,7 +737,7 @@ class log implements \phpbb\log\log_interface for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++) { $keywords_pattern[] = preg_quote($keywords[$i], '#'); - $keywords[$i] = $this->db->sql_like_expression($this->db->any_char . $keywords[$i] . $this->db->any_char); + $keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char()); } $keywords_pattern = '#' . implode('|', $keywords_pattern) . '#ui'; diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index c1d4d0e257..910f51b3a6 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -308,16 +308,15 @@ abstract class base implements \phpbb\notification\type\type_interface return array( 'NOTIFICATION_ID' => $this->notification_id, - + 'STYLING' => $this->get_style_class(), 'AVATAR' => $this->get_avatar(), - 'FORMATTED_TITLE' => $this->get_title(), - + 'REFERENCE' => $this->get_reference(), + 'FORUM' => $this->get_forum(), + 'REASON' => $this->get_reason(), 'URL' => $this->get_url(), 'TIME' => $this->user->format_date($this->notification_time), - 'UNREAD' => !$this->notification_read, - 'U_MARK_READ' => (!$this->notification_read) ? $u_mark_read : '', ); } @@ -337,6 +336,16 @@ abstract class base implements \phpbb\notification\type\type_interface } /** + * Get the CSS style class of the notification (fall back) + * + * @return string + */ + public function get_style_class() + { + return ''; + } + + /** * Get the user's avatar (fall back) * * @return string @@ -347,6 +356,36 @@ abstract class base implements \phpbb\notification\type\type_interface } /** + * Get the reference of the notifcation (fall back) + * + * @return string + */ + public function get_reference() + { + return ''; + } + + /** + * Get the forum of the notification reference (fall back) + * + * @return string + */ + public function get_forum() + { + return ''; + } + + /** + * Get the reason for the notifcation (fall back) + * + * @return string + */ + public function get_reason() + { + return ''; + } + + /** * Get the special items to load (fall back) * * @return array diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php index b5f94f404f..7b18ed70ea 100644 --- a/phpBB/phpbb/notification/type/disapprove_post.php +++ b/phpBB/phpbb/notification/type/disapprove_post.php @@ -31,6 +31,16 @@ class disapprove_post extends \phpbb\notification\type\approve_post } /** + * Get the CSS style class of the notification + * + * @return string + */ + public function get_style_class() + { + return 'notification-disapproved'; + } + + /** * Language key used to output the text * * @var string @@ -63,9 +73,31 @@ class disapprove_post extends \phpbb\notification\type\approve_post */ public function get_title() { + return $this->user->lang($this->language_key); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('topic_title')) + ); + } + + /** + * Get the reason for the disapproval notification + * + * @return string + */ + public function get_reason() + { return $this->user->lang( - $this->language_key, - censor_text($this->get_data('topic_title')), + 'NOTIFICATION_REASON', $this->get_data('disapprove_reason') ); } diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php index 8883c53294..3f87741807 100644 --- a/phpBB/phpbb/notification/type/disapprove_topic.php +++ b/phpBB/phpbb/notification/type/disapprove_topic.php @@ -31,6 +31,16 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic } /** + * Get the CSS style class of the notification + * + * @return string + */ + public function get_style_class() + { + return 'notification-disapproved'; + } + + /** * Language key used to output the text * * @var string @@ -63,9 +73,31 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic */ public function get_title() { + return $this->user->lang($this->language_key); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('topic_title')) + ); + } + + /** + * Get the reason for the disapproval notification + * + * @return string + */ + public function get_reason() + { return $this->user->lang( - $this->language_key, - censor_text($this->get_data('topic_title')), + 'NOTIFICATION_REASON', $this->get_data('disapprove_reason') ); } diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 955d121cc6..4f54e93e06 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -111,7 +111,20 @@ class pm extends \phpbb\notification\type\base { $username = $this->user_loader->get_username($this->get_data('from_user_id'), 'no_profile'); - return $this->user->lang('NOTIFICATION_PM', $username, $this->get_data('message_subject')); + return $this->user->lang('NOTIFICATION_PM', $username); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + $this->get_data('message_subject') + ); } /** diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index c8760f904e..ee3a253e0f 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -225,12 +225,24 @@ class post extends \phpbb\notification\type\base return $this->user->lang( $this->language_key, phpbb_generate_string_list($usernames, $this->user), - censor_text($this->get_data('topic_title')), $responders_cnt ); } /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('topic_title')) + ); + } + + /** * 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 03e89dd28e..2eb802eb4b 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -31,6 +31,16 @@ class report_pm extends \phpbb\notification\type\pm } /** + * Get the CSS style class of the notification + * + * @return string + */ + public function get_style_class() + { + return 'notification-reported'; + } + + /** * Language key used to output the text * * @var string @@ -159,12 +169,36 @@ class report_pm extends \phpbb\notification\type\pm $username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile'); + return $this->user->lang( + $this->language_key, + $username + ); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('message_subject')) + ); + } + + /** + * Get the reason for the notification + * + * @return string + */ + public function get_reason() + { if ($this->get_data('report_text')) { return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('message_subject')), + 'NOTIFICATION_REASON', $this->get_data('report_text') ); } @@ -172,17 +206,13 @@ class report_pm extends \phpbb\notification\type\pm if (isset($this->user->lang[$this->get_data('reason_title')])) { return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('message_subject')), + 'NOTIFICATION_REASON', $this->user->lang[$this->get_data('reason_title')] ); } return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('message_subject')), + 'NOTIFICATION_REASON', $this->get_data('reason_description') ); } diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php index a646996f75..ed40df67f3 100644 --- a/phpBB/phpbb/notification/type/report_pm_closed.php +++ b/phpBB/phpbb/notification/type/report_pm_closed.php @@ -107,7 +107,19 @@ class report_pm_closed extends \phpbb\notification\type\pm return $this->user->lang( $this->language_key, - $username, + $username + ); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', censor_text($this->get_data('message_subject')) ); } diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php index d5589a6756..024c8d9d42 100644 --- a/phpBB/phpbb/notification/type/report_post.php +++ b/phpBB/phpbb/notification/type/report_post.php @@ -30,6 +30,16 @@ class report_post extends \phpbb\notification\type\post_in_queue } /** + * Get the CSS style class of the notification + * + * @return string + */ + public function get_style_class() + { + return 'notification-reported'; + } + + /** * Language key used to output the text * * @var string @@ -132,12 +142,36 @@ class report_post extends \phpbb\notification\type\post_in_queue $username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile'); + return $this->user->lang( + $this->language_key, + $username + ); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('post_subject')) + ); + } + + /** + * Get the reason for the notification + * + * @return string + */ + public function get_reason() + { if ($this->get_data('report_text')) { return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('post_subject')), + 'NOTIFICATION_REASON', $this->get_data('report_text') ); } @@ -145,17 +179,13 @@ class report_post extends \phpbb\notification\type\post_in_queue if (isset($this->user->lang[$this->get_data('reason_title')])) { return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('post_subject')), + 'NOTIFICATION_REASON', $this->user->lang[$this->get_data('reason_title')] ); } return $this->user->lang( - $this->language_key, - $username, - censor_text($this->get_data('post_subject')), + 'NOTIFICATION_REASON', $this->get_data('reason_description') ); } diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php index e76fa57036..a979af1fb0 100644 --- a/phpBB/phpbb/notification/type/report_post_closed.php +++ b/phpBB/phpbb/notification/type/report_post_closed.php @@ -114,7 +114,19 @@ class report_post_closed extends \phpbb\notification\type\post return $this->user->lang( $this->language_key, - $username, + $username + ); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', censor_text($this->get_data('post_subject')) ); } diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 144c4e58a0..a512a12f20 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -151,8 +151,32 @@ class topic extends \phpbb\notification\type\base return $this->user->lang( $this->language_key, - $username, - censor_text($this->get_data('topic_title')), + $username + ); + } + + /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference() + { + return $this->user->lang( + 'NOTIFICATION_REFERENCE', + censor_text($this->get_data('topic_title')) + ); + } + + /** + * Get the forum of the notification reference + * + * @return string + */ + public function get_forum() + { + return $this->user->lang( + 'NOTIFICATION_FORUM', $this->get_data('forum_name') ); } diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php index c91c7078ad..5c5a110836 100644 --- a/phpBB/phpbb/notification/type/type_interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -88,6 +88,13 @@ interface type_interface public function load_special($data, $notifications); /** + * Get the CSS style class of the notification + * + * @return string + */ + public function get_style_class(); + + /** * Get the HTML formatted title of this notification * * @return string @@ -95,6 +102,20 @@ interface type_interface public function get_title(); /** + * Get the HTML formatted reference of the notification + * + * @return string + */ + public function get_reference(); + + /** + * Get the forum of the notification reference + * + * @return string + */ + public function get_forum(); + + /** * Get the url to this item * * @return string URL diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index a5314d2ce1..a8592eac6c 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -24,6 +24,9 @@ class path_helper /** @var \phpbb\filesystem */ protected $filesystem; + /** @var \phpbb\request\request_interface */ + protected $request; + /** @var string */ protected $phpbb_root_path; @@ -41,13 +44,16 @@ class path_helper * * @param \phpbb\symfony_request $symfony_request * @param \phpbb\filesystem $filesystem + * @param \phpbb\request\request_interface $request * @param string $phpbb_root_path Relative path to phpBB root * @param string $php_ext PHP extension (php) + * @param mixed $adm_relative_path Relative path admin path to adm/ root */ - public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $adm_relative_path = null) + public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null) { $this->symfony_request = $symfony_request; $this->filesystem = $filesystem; + $this->request = $request; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; $this->adm_relative_path = $adm_relative_path; @@ -98,7 +104,13 @@ class path_helper { $path = substr($path, strlen($this->phpbb_root_path)); - return $this->get_web_root_path() . $path; + $web_root_path = $this->get_web_root_path(); + if (substr($web_root_path, -8) === 'app.php/' && substr($path, 0, 7) === 'app.php') + { + $path = substr($path, 8); + } + + return $this->filesystem->clean_path($web_root_path . $path); } return $path; @@ -158,7 +170,7 @@ class path_helper */ if ($path_info === '/' && preg_match('/app\.' . $this->php_ext . '\/$/', $request_uri)) { - return $this->web_root_path = $this->phpbb_root_path . '../'; + return $this->web_root_path = $this->filesystem->clean_path('./../' . $this->phpbb_root_path); } /* @@ -170,31 +182,111 @@ class path_helper return $this->web_root_path = $this->phpbb_root_path; } + /* + * Check AJAX request: + * If the current request is a AJAX we need to fix the paths. + * We need to get the root path based on the Referer, so we can use + * the generated URLs in the template of the Referer. If we do not + * generate the relative path based on the Referer, but based on the + * currently requested URL, the generated URLs will not point to the + * intended locations: + * Referer desired URL desired relative root path + * memberlist.php faq.php ./ + * memberlist.php app.php/foo/bar ./ + * app.php/foo memberlist.php ../ + * app.php/foo app.php/fox ../ + * app.php/foo/bar memberlist.php ../../ + * ../page.php memberlist.php ./phpBB/ + * ../sub/page.php memberlist.php ./../phpBB/ + * + * The referer must be specified as a parameter in the query. + */ + if ($this->request->is_ajax() && $this->symfony_request->get('_referer')) + { + $referer_web_root_path = $this->get_web_root_path_from_ajax_referer( + $this->symfony_request->get('_referer'), + $this->symfony_request->getSchemeAndHttpHost() . $this->symfony_request->getBasePath() + ); + return $this->web_root_path = $this->phpbb_root_path . $referer_web_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 the script name (e.g. phpBB/app.php) does not exists in the + * requestUri (e.g. phpBB/app.php/foo/template), then we are rewriting + * the URL. So we must reduce the slash count by 1. */ - if (strpos($request_uri, $script_name) === 0) + 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); + $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); + // Prepend ../ to the phpbb_root_path as many times as / exists in path_info + $this->web_root_path = $this->filesystem->clean_path( + './' . str_repeat('../', $corrections) . $this->phpbb_root_path + ); + return $this->web_root_path; + } + + /** + * Get the web root path of the referer form an ajax request + * + * @param string $absolute_referer_url + * @param string $absolute_board_url + * @return string + */ + public function get_web_root_path_from_ajax_referer($absolute_referer_url, $absolute_board_url) + { + // If the board URL is in the beginning of the referer, this means + // we the referer is in the board URL or a subdirectory of it. + // So we just need to count the / (slashes) in the left over part of + // the referer and prepend ../ the the current root_path, to get the + // web root path of the referer. + if (strpos($absolute_referer_url, $absolute_board_url) === 0) + { + $relative_referer_path = substr($absolute_referer_url, strlen($absolute_board_url)); + $has_params = strpos($relative_referer_path, '?'); + if ($has_params !== false) + { + $relative_referer_path = substr($relative_referer_path, 0, $has_params); + } + $corrections = substr_count($relative_referer_path, '/'); + return $this->phpbb_root_path . str_repeat('../', $corrections - 1); + } + + // If not, it's a bit more complicated. We go to the parent directory + // of the referer until we find the remaining referer in the board URL. + // Foreach directory we need to add a ../ to the fixed root_path. + // When we finally found it, we need to remove the remaining referer + // from the board URL, to get the boards root path. + // If the then append these two strings, we get our fixed web root path. + $fixed_root_path = ''; + $referer_dir = $absolute_referer_url; + $has_params = strpos($referer_dir, '?'); + if ($has_params !== false) + { + $referer_dir = substr($referer_dir, 0, $has_params); + } + + // If we do not find a slash at the end of the referer, we come + // from a file. So the first dirname() does not need a traversal + // path correction. + if (substr($referer_dir, -1) !== '/') + { + $referer_dir = dirname($referer_dir); + } + + while (strpos($absolute_board_url, $referer_dir) !== 0) + { + $fixed_root_path .= '../'; + $referer_dir = dirname($referer_dir); + } + + $fixed_root_path .= substr($absolute_board_url, strlen($referer_dir) + 1); + // Add trailing slash + return $this->phpbb_root_path . $fixed_root_path . '/'; } /** diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php index 3f51016c93..9b3dcadf32 100644 --- a/phpBB/phpbb/permissions.php +++ b/phpBB/phpbb/permissions.php @@ -17,7 +17,7 @@ class permissions { /** * Event dispatcher object - * @var \phpbb\event\dispatcher + * @var \phpbb\event\dispatcher_interface */ protected $dispatcher; @@ -30,10 +30,10 @@ class permissions /** * Constructor * - * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher + * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher * @param \phpbb\user $user User Object */ - public function __construct(\phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\user $user) + public function __construct(\phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\user $user) { $this->dispatcher = $phpbb_dispatcher; $this->user = $user; diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php index c610d49a63..3c686a552f 100644 --- a/phpBB/phpbb/plupload/plupload.php +++ b/phpBB/phpbb/plupload/plupload.php @@ -79,8 +79,7 @@ class plupload $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'; + $this->set_default_directories(); } /** @@ -120,6 +119,9 @@ class plupload { rename("{$file_path}.part", $file_path); + // Reset upload directories to defaults once completed + $this->set_default_directories(); + // Need to modify some of the $_FILES values to reflect the new file return array( 'tmp_name' => $file_path, @@ -372,4 +374,29 @@ class plupload ); } } + + /** + * Sets the default directories for uploads + * + * @return null + */ + protected function set_default_directories() + { + $this->upload_directory = $this->phpbb_root_path . $this->config['upload_path']; + $this->temporary_directory = $this->upload_directory . '/plupload'; + } + + /** + * Sets the upload directories to the specified paths + * + * @param string $upload_directory Upload directory + * @param string $temporary_directory Temporary directory + * + * @return null + */ + public function set_upload_directories($upload_directory, $temporary_directory) + { + $this->upload_directory = $upload_directory; + $this->temporary_directory = $temporary_directory; + } } diff --git a/phpBB/phpbb/profilefields/lang_helper.php b/phpBB/phpbb/profilefields/lang_helper.php index c055931181..2e353722b2 100644 --- a/phpBB/phpbb/profilefields/lang_helper.php +++ b/phpBB/phpbb/profilefields/lang_helper.php @@ -49,43 +49,50 @@ class lang_helper } /** - * Get language entries for options and store them here for later use + * Loads preview options into language entries for options + * + * @param int $field_id + * @param int $lang_id + * @param mixed $preview_options */ - public function get_option_lang($field_id, $lang_id, $field_type, $preview_options) + public function load_preview_options($field_id, $lang_id, $preview_options) { - if ($preview_options !== false) - { - $lang_options = (!is_array($preview_options)) ? explode("\n", $preview_options) : $preview_options; + $lang_options = (!is_array($preview_options)) ? explode("\n", $preview_options) : $preview_options; - foreach ($lang_options as $num => $var) + 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])) { - 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; + $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 + } + + /** + * Fetches language entries for options from DB + * + * @param int $lang_id + */ + public function load_option_lang($lang_id) + { + $sql = 'SELECT field_id, 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) . "' + WHERE lang_id = ' . (int) $lang_id . " 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); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $this->options_lang[$row['field_id']][$lang_id][($row['option_id'] + 1)] = $row['lang_value']; } + + $this->db->sql_freeresult($result); } /** diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php index 490db0419a..98802d2209 100644 --- a/phpBB/phpbb/profilefields/manager.php +++ b/phpBB/phpbb/profilefields/manager.php @@ -32,7 +32,7 @@ class manager /** * Event dispatcher object - * @var \phpbb\event\dispatcher + * @var \phpbb\event\dispatcher_interface */ protected $dispatcher; @@ -73,7 +73,7 @@ class manager * * @param \phpbb\auth\auth $auth Auth object * @param \phpbb\db\driver\driver_interface $db Database object - * @param \phpbb\event\dispatcher $dispatcher Event dispatcher object + * @param \phpbb\event\dispatcher_interface $dispatcher Event dispatcher object * @param \phpbb\request\request $request Request object * @param \phpbb\template\template $template Template object * @param \phpbb\di\service_collection $type_collection @@ -82,7 +82,7 @@ class manager * @param string $fields_language_table * @param string $fields_data_table */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher $dispatcher, \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) + public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \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; @@ -389,6 +389,7 @@ class manager { $profile_field = $this->type_collection[$ident_ary['data']['field_type']]; $value = $profile_field->get_profile_value($ident_ary['value'], $ident_ary['data']); + $value_raw = $profile_field->get_profile_value_raw($ident_ary['value'], $ident_ary['data']); if ($value === null) { @@ -396,7 +397,7 @@ class manager } $field_desc = $contact_url = ''; - if ($use_contact_fields) + if ($use_contact_fields && $ident_ary['data']['field_is_contact']) { $value = $profile_field->get_profile_contact_value($ident_ary['value'], $ident_ary['data']); $field_desc = $this->user->lang($ident_ary['data']['field_contact_desc']); @@ -412,26 +413,28 @@ class manager } $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']), + 'PROFILE_' . strtoupper($ident) . '_IDENT' => $ident, + 'PROFILE_' . strtoupper($ident) . '_VALUE' => $value, + 'PROFILE_' . strtoupper($ident) . '_VALUE_RAW' => $value_raw, + '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']), + 'PROFILE_FIELD_IDENT' => $ident, + 'PROFILE_FIELD_VALUE' => $value, + 'PROFILE_FIELD_VALUE_RAW' => $value_raw, + '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, diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php index eb8d3e47d6..0582722833 100644 --- a/phpBB/phpbb/profilefields/type/type_bool.php +++ b/phpBB/phpbb/profilefields/type/type_bool.php @@ -155,7 +155,7 @@ class type_bool extends type_base if (!$this->lang_helper->is_set($field_id, $lang_id)) { - $this->lang_helper->get_option_lang($field_id, $lang_id, FIELD_BOOL, false); + $this->lang_helper->load_option_lang($lang_id); } if (!$field_value && $field_data['field_show_novalue']) @@ -180,6 +180,24 @@ class type_bool extends type_base /** * {@inheritDoc} */ + public function get_profile_value_raw($field_value, $field_data) + { + if ($field_value == $field_data['field_novalue'] && !$field_data['field_show_novalue']) + { + return null; + } + + if (!$field_value && $field_data['field_show_novalue']) + { + $field_value = $field_data['field_novalue']; + } + + 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']; @@ -203,7 +221,14 @@ class type_bool extends type_base { 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); + if ($preview_options) + { + $this->lang_helper->load_preview_options($profile_row['field_id'], $profile_row['lang_id'], $preview_options); + } + else + { + $this->lang_helper->load_option_lang($profile_row['lang_id']); + } } $options = $this->lang_helper->get($profile_row['field_id'], $profile_row['lang_id']); diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php index 158eec6a0c..90ac9a6703 100644 --- a/phpBB/phpbb/profilefields/type/type_date.php +++ b/phpBB/phpbb/profilefields/type/type_date.php @@ -208,6 +208,19 @@ class type_date extends type_base /** * {@inheritDoc} */ + public function get_profile_value_raw($field_value, $field_data) + { + if (($field_value === '' || $field_value === null) && !$field_data['field_show_novalue']) + { + return null; + } + + 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']; diff --git a/phpBB/phpbb/profilefields/type/type_dropdown.php b/phpBB/phpbb/profilefields/type/type_dropdown.php index 52c9fcf86a..17ae89e1b2 100644 --- a/phpBB/phpbb/profilefields/type/type_dropdown.php +++ b/phpBB/phpbb/profilefields/type/type_dropdown.php @@ -135,7 +135,7 @@ class type_dropdown extends type_base // 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); + $this->lang_helper->load_option_lang($field_data['lang_id']); } if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], $field_value)) @@ -160,7 +160,7 @@ class type_dropdown extends type_base $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); + $this->lang_helper->load_option_lang($lang_id); } if ($field_value == $field_data['field_novalue'] && !$field_data['field_show_novalue']) @@ -189,6 +189,24 @@ class type_dropdown extends type_base /** * {@inheritDoc} */ + public function get_profile_value_raw($field_value, $field_data) + { + if ($field_value == $field_data['field_novalue'] && !$field_data['field_show_novalue']) + { + return null; + } + + if (!$field_value && $field_data['field_show_novalue']) + { + $field_value = $field_data['field_novalue']; + } + + 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']; @@ -199,7 +217,14 @@ class type_dropdown extends type_base 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); + if ($preview_options) + { + $this->lang_helper->load_preview_options($profile_row['field_id'], $profile_row['lang_id'], $preview_options); + } + else + { + $this->lang_helper->load_option_lang($profile_row['lang_id']); + } } $profile_row['field_value'] = (int) $value; diff --git a/phpBB/phpbb/profilefields/type/type_googleplus.php b/phpBB/phpbb/profilefields/type/type_googleplus.php new file mode 100644 index 0000000000..887baa3de1 --- /dev/null +++ b/phpBB/phpbb/profilefields/type/type_googleplus.php @@ -0,0 +1,66 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\profilefields\type; + +class type_googleplus extends type_string +{ + /** + * {@inheritDoc} + */ + public function get_name() + { + return $this->user->lang('FIELD_GOOGLEPLUS'); + } + + /** + * {@inheritDoc} + */ + public function get_service_name() + { + return 'profilefields.type.googleplus'; + } + + /** + * {@inheritDoc} + */ + public function get_default_option_values() + { + return array( + 'field_length' => 20, + 'field_minlen' => 3, + 'field_maxlen' => 255, + 'field_validation' => '[\w]+', + 'field_novalue' => '', + 'field_default_value' => '', + ); + } + + /** + * {@inheritDoc} + */ + public function get_profile_contact_value($field_value, $field_data) + { + if (!$field_value && !$field_data['field_show_novalue']) + { + return null; + } + + if (!is_numeric($field_value)) + { + $field_value = '+' . $field_value; + } + + return $field_value; + } +} diff --git a/phpBB/phpbb/profilefields/type/type_int.php b/phpBB/phpbb/profilefields/type/type_int.php index 78f1c7d2c9..dd08df94c1 100644 --- a/phpBB/phpbb/profilefields/type/type_int.php +++ b/phpBB/phpbb/profilefields/type/type_int.php @@ -154,6 +154,18 @@ class type_int extends type_base /** * {@inheritDoc} */ + public function get_profile_value_raw($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']; diff --git a/phpBB/phpbb/profilefields/type/type_interface.php b/phpBB/phpbb/profilefields/type/type_interface.php index 489e916fd5..2dd13fa480 100644 --- a/phpBB/phpbb/profilefields/type/type_interface.php +++ b/phpBB/phpbb/profilefields/type/type_interface.php @@ -94,6 +94,15 @@ interface type_interface public function get_profile_value($field_value, $field_data); /** + * Get Profile Value ID for display (the raw, unprocessed user data) + * + * @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 ID to display + */ + public function get_profile_value_raw($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 diff --git a/phpBB/phpbb/profilefields/type/type_string_common.php b/phpBB/phpbb/profilefields/type/type_string_common.php index b48e3c5add..0eaf7e527d 100644 --- a/phpBB/phpbb/profilefields/type/type_string_common.php +++ b/phpBB/phpbb/profilefields/type/type_string_common.php @@ -98,7 +98,7 @@ abstract class type_string_common extends type_base */ public function get_profile_value($field_value, $field_data) { - if (!$field_value && !$field_data['field_show_novalue']) + if (($field_value === null || $field_value === '') && !$field_data['field_show_novalue']) { return null; } @@ -112,9 +112,9 @@ abstract class type_string_common extends type_base /** * {@inheritDoc} */ - public function get_profile_contact_value($field_value, $field_data) + public function get_profile_value_raw($field_value, $field_data) { - if (!$field_value && !$field_data['field_show_novalue']) + if (($field_value === null || $field_value === '') && !$field_data['field_show_novalue']) { return null; } @@ -125,6 +125,14 @@ abstract class type_string_common extends type_base /** * {@inheritDoc} */ + public function get_profile_contact_value($field_value, $field_data) + { + return $this->get_profile_value_raw($field_value, $field_data); + } + + /** + * {@inheritDoc} + */ public function prepare_options_form(&$exclude_options, &$visibility_options) { $exclude_options[1][] = 'lang_default_value'; diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/base.php index 861b1f9328..9395b6a273 100644 --- a/phpBB/phpbb/search/base.php +++ b/phpBB/phpbb/search/base.php @@ -282,7 +282,7 @@ class base $sql_where = ''; foreach ($words as $word) { - $sql_where .= " OR search_keywords " . $db->sql_like_expression($db->any_char . $word . $db->any_char); + $sql_where .= " OR search_keywords " . $db->sql_like_expression($db->get_any_char() . $word . $db->get_any_char()); } $sql = 'SELECT search_key @@ -303,7 +303,7 @@ class base $sql_where = ''; foreach ($authors as $author) { - $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $db->sql_like_expression($db->any_char . ' ' . (int) $author . ' ' . $db->any_char); + $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $db->sql_like_expression($db->get_any_char() . ' ' . (int) $author . ' ' . $db->get_any_char()); } $sql = 'SELECT search_key diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index 3e8e492cd8..d4e7de31e5 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -140,7 +140,7 @@ class fulltext_mysql extends \phpbb\search\base */ public function init() { - if ($this->db->sql_layer != 'mysql4' && $this->db->sql_layer != 'mysqli') + if ($this->db->get_sql_layer() != 'mysql4' && $this->db->get_sql_layer() != 'mysqli') { return $this->user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE']; } @@ -764,7 +764,7 @@ class fulltext_mysql extends \phpbb\search\base if (!isset($this->stats['post_subject'])) { - if ($this->db->sql_layer == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) + if ($this->db->get_sql_layer() == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) { $alter[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; } @@ -777,7 +777,7 @@ class fulltext_mysql extends \phpbb\search\base if (!isset($this->stats['post_content'])) { - if ($this->db->sql_layer == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) + if ($this->db->get_sql_layer() == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) { $alter[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL'; } @@ -872,7 +872,7 @@ class fulltext_mysql extends \phpbb\search\base */ protected function get_stats() { - if (strpos($this->db->sql_layer, 'mysql') === false) + if (strpos($this->db->get_sql_layer(), 'mysql') === false) { $this->stats = array(); return; diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 8d97916ec5..34947b176d 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -758,7 +758,7 @@ class fulltext_native extends \phpbb\search\base ); } - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'mysql4': case 'mysqli': @@ -978,7 +978,7 @@ class fulltext_native extends \phpbb\search\base // If the cache was completely empty count the results if (!$total_results) { - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'mysql4': case 'mysqli': @@ -1000,7 +1000,7 @@ class fulltext_native extends \phpbb\search\base } else { - if ($this->db->sql_layer == 'sqlite' || $this->db->sql_layer == 'sqlite3') + if ($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') { $sql = 'SELECT COUNT(topic_id) as total_results FROM (SELECT DISTINCT t.topic_id'; @@ -1017,7 +1017,7 @@ class fulltext_native extends \phpbb\search\base $post_visibility $sql_fora AND t.topic_id = p.topic_id - $sql_time" . (($this->db->sql_layer == 'sqlite' || $this->db->sql_layer == 'sqlite3') ? ')' : ''); + $sql_time" . (($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') ? ')' : ''); } $result = $this->db->sql_query($sql); @@ -1481,11 +1481,10 @@ class fulltext_native extends \phpbb\search\base */ public function delete_index($acp_module, $u_action) { - switch ($this->db->sql_layer) + switch ($this->db->get_sql_layer()) { case 'sqlite': case 'sqlite3': - case 'firebird': $this->db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE); $this->db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE); $this->db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE); diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php index bdb5a86009..b3e7f51f87 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/fulltext_postgres.php @@ -31,18 +31,6 @@ class fulltext_postgres extends \phpbb\search\base protected $split_words = array(); /** - * True if PostgreSQL version supports tsearch - * @var boolean - */ - protected $tsearch_usable = false; - - /** - * Stores the PostgreSQL version - * @var string - */ - protected $version; - - /** * Stores the tsearch query * @var string */ @@ -107,16 +95,6 @@ class fulltext_postgres extends \phpbb\search\base $this->word_length = array('min' => $this->config['fulltext_postgres_min_word_len'], 'max' => $this->config['fulltext_postgres_max_word_len']); - if ($this->db->sql_layer == 'postgres') - { - $pgsql_version = explode(',', substr($this->db->sql_server_info(), 10)); - $this->version = trim($pgsql_version[0]); - if (version_compare($this->version, '8.3', '>=')) - { - $this->tsearch_usable = true; - } - } - /** * Load the UTF tools */ @@ -185,16 +163,11 @@ class fulltext_postgres extends \phpbb\search\base */ public function init() { - if ($this->db->sql_layer != 'postgres') + if ($this->db->get_sql_layer() != 'postgres') { return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE']; } - if (!$this->tsearch_usable) - { - return $this->user->lang['FULLTEXT_POSTGRES_TS_NOT_USABLE']; - } - return false; } @@ -869,7 +842,7 @@ class fulltext_postgres extends \phpbb\search\base */ protected function get_stats() { - if ($this->db->sql_layer != 'postgres') + if ($this->db->get_sql_layer() != 'postgres') { $this->stats = array(); return; @@ -913,13 +886,13 @@ class fulltext_postgres extends \phpbb\search\base $tpl = ' <dl> <dt><label>' . $this->user->lang['FULLTEXT_POSTGRES_VERSION_CHECK'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN'] . '</span></dt> - <dd>' . (($this->tsearch_usable) ? $this->user->lang['YES'] : $this->user->lang['NO']) . ' (PostgreSQL ' . $this->version . ')</dd> + <dd>' . (($this->db->get_sql_layer() == 'postgres') ? $this->user->lang['YES'] : $this->user->lang['NO']) . '</dd> </dl> <dl> <dt><label>' . $this->user->lang['FULLTEXT_POSTGRES_TS_NAME'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_TS_NAME_EXPLAIN'] . '</span></dt> <dd><select name="config[fulltext_postgres_ts_name]">'; - if ($this->db->sql_layer == 'postgres' && $this->tsearch_usable) + if ($this->db->get_sql_layer() == 'postgres') { $sql = 'SELECT cfgname AS ts_name FROM pg_ts_config'; diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 9008af338b..78c11f1180 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -199,7 +199,7 @@ class fulltext_sphinx */ public function init() { - if ($this->db->sql_layer != 'mysql' && $this->db->sql_layer != 'mysql4' && $this->db->sql_layer != 'mysqli' && $this->db->sql_layer != 'postgres') + if ($this->db->get_sql_layer() != 'mysql' && $this->db->get_sql_layer() != 'mysql4' && $this->db->get_sql_layer() != 'mysqli' && $this->db->get_sql_layer() != 'postgres') { return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE']; } @@ -218,11 +218,11 @@ class fulltext_sphinx protected function config_generate() { // Check if Database is supported by Sphinx - if ($this->db->sql_layer =='mysql' || $this->db->sql_layer == 'mysql4' || $this->db->sql_layer == 'mysqli') + if ($this->db->get_sql_layer() =='mysql' || $this->db->get_sql_layer() == 'mysql4' || $this->db->get_sql_layer() == 'mysqli') { $this->dbtype = 'mysql'; } - else if ($this->db->sql_layer == 'postgres') + else if ($this->db->get_sql_layer() == 'postgres') { $this->dbtype = 'pgsql'; } diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 0a32879943..4ee48205c8 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -34,6 +34,11 @@ class context */ private $rootref; + /** + * @var bool + */ + private $num_rows_is_set; + public function __construct() { $this->clear(); @@ -46,6 +51,7 @@ class context { $this->tpldata = array('.' => array(0 => array())); $this->rootref = &$this->tpldata['.'][0]; + $this->num_rows_is_set = false; } /** @@ -95,10 +101,59 @@ class context // returning a reference directly is not // something php is capable of doing $ref = &$this->tpldata; + + if (!$this->num_rows_is_set) + { + /* + * We do not set S_NUM_ROWS while adding a row, to reduce the complexity + * If we would set it on adding, each subsequent adding would cause + * n modifications, resulting in a O(n!) complexity, rather then O(n) + */ + foreach ($ref as $loop_name => &$loop_data) + { + if ($loop_name === '.') + { + continue; + } + + $this->set_num_rows($loop_data); + } + $this->num_rows_is_set = true; + } + return $ref; } /** + * Set S_NUM_ROWS for each row in this template block + * + * @param array $loop_data + */ + protected function set_num_rows(&$loop_data) + { + $s_num_rows = sizeof($loop_data); + foreach ($loop_data as &$mod_block) + { + foreach ($mod_block as $sub_block_name => &$sub_block) + { + // If the key name is lowercase and the data is an array, + // it could be a template loop. So we set the S_NUM_ROWS there + // aswell. + if ($sub_block_name === strtolower($sub_block_name) && is_array($sub_block)) + { + $this->set_num_rows($sub_block); + } + } + + // Check whether we are inside a block before setting the variable + if (isset($mod_block['S_BLOCK_NAME'])) + { + $mod_block['S_NUM_ROWS'] = $s_num_rows; + } + } + } + + /** * Returns a reference to template root scope. * * This function is public so that template renderer may invoke it. @@ -123,6 +178,7 @@ class context */ public function assign_block_vars($blockname, array $vararray) { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. @@ -160,13 +216,6 @@ class 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'] = $s_num_rows; - } } else { @@ -192,13 +241,6 @@ class 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'] = $s_num_rows; - } } return true; @@ -250,6 +292,7 @@ class context */ public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. @@ -349,12 +392,6 @@ class context $block[$key] = $vararray; $block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key; - // Set S_NUM_ROWS - foreach ($this->tpldata[$blockname] as &$mod_block) - { - $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); - } - return true; } @@ -382,6 +419,7 @@ class context */ public function destroy_block_vars($blockname) { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php index cceefda7ef..c5dc7273ba 100644 --- a/phpBB/phpbb/template/twig/lexer.php +++ b/phpBB/phpbb/template/twig/lexer.php @@ -285,7 +285,7 @@ class lexer extends \Twig_Lexer return "<!-- {$matches[1]}IF{$inner}-->"; }; - return preg_replace_callback('#<!-- (ELSE)?IF((.*?) \(*!?[\$|\.]([^\s]+)(.*?))-->#', $callback, $code); + return preg_replace_callback('#<!-- (ELSE)?IF((.*?) (?:\(*!?[\$|\.]([^\s]+)(.*?))?)-->#', $callback, $code); } /** diff --git a/phpBB/phpbb/viewonline_helper.php b/phpBB/phpbb/viewonline_helper.php new file mode 100644 index 0000000000..b722f9d911 --- /dev/null +++ b/phpBB/phpbb/viewonline_helper.php @@ -0,0 +1,54 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb; + +/** +* Class to handle viewonline related tasks +*/ +class viewonline_helper +{ + /** @var \phpbb\filesystem */ + protected $filesystem; + + /** + * @param \phpbb\filesystem $filesystem + */ + public function __construct(\phpbb\filesystem $filesystem) + { + $this->filesystem = $filesystem; + } + + /** + * Get user page + * + * @param string $session_page User's session page + * @return array Match array filled by preg_match() + */ + public function get_user_page($session_page) + { + $session_page = $this->filesystem->clean_path($session_page); + if (strpos($session_page, './') === 0) + { + $session_page = substr($session_page, 2); + } + + preg_match('#^((\.\./)*([a-z0-9/_-]+))#i', $session_page, $on_page); + if (empty($on_page)) + { + $on_page[1] = ''; + } + + return $on_page; + } +} |