aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb')
-rw-r--r--phpBB/phpbb/auth/provider/apache.php15
-rw-r--r--phpBB/phpbb/auth/provider/db.php32
-rw-r--r--phpBB/phpbb/auth/provider/ldap.php19
-rw-r--r--phpBB/phpbb/auth/provider/oauth/oauth.php17
-rw-r--r--phpBB/phpbb/auth/provider/oauth/token_storage.php6
-rw-r--r--phpBB/phpbb/avatar/driver/upload.php2
-rw-r--r--phpBB/phpbb/cache/driver/apc.php4
-rw-r--r--phpBB/phpbb/cache/driver/driver_interface.php31
-rw-r--r--phpBB/phpbb/cache/driver/eaccelerator.php10
-rw-r--r--phpBB/phpbb/cache/driver/file.php36
-rw-r--r--phpBB/phpbb/cache/driver/memcache.php8
-rw-r--r--phpBB/phpbb/cache/driver/memory.php36
-rw-r--r--phpBB/phpbb/cache/driver/null.php32
-rw-r--r--phpBB/phpbb/cache/driver/redis.php9
-rw-r--r--phpBB/phpbb/cache/driver/wincache.php4
-rw-r--r--phpBB/phpbb/cache/driver/xcache.php4
-rw-r--r--phpBB/phpbb/cache/service.php6
-rw-r--r--phpBB/phpbb/class_loader.php8
-rw-r--r--phpBB/phpbb/config/db.php6
-rw-r--r--phpBB/phpbb/config/db_text.php6
-rw-r--r--phpBB/phpbb/console/command/config/command.php22
-rw-r--r--phpBB/phpbb/console/command/config/delete.php46
-rw-r--r--phpBB/phpbb/console/command/config/get.php54
-rw-r--r--phpBB/phpbb/console/command/config/increment.php52
-rw-r--r--phpBB/phpbb/console/command/config/set.php52
-rw-r--r--phpBB/phpbb/console/command/config/set_atomic.php65
-rw-r--r--phpBB/phpbb/console/command/fixup/recalculate_email_hash.php4
-rw-r--r--phpBB/phpbb/content_visibility.php86
-rw-r--r--phpBB/phpbb/controller/helper.php44
-rw-r--r--phpBB/phpbb/controller/provider.php56
-rw-r--r--phpBB/phpbb/cron/task/core/prune_all_forums.php4
-rw-r--r--phpBB/phpbb/cron/task/core/prune_forum.php4
-rw-r--r--phpBB/phpbb/cron/task/core/prune_shadow_topics.php191
-rw-r--r--phpBB/phpbb/cron/task/core/tidy_search.php4
-rw-r--r--phpBB/phpbb/db/driver/driver.php137
-rw-r--r--phpBB/phpbb/db/driver/driver_interface.php355
-rw-r--r--phpBB/phpbb/db/driver/firebird.php29
-rw-r--r--phpBB/phpbb/db/driver/mssql.php28
-rw-r--r--phpBB/phpbb/db/driver/mssql_base.php2
-rw-r--r--phpBB/phpbb/db/driver/mssql_odbc.php24
-rw-r--r--phpBB/phpbb/db/driver/mssqlnative.php23
-rw-r--r--phpBB/phpbb/db/driver/mysql.php29
-rw-r--r--phpBB/phpbb/db/driver/mysql_base.php17
-rw-r--r--phpBB/phpbb/db/driver/mysqli.php28
-rw-r--r--phpBB/phpbb/db/driver/oracle.php28
-rw-r--r--phpBB/phpbb/db/driver/postgres.php33
-rw-r--r--phpBB/phpbb/db/driver/sqlite.php31
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php1177
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php7
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_4.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php77
-rw-r--r--phpBB/phpbb/db/migration/data/v310/allow_cdn.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/alpha1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/alpha3.php30
-rw-r--r--phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php40
-rw-r--r--phpBB/phpbb/db/migration/data/v310/avatar_types.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/avatars.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/beta1.php33
-rw-r--r--phpBB/phpbb/db/migration/data/v310/beta2.php29
-rw-r--r--phpBB/phpbb/db/migration/data/v310/board_contact_name.php30
-rw-r--r--phpBB/phpbb/db/migration/data/v310/boardindex.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/config_db_text.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/dev.php3
-rw-r--r--phpBB/phpbb/db/migration/data/v310/extensions.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/forgot_password.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/jquery_update.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/jquery_update2.php33
-rw-r--r--phpBB/phpbb/db/migration/data/v310/migrations_table.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/mod_rewrite.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/namespaces.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/notifications.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/passwords.php46
-rw-r--r--phpBB/phpbb/db/migration/data/v310/passwords_p2.php40
-rw-r--r--phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_aol.php51
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php30
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php51
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php51
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_icq.php50
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_interests.php48
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_location.php48
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php45
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_types.php106
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_website.php52
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php51
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php51
-rw-r--r--phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php46
-rw-r--r--phpBB/phpbb/db/migration/data/v310/reported_posts_display.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php128
-rw-r--r--phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php62
-rw-r--r--phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/softdelete_p1.php11
-rw-r--r--phpBB/phpbb/db/migration/data/v310/softdelete_p2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/style_update_p1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/style_update_p2.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/teampage.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/timezone.php47
-rw-r--r--phpBB/phpbb/db/migration/data/v310/timezone_p2.php2
-rw-r--r--phpBB/phpbb/db/migration/exception.php2
-rw-r--r--phpBB/phpbb/db/migration/helper.php82
-rw-r--r--phpBB/phpbb/db/migration/migration.php8
-rw-r--r--phpBB/phpbb/db/migration/profilefield_base_migration.php155
-rw-r--r--phpBB/phpbb/db/migration/schema_generator.php215
-rw-r--r--phpBB/phpbb/db/migration/tool/config.php2
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php32
-rw-r--r--phpBB/phpbb/db/migration/tool/permission.php10
-rw-r--r--phpBB/phpbb/db/migration/tool/tool_interface.php2
-rw-r--r--phpBB/phpbb/db/migrator.php68
-rw-r--r--phpBB/phpbb/db/sql_insert_buffer.php6
-rw-r--r--phpBB/phpbb/db/tools.php414
-rw-r--r--phpBB/phpbb/event/md_exporter.php439
-rw-r--r--phpBB/phpbb/event/php_exporter.php608
-rw-r--r--phpBB/phpbb/event/recursive_event_filter_iterator.php70
-rw-r--r--phpBB/phpbb/extension/exception.php2
-rw-r--r--phpBB/phpbb/extension/finder.php15
-rw-r--r--phpBB/phpbb/extension/manager.php9
-rw-r--r--phpBB/phpbb/extension/metadata_manager.php4
-rw-r--r--phpBB/phpbb/feed/attachments_base.php83
-rw-r--r--phpBB/phpbb/feed/base.php6
-rw-r--r--phpBB/phpbb/feed/factory.php6
-rw-r--r--phpBB/phpbb/feed/forum.php4
-rw-r--r--phpBB/phpbb/feed/helper.php31
-rw-r--r--phpBB/phpbb/feed/news.php2
-rw-r--r--phpBB/phpbb/feed/overall.php2
-rw-r--r--phpBB/phpbb/feed/post_base.php3
-rw-r--r--phpBB/phpbb/feed/topic.php4
-rw-r--r--phpBB/phpbb/feed/topic_base.php2
-rw-r--r--phpBB/phpbb/feed/topics.php2
-rw-r--r--phpBB/phpbb/feed/topics_active.php2
-rw-r--r--phpBB/phpbb/groupposition/exception.php2
-rw-r--r--phpBB/phpbb/groupposition/legend.php6
-rw-r--r--phpBB/phpbb/groupposition/teampage.php6
-rw-r--r--phpBB/phpbb/json_response.php2
-rw-r--r--phpBB/phpbb/lock/db.php6
-rw-r--r--phpBB/phpbb/log/log.php94
-rw-r--r--phpBB/phpbb/notification/exception.php2
-rw-r--r--phpBB/phpbb/notification/manager.php6
-rw-r--r--phpBB/phpbb/notification/method/base.php6
-rw-r--r--phpBB/phpbb/notification/type/admin_activate_user.php4
-rw-r--r--phpBB/phpbb/notification/type/approve_post.php15
-rw-r--r--phpBB/phpbb/notification/type/approve_topic.php7
-rw-r--r--phpBB/phpbb/notification/type/base.php20
-rw-r--r--phpBB/phpbb/notification/type/bookmark.php14
-rw-r--r--phpBB/phpbb/notification/type/disapprove_post.php7
-rw-r--r--phpBB/phpbb/notification/type/disapprove_topic.php7
-rw-r--r--phpBB/phpbb/notification/type/post.php73
-rw-r--r--phpBB/phpbb/notification/type/post_in_queue.php8
-rw-r--r--phpBB/phpbb/notification/type/quote.php33
-rw-r--r--phpBB/phpbb/notification/type/report_pm_closed.php2
-rw-r--r--phpBB/phpbb/notification/type/report_post.php7
-rw-r--r--phpBB/phpbb/notification/type/report_post_closed.php7
-rw-r--r--phpBB/phpbb/notification/type/topic.php13
-rw-r--r--phpBB/phpbb/notification/type/type_interface.php7
-rw-r--r--phpBB/phpbb/pagination.php217
-rw-r--r--phpBB/phpbb/passwords/driver/base.php45
-rw-r--r--phpBB/phpbb/passwords/driver/bcrypt.php104
-rw-r--r--phpBB/phpbb/passwords/driver/bcrypt_2y.php34
-rw-r--r--phpBB/phpbb/passwords/driver/driver_interface.php60
-rw-r--r--phpBB/phpbb/passwords/driver/helper.php144
-rw-r--r--phpBB/phpbb/passwords/driver/phpass.php26
-rw-r--r--phpBB/phpbb/passwords/driver/salted_md5.php160
-rw-r--r--phpBB/phpbb/passwords/helper.php103
-rw-r--r--phpBB/phpbb/passwords/manager.php341
-rw-r--r--phpBB/phpbb/path_helper.php170
-rw-r--r--phpBB/phpbb/permissions.php3
-rw-r--r--phpBB/phpbb/plupload/plupload.php6
-rw-r--r--phpBB/phpbb/profilefields/lang_helper.php130
-rw-r--r--phpBB/phpbb/profilefields/manager.php437
-rw-r--r--phpBB/phpbb/profilefields/type/type_base.php191
-rw-r--r--phpBB/phpbb/profilefields/type/type_bool.php387
-rw-r--r--phpBB/phpbb/profilefields/type/type_date.php358
-rw-r--r--phpBB/phpbb/profilefields/type/type_dropdown.php297
-rw-r--r--phpBB/phpbb/profilefields/type/type_int.php234
-rw-r--r--phpBB/phpbb/profilefields/type/type_interface.php205
-rw-r--r--phpBB/phpbb/profilefields/type/type_string.php156
-rw-r--r--phpBB/phpbb/profilefields/type/type_string_common.php128
-rw-r--r--phpBB/phpbb/profilefields/type/type_text.php201
-rw-r--r--phpBB/phpbb/profilefields/type/type_url.php70
-rw-r--r--phpBB/phpbb/recursive_dot_prefix_filter_iterator.php28
-rw-r--r--phpBB/phpbb/request/deactivated_super_global.php1
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php4
-rw-r--r--phpBB/phpbb/search/fulltext_native.php43
-rw-r--r--phpBB/phpbb/search/fulltext_postgres.php28
-rw-r--r--phpBB/phpbb/search/fulltext_sphinx.php8
-rw-r--r--phpBB/phpbb/template/base.php10
-rw-r--r--phpBB/phpbb/template/context.php22
-rw-r--r--phpBB/phpbb/template/template.php8
-rw-r--r--phpBB/phpbb/template/twig/environment.php15
-rw-r--r--phpBB/phpbb/template/twig/twig.php2
-rw-r--r--phpBB/phpbb/tree/nestedset.php32
-rw-r--r--phpBB/phpbb/tree/nestedset_forum.php4
-rw-r--r--phpBB/phpbb/user.php33
-rw-r--r--phpBB/phpbb/user_loader.php6
-rw-r--r--phpBB/phpbb/version_helper.php271
241 files changed, 11122 insertions, 1044 deletions
diff --git a/phpBB/phpbb/auth/provider/apache.php b/phpBB/phpbb/auth/provider/apache.php
index 77bc976938..6374f29d67 100644
--- a/phpBB/phpbb/auth/provider/apache.php
+++ b/phpBB/phpbb/auth/provider/apache.php
@@ -17,19 +17,28 @@ namespace phpbb\auth\provider;
class apache extends \phpbb\auth\provider\base
{
/**
+ * phpBB passwords manager
+ *
+ * @var \phpbb\passwords\manager
+ */
+ protected $passwords_manager;
+
+ /**
* Apache Authentication Constructor
*
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\config\config $config
+ * @param \phpbb\passwords\manager $passwords_manager
* @param \phpbb\request\request $request
* @param \phpbb\user $user
* @param string $phpbb_root_path
* @param string $php_ext
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
+ $this->passwords_manager = $passwords_manager;
$this->request = $request;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
@@ -220,7 +229,7 @@ class apache extends \phpbb\auth\provider\base
// generate user account data
return array(
'username' => $username,
- 'user_password' => phpbb_hash($password),
+ 'user_password' => $this->passwords_manager->hash($password),
'user_email' => '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php
index 6ea04eab36..5adbf84d9f 100644
--- a/phpBB/phpbb/auth/provider/db.php
+++ b/phpBB/phpbb/auth/provider/db.php
@@ -18,21 +18,29 @@ namespace phpbb\auth\provider;
*/
class db extends \phpbb\auth\provider\base
{
+ /**
+ * phpBB passwords manager
+ *
+ * @var \phpbb\passwords\manager
+ */
+ protected $passwords_manager;
/**
* Database Authentication Constructor
*
- * @param \phpbb\db\driver\driver $db
- * @param \phpbb\config\config $config
- * @param \phpbb\request\request $request
- * @param \phpbb\user $user
- * @param string $phpbb_root_path
- * @param string $php_ext
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\config\config $config
+ * @param \phpbb\passwords\manager $passwords_manager
+ * @param \phpbb\request\request $request
+ * @param \phpbb\user $user
+ * @param string $phpbb_root_path
+ * @param string $php_ext
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
+ $this->passwords_manager = $passwords_manager;
$this->request = $request;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
@@ -191,10 +199,10 @@ class db extends \phpbb\auth\provider\base
// cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
// plain md5 support left in for conversions from other systems.
- if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
+ if ((strlen($row['user_password']) == 34 && ($this->passwords_manager->check(md5($password_old_format), $row['user_password']) || $this->passwords_manager->check(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
|| (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
{
- $hash = phpbb_hash($password_new_format);
+ $hash = $this->passwords_manager->hash($password_new_format);
// Update the password in the users table to the new format and remove user_pass_convert flag
$sql = 'UPDATE ' . USERS_TABLE . '
@@ -226,12 +234,12 @@ class db extends \phpbb\auth\provider\base
}
// Check password ...
- if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password']))
+ if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password']))
{
// Check for old password hash...
- if (strlen($row['user_password']) == 32)
+ if ($this->passwords_manager->convert_flag || strlen($row['user_password']) == 32)
{
- $hash = phpbb_hash($password);
+ $hash = $this->passwords_manager->hash($password);
// Update the password in the users table to the new format
$sql = 'UPDATE ' . USERS_TABLE . "
diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php
index 4ce43853bd..3d3f1990eb 100644
--- a/phpBB/phpbb/auth/provider/ldap.php
+++ b/phpBB/phpbb/auth/provider/ldap.php
@@ -19,16 +19,25 @@ namespace phpbb\auth\provider;
class ldap extends \phpbb\auth\provider\base
{
/**
+ * phpBB passwords manager
+ *
+ * @var \phpbb\passwords\manager
+ */
+ protected $passwords_manager;
+
+ /**
* LDAP Authentication Constructor
*
- * @param \phpbb\db\driver\driver $db
- * @param \phpbb\config\config $config
- * @param \phpbb\user $user
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\config\config $config
+ * @param \phpbb\passwords\manager $passwords_manager
+ * @param \phpbb\user $user
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\user $user)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\user $user)
{
$this->db = $db;
$this->config = $config;
+ $this->passwords_manager = $passwords_manager;
$this->user = $user;
}
@@ -235,7 +244,7 @@ class ldap extends \phpbb\auth\provider\base
// generate user account data
$ldap_user_row = array(
'username' => $username,
- 'user_password' => phpbb_hash($password),
+ 'user_password' => $this->passwords_manager->hash($password),
'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php
index 2749661269..10d5cda5e3 100644
--- a/phpBB/phpbb/auth/provider/oauth/oauth.php
+++ b/phpBB/phpbb/auth/provider/oauth/oauth.php
@@ -22,7 +22,7 @@ class oauth extends \phpbb\auth\provider\base
/**
* Database driver
*
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -34,6 +34,13 @@ class oauth extends \phpbb\auth\provider\base
protected $config;
/**
+ * phpBB passwords manager
+ *
+ * @var \phpbb\passwords\manager
+ */
+ protected $passwords_manager;
+
+ /**
* phpBB request object
*
* @var \phpbb\request\request_interface
@@ -99,8 +106,9 @@ class oauth extends \phpbb\auth\provider\base
/**
* OAuth Authentication Constructor
*
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\config\config $config
+ * @param \phpbb\passwords\manager $passwords_manager
* @param \phpbb\request\request_interface $request
* @param \phpbb\user $user
* @param string $auth_provider_oauth_token_storage_table
@@ -110,10 +118,11 @@ class oauth extends \phpbb\auth\provider\base
* @param string $phpbb_root_path
* @param string $php_ext
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
+ $this->passwords_manager = $passwords_manager;
$this->request = $request;
$this->user = $user;
$this->auth_provider_oauth_token_storage_table = $auth_provider_oauth_token_storage_table;
@@ -150,7 +159,7 @@ class oauth extends \phpbb\auth\provider\base
// Temporary workaround for only having one authentication provider available
if (!$this->request->is_set('oauth_service'))
{
- $provider = new \phpbb\auth\provider\db($this->db, $this->config, $this->request, $this->user, $this->phpbb_root_path, $this->php_ext);
+ $provider = new \phpbb\auth\provider\db($this->db, $this->config, $this->passwords_manager, $this->request, $this->user, $this->phpbb_root_path, $this->php_ext);
return $provider->login($username, $password);
}
diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php
index 43574288dc..d32a03be0a 100644
--- a/phpBB/phpbb/auth/provider/oauth/token_storage.php
+++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php
@@ -26,7 +26,7 @@ class token_storage implements TokenStorageInterface
/**
* Cache driver.
*
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -52,11 +52,11 @@ class token_storage implements TokenStorageInterface
/**
* Creates token storage for phpBB.
*
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\user $user
* @param string $auth_provider_oauth_table
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\user $user, $auth_provider_oauth_table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $auth_provider_oauth_table)
{
$this->db = $db;
$this->user = $user;
diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php
index 1e50e135e4..f77ef1332b 100644
--- a/phpBB/phpbb/avatar/driver/upload.php
+++ b/phpBB/phpbb/avatar/driver/upload.php
@@ -147,7 +147,7 @@ class upload extends \phpbb\avatar\driver\driver
return array(
'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'number:0', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
- 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true),
+ 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true),
);
}
diff --git a/phpBB/phpbb/cache/driver/apc.php b/phpBB/phpbb/cache/driver/apc.php
index a28d91c00a..77b7b11181 100644
--- a/phpBB/phpbb/cache/driver/apc.php
+++ b/phpBB/phpbb/cache/driver/apc.php
@@ -18,9 +18,7 @@ class apc extends \phpbb\cache\driver\memory
var $extension = 'apc';
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
diff --git a/phpBB/phpbb/cache/driver/driver_interface.php b/phpBB/phpbb/cache/driver/driver_interface.php
index 0715a4b934..8929647411 100644
--- a/phpBB/phpbb/cache/driver/driver_interface.php
+++ b/phpBB/phpbb/cache/driver/driver_interface.php
@@ -18,46 +18,73 @@ interface driver_interface
{
/**
* Load global cache
+ *
+ * @return mixed False if an error was encountered, otherwise the data type of the cached data
*/
public function load();
/**
* Unload cache object
+ *
+ * @return null
*/
public function unload();
/**
* Save modified objects
+ *
+ * @return null
*/
public function save();
/**
* Tidy cache
+ *
+ * @return null
*/
public function tidy();
/**
* Get saved cache object
+ *
+ * @param string $var_name Cache key
+ * @return mixed False if an error was encountered, otherwise the saved cached object
*/
public function get($var_name);
/**
* Put data into cache
+ *
+ * @param string $var_name Cache key
+ * @param mixed $var Cached data to store
+ * @param int $ttl Time-to-live of cached data
+ * @return null
*/
public function put($var_name, $var, $ttl = 0);
/**
* Purge cache data
+ *
+ * @return null
*/
public function purge();
/**
* Destroy cache data
+ *
+ * @param string $var_name Cache key
+ * @param string $table Table name
+ * @return null
*/
public function destroy($var_name, $table = '');
/**
* Check if a given cache entry exists
+ *
+ * @param string $var_name Cache key
+ *
+ * @return bool True if cache file exists and has not expired.
+ * False otherwise.
*/
public function _exists($var_name);
@@ -79,7 +106,7 @@ interface driver_interface
* result to persistent storage. In other words, there is no need
* to call save() afterwards.
*
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param string $query SQL query, should be used for generating storage key
* @param mixed $query_result The result from \dbal::sql_query, to be passed to
* \dbal::sql_fetchrow to get all rows and store them
@@ -90,7 +117,7 @@ interface driver_interface
* representing the query should be returned. Otherwise
* the original $query_result should be returned.
*/
- public function sql_save(\phpbb\db\driver\driver $db, $query, $query_result, $ttl);
+ public function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl);
/**
* Check if result for a given SQL query exists in cache.
diff --git a/phpBB/phpbb/cache/driver/eaccelerator.php b/phpBB/phpbb/cache/driver/eaccelerator.php
index 2629cb53e5..d1ad69ef6d 100644
--- a/phpBB/phpbb/cache/driver/eaccelerator.php
+++ b/phpBB/phpbb/cache/driver/eaccelerator.php
@@ -22,9 +22,7 @@ class eaccelerator extends \phpbb\cache\driver\memory
var $serialize_header = '#phpbb-serialized#';
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
@@ -39,10 +37,8 @@ class eaccelerator extends \phpbb\cache\driver\memory
}
/**
- * Perform cache garbage collection
- *
- * @return null
- */
+ * {@inheritDoc}
+ */
function tidy()
{
eaccelerator_gc();
diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php
index 6686da6953..286ba328c3 100644
--- a/phpBB/phpbb/cache/driver/file.php
+++ b/phpBB/phpbb/cache/driver/file.php
@@ -33,7 +33,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Load global cache
+ * {@inheritDoc}
*/
function load()
{
@@ -41,7 +41,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Unload cache object
+ * {@inheritDoc}
*/
function unload()
{
@@ -58,7 +58,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Save modified objects
+ * {@inheritDoc}
*/
function save()
{
@@ -93,7 +93,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Tidy cache
+ * {@inheritDoc}
*/
function tidy()
{
@@ -155,7 +155,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Get saved cache object
+ * {@inheritDoc}
*/
function get($var_name)
{
@@ -177,7 +177,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Put data into cache
+ * {@inheritDoc}
*/
function put($var_name, $var, $ttl = 31536000)
{
@@ -194,7 +194,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Purge cache data
+ * {@inheritDoc}
*/
function purge()
{
@@ -280,7 +280,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Destroy cache data
+ * {@inheritDoc}
*/
function destroy($var_name, $table = '')
{
@@ -359,7 +359,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Check if a given cache entry exist
+ * {@inheritDoc}
*/
function _exists($var_name)
{
@@ -385,7 +385,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Load cached sql query
+ * {@inheritDoc}
*/
function sql_load($query)
{
@@ -407,7 +407,7 @@ class file extends \phpbb\cache\driver\base
/**
* {@inheritDoc}
*/
- function sql_save(\phpbb\db\driver\driver $db, $query, $query_result, $ttl)
+ function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
{
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
@@ -431,7 +431,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Ceck if a given sql query exist in cache
+ * {@inheritDoc}
*/
function sql_exists($query_id)
{
@@ -439,7 +439,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Fetch row from cache (database)
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id)
{
@@ -452,7 +452,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Fetch a field from the current row of a cached database result (database)
+ * {@inheritDoc}
*/
function sql_fetchfield($query_id, $field)
{
@@ -465,7 +465,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Seek a specific row in an a cached database result (database)
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, $query_id)
{
@@ -479,7 +479,7 @@ class file extends \phpbb\cache\driver\base
}
/**
- * Free memory used for a cached database result (database)
+ * {@inheritDoc}
*/
function sql_freeresult($query_id)
{
@@ -758,6 +758,10 @@ class file extends \phpbb\cache\driver\base
/**
* Removes/unlinks file
+ *
+ * @param string $filename Filename to remove
+ * @param bool $check Check file permissions
+ * @return bool True if the file was successfully removed, otherwise false
*/
function remove_file($filename, $check = false)
{
diff --git a/phpBB/phpbb/cache/driver/memcache.php b/phpBB/phpbb/cache/driver/memcache.php
index c725ec0fb0..eb3fced973 100644
--- a/phpBB/phpbb/cache/driver/memcache.php
+++ b/phpBB/phpbb/cache/driver/memcache.php
@@ -56,9 +56,7 @@ class memcache extends \phpbb\cache\driver\memory
}
/**
- * Unload the cache resources
- *
- * @return null
+ * {@inheritDoc}
*/
function unload()
{
@@ -68,9 +66,7 @@ class memcache extends \phpbb\cache\driver\memory
}
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php
index 292024212b..d5404455d1 100644
--- a/phpBB/phpbb/cache/driver/memory.php
+++ b/phpBB/phpbb/cache/driver/memory.php
@@ -50,7 +50,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Load global cache
+ * {@inheritDoc}
*/
function load()
{
@@ -66,7 +66,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Unload cache object
+ * {@inheritDoc}
*/
function unload()
{
@@ -81,7 +81,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Save modified objects
+ * {@inheritDoc}
*/
function save()
{
@@ -96,7 +96,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Tidy cache
+ * {@inheritDoc}
*/
function tidy()
{
@@ -106,7 +106,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Get saved cache object
+ * {@inheritDoc}
*/
function get($var_name)
{
@@ -126,7 +126,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Put data into cache
+ * {@inheritDoc}
*/
function put($var_name, $var, $ttl = 2592000)
{
@@ -142,7 +142,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Purge cache data
+ * {@inheritDoc}
*/
function purge()
{
@@ -183,7 +183,7 @@ abstract class memory extends \phpbb\cache\driver\base
/**
- * Destroy cache data
+ * {@inheritDoc}
*/
function destroy($var_name, $table = '')
{
@@ -237,7 +237,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Check if a given cache entry exist
+ * {@inheritDoc}
*/
function _exists($var_name)
{
@@ -257,7 +257,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Load cached sql query
+ * {@inheritDoc}
*/
function sql_load($query)
{
@@ -279,7 +279,7 @@ abstract class memory extends \phpbb\cache\driver\base
/**
* {@inheritDoc}
*/
- function sql_save(\phpbb\db\driver\driver $db, $query, $query_result, $ttl)
+ function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
{
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
@@ -335,7 +335,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Ceck if a given sql query exist in cache
+ * {@inheritDoc}
*/
function sql_exists($query_id)
{
@@ -343,7 +343,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Fetch row from cache (database)
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id)
{
@@ -356,7 +356,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Fetch a field from the current row of a cached database result (database)
+ * {@inheritDoc}
*/
function sql_fetchfield($query_id, $field)
{
@@ -369,7 +369,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Seek a specific row in an a cached database result (database)
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, $query_id)
{
@@ -383,7 +383,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
/**
- * Free memory used for a cached database result (database)
+ * {@inheritDoc}
*/
function sql_freeresult($query_id)
{
@@ -400,6 +400,10 @@ abstract class memory extends \phpbb\cache\driver\base
/**
* Removes/unlinks file
+ *
+ * @param string $filename Filename to remove
+ * @param bool $check Check file permissions
+ * @return bool True if the file was successfully removed, otherwise false
*/
function remove_file($filename, $check = false)
{
diff --git a/phpBB/phpbb/cache/driver/null.php b/phpBB/phpbb/cache/driver/null.php
index ea535ca1e1..99cfe454e0 100644
--- a/phpBB/phpbb/cache/driver/null.php
+++ b/phpBB/phpbb/cache/driver/null.php
@@ -23,7 +23,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Load global cache
+ * {@inheritDoc}
*/
function load()
{
@@ -31,21 +31,21 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Unload cache object
+ * {@inheritDoc}
*/
function unload()
{
}
/**
- * Save modified objects
+ * {@inheritDoc}
*/
function save()
{
}
/**
- * Tidy cache
+ * {@inheritDoc}
*/
function tidy()
{
@@ -54,7 +54,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Get saved cache object
+ * {@inheritDoc}
*/
function get($var_name)
{
@@ -62,28 +62,28 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Put data into cache
+ * {@inheritDoc}
*/
function put($var_name, $var, $ttl = 0)
{
}
/**
- * Purge cache data
+ * {@inheritDoc}
*/
function purge()
{
}
/**
- * Destroy cache data
+ * {@inheritDoc}
*/
function destroy($var_name, $table = '')
{
}
/**
- * Check if a given cache entry exist
+ * {@inheritDoc}
*/
function _exists($var_name)
{
@@ -91,7 +91,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Load cached sql query
+ * {@inheritDoc}
*/
function sql_load($query)
{
@@ -101,13 +101,13 @@ class null extends \phpbb\cache\driver\base
/**
* {@inheritDoc}
*/
- function sql_save(\phpbb\db\driver\driver $db, $query, $query_result, $ttl)
+ function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
{
return $query_result;
}
/**
- * Ceck if a given sql query exist in cache
+ * {@inheritDoc}
*/
function sql_exists($query_id)
{
@@ -115,7 +115,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Fetch row from cache (database)
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id)
{
@@ -123,7 +123,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Fetch a field from the current row of a cached database result (database)
+ * {@inheritDoc}
*/
function sql_fetchfield($query_id, $field)
{
@@ -131,7 +131,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Seek a specific row in an a cached database result (database)
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, $query_id)
{
@@ -139,7 +139,7 @@ class null extends \phpbb\cache\driver\base
}
/**
- * Free memory used for a cached database result (database)
+ * {@inheritDoc}
*/
function sql_freeresult($query_id)
{
diff --git a/phpBB/phpbb/cache/driver/redis.php b/phpBB/phpbb/cache/driver/redis.php
index 3c6cb0e138..2f2a32a12d 100644
--- a/phpBB/phpbb/cache/driver/redis.php
+++ b/phpBB/phpbb/cache/driver/redis.php
@@ -92,9 +92,7 @@ class redis extends \phpbb\cache\driver\memory
}
/**
- * Unload the cache resources
- *
- * @return null
+ * {@inheritDoc}
*/
function unload()
{
@@ -104,9 +102,7 @@ class redis extends \phpbb\cache\driver\memory
}
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
@@ -157,4 +153,3 @@ class redis extends \phpbb\cache\driver\memory
return false;
}
}
-
diff --git a/phpBB/phpbb/cache/driver/wincache.php b/phpBB/phpbb/cache/driver/wincache.php
index 1f040e9ab2..d0f636d9cb 100644
--- a/phpBB/phpbb/cache/driver/wincache.php
+++ b/phpBB/phpbb/cache/driver/wincache.php
@@ -18,9 +18,7 @@ class wincache extends \phpbb\cache\driver\memory
var $extension = 'wincache';
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
diff --git a/phpBB/phpbb/cache/driver/xcache.php b/phpBB/phpbb/cache/driver/xcache.php
index 4d0d683b3d..6c9323ec83 100644
--- a/phpBB/phpbb/cache/driver/xcache.php
+++ b/phpBB/phpbb/cache/driver/xcache.php
@@ -33,9 +33,7 @@ class xcache extends \phpbb\cache\driver\memory
}
/**
- * Purge cache data
- *
- * @return null
+ * {@inheritDoc}
*/
function purge()
{
diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php
index ebbcfb8cdb..f9b6324b05 100644
--- a/phpBB/phpbb/cache/service.php
+++ b/phpBB/phpbb/cache/service.php
@@ -32,7 +32,7 @@ class service
/**
* Database connection.
*
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -55,11 +55,11 @@ class service
*
* @param \phpbb\cache\driver\driver_interface $driver The cache driver
* @param \phpbb\config\config $config The config
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP extension
*/
- public function __construct(\phpbb\cache\driver\driver_interface $driver, \phpbb\config\config $config, \phpbb\db\driver\driver $db, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\cache\driver\driver_interface $driver, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext)
{
$this->set_driver($driver);
$this->config = $config;
diff --git a/phpBB/phpbb/class_loader.php b/phpBB/phpbb/class_loader.php
index 37b62fff24..ee9767148b 100644
--- a/phpBB/phpbb/class_loader.php
+++ b/phpBB/phpbb/class_loader.php
@@ -142,7 +142,13 @@ class class_loader
*/
public function load_class($class)
{
- $class = '\\' . $class;
+ // In general $class is not supposed to contain a leading backslash,
+ // but sometimes it does. See tickets PHP-50731 and HHVM-1840.
+ if ($class[0] !== '\\')
+ {
+ $class = '\\' . $class;
+ }
+
if (substr($class, 0, strlen($this->namespace)) === $this->namespace)
{
$path = $this->resolve_path($class);
diff --git a/phpBB/phpbb/config/db.php b/phpBB/phpbb/config/db.php
index c1a3630a14..ea84a9f873 100644
--- a/phpBB/phpbb/config/db.php
+++ b/phpBB/phpbb/config/db.php
@@ -23,7 +23,7 @@ class db extends \phpbb\config\config
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -36,11 +36,11 @@ class db extends \phpbb\config\config
/**
* Creates a configuration container with a default set of values
*
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param \phpbb\cache\driver\driver_interface $cache Cache instance
* @param string $table Configuration table name
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\cache\driver\driver_interface $cache, $table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $table)
{
$this->db = $db;
$this->cache = $cache;
diff --git a/phpBB/phpbb/config/db_text.php b/phpBB/phpbb/config/db_text.php
index b1ea112b53..250a2ec7de 100644
--- a/phpBB/phpbb/config/db_text.php
+++ b/phpBB/phpbb/config/db_text.php
@@ -20,7 +20,7 @@ class db_text
{
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -31,10 +31,10 @@ class db_text
protected $table;
/**
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param string $table Table name
*/
- public function __construct(\phpbb\db\driver\driver $db, $table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, $table)
{
$this->db = $db;
$this->table = $this->db->sql_escape($table);
diff --git a/phpBB/phpbb/console/command/config/command.php b/phpBB/phpbb/console/command/config/command.php
new file mode 100644
index 0000000000..b105bc826d
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/command.php
@@ -0,0 +1,22 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+abstract class command extends \phpbb\console\command\command
+{
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ function __construct(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+
+ parent::__construct();
+ }
+}
diff --git a/phpBB/phpbb/console/command/config/delete.php b/phpBB/phpbb/console/command/config/delete.php
new file mode 100644
index 0000000000..9a2d00561d
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/delete.php
@@ -0,0 +1,46 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class delete extends command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('config:delete')
+ ->setDescription('Deletes a configuration option')
+ ->addArgument(
+ 'key',
+ InputArgument::REQUIRED,
+ "The configuration option's name"
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $key = $input->getArgument('key');
+
+ if (isset($this->config[$key]))
+ {
+ $this->config->delete($key);
+
+ $output->writeln("<info>Successfully deleted config $key</info>");
+ }
+ else
+ {
+ $output->writeln("<error>Config $key does not exist</error>");
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/config/get.php b/phpBB/phpbb/console/command/config/get.php
new file mode 100644
index 0000000000..275c82b53f
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/get.php
@@ -0,0 +1,54 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class get extends command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('config:get')
+ ->setDescription("Gets a configuration option's value")
+ ->addArgument(
+ 'key',
+ InputArgument::REQUIRED,
+ "The configuration option's name"
+ )
+ ->addOption(
+ 'no-newline',
+ null,
+ InputOption::VALUE_NONE,
+ 'Set this option if the value should be printed without a new line at the end.'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $key = $input->getArgument('key');
+
+ if (isset($this->config[$key]) && $input->getOption('no-newline'))
+ {
+ $output->write($this->config[$key]);
+ }
+ elseif (isset($this->config[$key]))
+ {
+ $output->writeln($this->config[$key]);
+ }
+ else
+ {
+ $output->writeln("<error>Could not get config $key</error>");
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/config/increment.php b/phpBB/phpbb/console/command/config/increment.php
new file mode 100644
index 0000000000..bc6b63c6ff
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/increment.php
@@ -0,0 +1,52 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class increment extends command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('config:increment')
+ ->setDescription("Increments a configuration option's value")
+ ->addArgument(
+ 'key',
+ InputArgument::REQUIRED,
+ "The configuration option's name"
+ )
+ ->addArgument(
+ 'increment',
+ InputArgument::REQUIRED,
+ 'Amount to increment by'
+ )
+ ->addOption(
+ 'dynamic',
+ 'd',
+ InputOption::VALUE_NONE,
+ 'Set this option if the configuration option changes too frequently to be efficiently cached.'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $key = $input->getArgument('key');
+ $increment = $input->getArgument('increment');
+ $use_cache = !$input->getOption('dynamic');
+
+ $this->config->increment($key, $increment, $use_cache);
+
+ $output->writeln("<info>Successfully incremented config $key</info>");
+ }
+}
diff --git a/phpBB/phpbb/console/command/config/set.php b/phpBB/phpbb/console/command/config/set.php
new file mode 100644
index 0000000000..9d471a96ad
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/set.php
@@ -0,0 +1,52 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class set extends command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('config:set')
+ ->setDescription("Sets a configuration option's value")
+ ->addArgument(
+ 'key',
+ InputArgument::REQUIRED,
+ "The configuration option's name"
+ )
+ ->addArgument(
+ 'value',
+ InputArgument::REQUIRED,
+ 'New configuration value, use 0 and 1 to specify boolean values'
+ )
+ ->addOption(
+ 'dynamic',
+ 'd',
+ InputOption::VALUE_NONE,
+ 'Set this option if the configuration option changes too frequently to be efficiently cached.'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $key = $input->getArgument('key');
+ $value = $input->getArgument('value');
+ $use_cache = !$input->getOption('dynamic');
+
+ $this->config->set($key, $value, $use_cache);
+
+ $output->writeln("<info>Successfully set config $key</info>");
+ }
+}
diff --git a/phpBB/phpbb/console/command/config/set_atomic.php b/phpBB/phpbb/console/command/config/set_atomic.php
new file mode 100644
index 0000000000..03e7a60210
--- /dev/null
+++ b/phpBB/phpbb/console/command/config/set_atomic.php
@@ -0,0 +1,65 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+namespace phpbb\console\command\config;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class set_atomic extends command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('config:set-atomic')
+ ->setDescription("Sets a configuration option's value only if the old matches the current value.")
+ ->addArgument(
+ 'key',
+ InputArgument::REQUIRED,
+ "The configuration option's name"
+ )
+ ->addArgument(
+ 'old',
+ InputArgument::REQUIRED,
+ 'Current configuration value, use 0 and 1 to specify boolean values'
+ )
+ ->addArgument(
+ 'new',
+ InputArgument::REQUIRED,
+ 'New configuration value, use 0 and 1 to specify boolean values'
+ )
+ ->addOption(
+ 'dynamic',
+ 'd',
+ InputOption::VALUE_NONE,
+ 'Set this option if the configuration option changes too frequently to be efficiently cached.'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $key = $input->getArgument('key');
+ $old_value = $input->getArgument('old');
+ $new_value = $input->getArgument('new');
+ $use_cache = !$input->getOption('dynamic');
+
+ if ($this->config->set_atomic($key, $old_value, $new_value, $use_cache))
+ {
+ $output->writeln("<info>Successfully set config $key</info>");
+ return 0;
+ }
+ else
+ {
+ $output->writeln("<error>Could not set config $key</error>");
+ return 1;
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php
index 04db880091..8c520673d9 100644
--- a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php
+++ b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php
@@ -13,10 +13,10 @@ use Symfony\Component\Console\Output\OutputInterface;
class recalculate_email_hash extends \phpbb\console\command\command
{
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
- function __construct(\phpbb\db\driver\driver $db)
+ function __construct(\phpbb\db\driver\driver_interface $db)
{
$this->db = $db;
diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php
index 874889015a..881a8f2c54 100644
--- a/phpBB/phpbb/content_visibility.php
+++ b/phpBB/phpbb/content_visibility.php
@@ -18,7 +18,7 @@ class content_visibility
{
/**
* Database object
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -50,13 +50,13 @@ class content_visibility
* Constructor
*
* @param \phpbb\auth\auth $auth Auth object
- * @param \phpbb\db\driver\driver $db Database object
+ * @param \phpbb\db\driver\driver_interface $db Database object
* @param \phpbb\user $user User object
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP Extension
* @return null
*/
- public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
+ public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
{
$this->auth = $auth;
$this->db = $db;
@@ -215,23 +215,23 @@ class content_visibility
/**
* Change visibility status of one post or all posts of a topic
*
- * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED}
+ * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
* @param $post_id mixed Post ID or array of post IDs to act on,
* if it is empty, all posts of topic_id will be modified
* @param $topic_id int Topic where $post_id is found
* @param $forum_id int Forum where $topic_id is found
* @param $user_id int User performing the action
* @param $time int Timestamp when the action is performed
- * @param $reason string Reason why the visibilty was changed.
+ * @param $reason string Reason why the visibility was changed.
* @param $is_starter bool Is this the first post of the topic changed?
* @param $is_latest bool Is this the last post of the topic changed?
* @param $limit_visibility mixed Limit updating per topic_id to a certain visibility
* @param $limit_delete_time mixed Limit updating per topic_id to a certain deletion time
- * @return array Changed post data, empty array if an error occured.
+ * @return array Changed post data, empty array if an error occurred.
*/
public function set_post_visibility($visibility, $post_id, $topic_id, $forum_id, $user_id, $time, $reason, $is_starter, $is_latest, $limit_visibility = false, $limit_delete_time = false)
{
- if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED)))
+ if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
{
return array();
}
@@ -326,7 +326,7 @@ class content_visibility
// Update users postcounts
foreach ($postcounts as $num_posts => $poster_ids)
{
- if ($visibility == ITEM_DELETED)
+ if (in_array($visibility, array(ITEM_REAPPROVE, ITEM_DELETED)))
{
$sql = 'UPDATE ' . $this->users_table . '
SET user_posts = 0
@@ -387,54 +387,36 @@ class content_visibility
// Update the topic's reply count and the forum's post count
if ($update_topic_postcount)
{
- $cur_posts = $cur_unapproved_posts = $cur_softdeleted_posts = 0;
+ $field_alias = array(
+ ITEM_APPROVED => 'posts_approved',
+ ITEM_UNAPPROVED => 'posts_unapproved',
+ ITEM_DELETED => 'posts_softdeleted',
+ ITEM_REAPPROVE => 'posts_unapproved',
+ );
+ $cur_posts = array_fill_keys($field_alias, 0);
+
foreach ($postcount_visibility as $post_visibility => $visibility_posts)
{
- // We need to substract the posts from the counters ...
- if ($post_visibility == ITEM_APPROVED)
- {
- $cur_posts += $visibility_posts;
- }
- else if ($post_visibility == ITEM_UNAPPROVED)
- {
- $cur_unapproved_posts += $visibility_posts;
- }
- else if ($post_visibility == ITEM_DELETED)
- {
- $cur_softdeleted_posts += $visibility_posts;
- }
+ $cur_posts[$field_alias[(int) $post_visibility]] += $visibility_posts;
}
$sql_ary = array();
- if ($visibility == ITEM_DELETED)
+ $recipient_field = $field_alias[$visibility];
+
+ foreach ($cur_posts as $field => $count)
{
- if ($cur_posts)
- {
- $sql_ary['posts_approved'] = ' - ' . $cur_posts;
- }
- if ($cur_unapproved_posts)
+ // Decrease the count for the old statuses.
+ if ($count && $field != $recipient_field)
{
- $sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts;
- }
- if ($cur_posts + $cur_unapproved_posts)
- {
- $sql_ary['posts_softdeleted'] = ' + ' . ($cur_posts + $cur_unapproved_posts);
+ $sql_ary[$field] = " - $count";
}
}
- else
+ // Add up the count from all statuses excluding the recipient status.
+ $count_increase = array_sum(array_diff($cur_posts, array($recipient_field)));
+
+ if ($count_increase)
{
- if ($cur_unapproved_posts)
- {
- $sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts;
- }
- if ($cur_softdeleted_posts)
- {
- $sql_ary['posts_softdeleted'] = ' - ' . $cur_softdeleted_posts;
- }
- if ($cur_softdeleted_posts + $cur_unapproved_posts)
- {
- $sql_ary['posts_approved'] = ' + ' . ($cur_softdeleted_posts + $cur_unapproved_posts);
- }
+ $sql_ary[$recipient_field] = " + $count_increase";
}
if (sizeof($sql_ary))
@@ -475,7 +457,7 @@ class content_visibility
* as soft deleted.
* If you want to update all posts, use the force option.
*
- * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED}
+ * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
* @param $topic_id mixed Topic ID to act on
* @param $forum_id int Forum where $topic_id is found
* @param $user_id int User performing the action
@@ -486,7 +468,7 @@ class content_visibility
*/
public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false)
{
- if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED)))
+ if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
{
return array();
}
@@ -528,16 +510,16 @@ class content_visibility
if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED)
{
// If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion.
- self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']);
+ $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']);
}
else if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED)
{
- // If we're soft deleting a topic we only approved posts are soft deleted.
- self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']);
+ // If we're soft deleting a topic we only mark approved posts as soft deleted.
+ $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']);
}
else
{
- self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
+ $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
}
return $data;
diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php
index 05a05d1e57..54c30c93fc 100644
--- a/phpBB/phpbb/controller/helper.php
+++ b/phpBB/phpbb/controller/helper.php
@@ -10,6 +10,8 @@
namespace phpbb\controller;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Generator\UrlGenerator;
+use Symfony\Component\Routing\RequestContext;
/**
* Controller helper class, contains methods that do things for controllers
@@ -51,18 +53,20 @@ class helper
* Constructor
*
* @param \phpbb\template\template $template Template object
- * @param \phpbb\user $user User object
- * @param \phpbb\config\config $config Config object
+ * @param \phpbb\user $user User object
+ * @param \phpbb\config\config $config Config object
+ * @param \phpbb\controller\provider $provider Path provider
* @param string $phpbb_root_path phpBB root path
* @param string $php_ext PHP extension
*/
- public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, $phpbb_root_path, $php_ext)
{
$this->template = $template;
$this->user = $user;
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
+ $this->route_collection = $provider->get_routes();
}
/**
@@ -73,9 +77,9 @@ class helper
* @param int $status_code The status code to be sent to the page header
* @return Response object containing rendered page
*/
- public function render($template_file, $page_title = '', $status_code = 200)
+ public function render($template_file, $page_title = '', $status_code = 200, $display_online_list = false)
{
- page_header($page_title);
+ page_header($page_title, $display_online_list);
$this->template->set_filenames(array(
'body' => $template_file,
@@ -87,21 +91,33 @@ class helper
}
/**
- * Generate a URL
+ * Generate a URL to a route
*
- * @param string $route The route to travel
- * @param mixed $params String or array of additional url parameters
+ * @param string $route Name of the route to travel
+ * @param array $params String or array of additional url parameters
* @param bool $is_amp Is url using &amp; (true) or & (false)
* @param string $session_id Possibility to use a custom session id instead of the global one
* @return string The URL already passed through append_sid()
*/
- public function url($route, $params = false, $is_amp = true, $session_id = false)
+ public function route($route, array $params = array(), $is_amp = true, $session_id = false)
{
- $route_params = '';
- if (($route_delim = strpos($route, '?')) !== false)
+ $anchor = '';
+ if (isset($params['#']))
{
- $route_params = substr($route, $route_delim);
- $route = substr($route, 0, $route_delim);
+ $anchor = '#' . $params['#'];
+ unset($params['#']);
+ }
+ $url_generator = new UrlGenerator($this->route_collection, new RequestContext());
+ $route_url = $url_generator->generate($route, $params);
+
+ if (strpos($route_url, '/') === 0)
+ {
+ $route_url = substr($route_url, 1);
+ }
+
+ if ($is_amp)
+ {
+ $route_url = str_replace(array('&amp;', '&'), array('&', '&amp;'), $route_url);
}
// If enable_mod_rewrite is false, we need to include app.php
@@ -111,7 +127,7 @@ class helper
$route_prefix .= 'app.' . $this->php_ext . '/';
}
- return append_sid($route_prefix . "$route" . $route_params, $params, $is_amp, $session_id);
+ return append_sid($route_prefix . $route_url . $anchor, false, $is_amp, $session_id);
}
/**
diff --git a/phpBB/phpbb/controller/provider.php b/phpBB/phpbb/controller/provider.php
index fde51696e8..9df8130210 100644
--- a/phpBB/phpbb/controller/provider.php
+++ b/phpBB/phpbb/controller/provider.php
@@ -26,50 +26,58 @@ class provider
protected $routing_files;
/**
+ * Collection of the routes in phpBB and all found extensions
+ * @var RouteCollection
+ */
+ protected $routes;
+
+ /**
* Construct method
*
* @param array() $routing_files Array of strings containing paths
* to YAML files holding route information
*/
- public function __construct($routing_files = array())
+ public function __construct(\phpbb\extension\finder $finder = null, $routing_files = array())
{
$this->routing_files = $routing_files;
- }
-
- /**
- * Locate paths containing routing files
- * This sets an internal property but does not return the paths.
- *
- * @return The current instance of this object for method chaining
- */
- public function import_paths_from_finder(\phpbb\extension\finder $finder)
- {
- // We hardcode the path to the core config directory
- // because the finder cannot find it
- $this->routing_files = array_merge(array('config/routing.yml'), array_keys($finder
- ->directory('config')
- ->suffix('routing.yml')
- ->find()
- ));
- return $this;
+ if ($finder)
+ {
+ // We hardcode the path to the core config directory
+ // because the finder cannot find it
+ $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder
+ ->directory('config')
+ ->suffix('routing.yml')
+ ->find()
+ ));
+ }
}
/**
- * Get a list of controllers and return it
+ * Find a list of controllers and return it
*
* @param string $base_path Base path to prepend to file paths
- * @return array Array of controllers and their route information
+ * @return null
*/
public function find($base_path = '')
{
- $routes = new RouteCollection;
+ $this->routes = new RouteCollection;
foreach ($this->routing_files as $file_path)
{
$loader = new YamlFileLoader(new FileLocator($base_path));
- $routes->addCollection($loader->load($file_path));
+ $this->routes->addCollection($loader->load($file_path));
}
- return $routes;
+ return $this;
+ }
+
+ /**
+ * Get the list of routes
+ *
+ * @return RouteCollection Get the route collection
+ */
+ public function get_routes()
+ {
+ return $this->routes;
}
}
diff --git a/phpBB/phpbb/cron/task/core/prune_all_forums.php b/phpBB/phpbb/cron/task/core/prune_all_forums.php
index 90b9a5914b..36a551394a 100644
--- a/phpBB/phpbb/cron/task/core/prune_all_forums.php
+++ b/phpBB/phpbb/cron/task/core/prune_all_forums.php
@@ -31,9 +31,9 @@ class prune_all_forums extends \phpbb\cron\task\base
* @param string $phpbb_root_path The root path
* @param string $php_ext The PHP extension
* @param \phpbb\config\config $config The config
- * @param \phpbb\db\driver\driver $db The db connection
+ * @param \phpbb\db\driver\driver_interface $db The db connection
*/
- public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver $db)
+ public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
diff --git a/phpBB/phpbb/cron/task/core/prune_forum.php b/phpBB/phpbb/cron/task/core/prune_forum.php
index e0d8b067c5..542d75e5b9 100644
--- a/phpBB/phpbb/cron/task/core/prune_forum.php
+++ b/phpBB/phpbb/cron/task/core/prune_forum.php
@@ -41,9 +41,9 @@ class prune_forum extends \phpbb\cron\task\base implements \phpbb\cron\task\para
* @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
*/
- public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver $db)
+ public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
diff --git a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
new file mode 100644
index 0000000000..b30e665a87
--- /dev/null
+++ b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
@@ -0,0 +1,191 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\cron\task\core;
+
+/**
+* Prune one forum of its shadow topics cron task.
+*
+* It is intended to be used when cron is invoked via web.
+* This task can decide whether it should be run using data obtained by viewforum
+* code, without making additional database queries.
+*
+* @package phpBB3
+*/
+class prune_shadow_topics extends \phpbb\cron\task\base implements \phpbb\cron\task\parametrized
+{
+ protected $phpbb_root_path;
+ protected $php_ext;
+ protected $config;
+ protected $db;
+ protected $log;
+
+ /**
+ * If $forum_data is given, it is assumed to contain necessary information
+ * about a single forum that is to be pruned.
+ *
+ * If $forum_data is not given, forum id will be retrieved via request_var
+ * and a database query will be performed to load the necessary information
+ * about the forum.
+ */
+ protected $forum_data;
+
+ /**
+ * Constructor.
+ *
+ * @param string $phpbb_root_path The root path
+ * @param string $php_ext The PHP extension
+ * @param \phpbb\config\config $config The config
+ * @param \phpbb\db\driver\driver $db The db connection
+ * @param \phpbb\log\log $log The phpBB log system
+ */
+ public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\log\log $log)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->config = $config;
+ $this->db = $db;
+ $this->log = $log;
+ }
+
+ /**
+ * Manually set forum data.
+ *
+ * @param array $forum_data Information about a forum to be pruned.
+ */
+ public function set_forum_data($forum_data)
+ {
+ $this->forum_data = $forum_data;
+ }
+
+ /**
+ * Runs this cron task.
+ *
+ * @return null
+ */
+ public function run()
+ {
+ if (!function_exists('auto_prune'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_admin.' . $this->php_ext);
+ }
+
+ if ($this->forum_data['prune_shadow_days'])
+ {
+ $this->auto_prune_shadow_topics($this->forum_data['forum_id'], 'shadow', $this->forum_data['forum_flags'], $this->forum_data['prune_shadow_days'], $this->forum_data['prune_shadow_freq']);
+ }
+ }
+
+ /**
+ * Returns whether this cron task can run, given current board configuration.
+ *
+ * This cron task will not run when system cron is utilised, as in
+ * such cases prune_all_forums task would run instead.
+ *
+ * Additionally, this task must be given the forum data, either via
+ * the constructor or parse_parameters method.
+ *
+ * @return bool
+ */
+ public function is_runnable()
+ {
+ return !$this->config['use_system_cron'] && $this->forum_data;
+ }
+
+ /**
+ * Returns whether this cron task should run now, because enough time
+ * has passed since it was last run.
+ *
+ * Forum pruning interval is specified in the forum data.
+ *
+ * @return bool
+ */
+ public function should_run()
+ {
+ return $this->forum_data['enable_shadow_prune'] && $this->forum_data['prune_shadow_next'] < time();
+ }
+
+ /**
+ * Returns parameters of this cron task as an array.
+ * The array has one key, f, whose value is id of the forum to be pruned.
+ *
+ * @return array
+ */
+ public function get_parameters()
+ {
+ return array('f' => $this->forum_data['forum_id']);
+ }
+
+ /**
+ * Parses parameters found in $request, which is an instance of
+ * \phpbb\request\request_interface.
+ *
+ * It is expected to have a key f whose value is id of the forum to be pruned.
+ *
+ * @param \phpbb\request\request_interface $request Request object.
+ *
+ * @return null
+ */
+ public function parse_parameters(\phpbb\request\request_interface $request)
+ {
+ $this->forum_data = null;
+ if ($request->is_set('f'))
+ {
+ $forum_id = $request->variable('f', 0);
+
+ $sql = 'SELECT forum_id, prune_shadow_next, enable_shadow_prune, prune_shadow_days, forum_flags, prune_shadow_freq
+ FROM ' . FORUMS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $this->forum_data = $row;
+ }
+ }
+ }
+
+ /**
+ * Automatically prune shadow topics
+ * Based on fuunction auto_prune()
+ * @param int $forum_id Forum ID of forum that should be pruned
+ * @param string $prune_mode Prune mode
+ * @param int $prune_flags Prune flags
+ * @param int $prune_freq Prune frequency
+ * @return null
+ */
+ protected function auto_prune_shadow_topics($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq)
+ {
+ $sql = 'SELECT forum_name
+ FROM ' . FORUMS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $result = $this->db->sql_query($sql, 3600);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $prune_date = time() - ($prune_days * 86400);
+ $next_prune = time() + ($prune_freq * 86400);
+
+ prune($forum_id, $prune_mode, $prune_date, $prune_flags, true);
+
+ $sql = 'UPDATE ' . FORUMS_TABLE . "
+ SET prune_shadow_next = $next_prune
+ WHERE forum_id = $forum_id";
+ $this->db->sql_query($sql);
+
+ $this->log->add('admin', 'LOG_PRUNE_SHADOW', $row['forum_name']);
+ }
+
+ return;
+ }
+}
diff --git a/phpBB/phpbb/cron/task/core/tidy_search.php b/phpBB/phpbb/cron/task/core/tidy_search.php
index 42f7df308f..eac6aa0a36 100644
--- a/phpBB/phpbb/cron/task/core/tidy_search.php
+++ b/phpBB/phpbb/cron/task/core/tidy_search.php
@@ -32,10 +32,10 @@ class tidy_search extends \phpbb\cron\task\base
* @param string $php_ext The PHP extension
* @param \phpbb\auth\auth $auth The auth
* @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\user $user The user
*/
- public function __construct($phpbb_root_path, $php_ext, \phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\user $user)
+ public function __construct($phpbb_root_path, $php_ext, \phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\user $user)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php
index d721ed2eb7..85d160c80e 100644
--- a/phpBB/phpbb/db/driver/driver.php
+++ b/phpBB/phpbb/db/driver/driver.php
@@ -13,7 +13,7 @@ namespace phpbb\db\driver;
* Database Abstraction Layer
* @package dbal
*/
-class driver
+abstract class driver implements driver_interface
{
var $db_connect_id;
var $query_result;
@@ -84,7 +84,7 @@ class driver
}
/**
- * return on error or display error message
+ * {@inheritDoc}
*/
function sql_return_on_error($fail = false)
{
@@ -95,7 +95,7 @@ class driver
}
/**
- * Return number of sql queries and cached sql queries used
+ * {@inheritDoc}
*/
function sql_num_queries($cached = false)
{
@@ -103,7 +103,7 @@ class driver
}
/**
- * Add to query count
+ * {@inheritDoc}
*/
function sql_add_num_queries($cached = false)
{
@@ -113,7 +113,7 @@ class driver
}
/**
- * DBAL garbage collection, close sql connection
+ * {@inheritDoc}
*/
function sql_close()
{
@@ -146,8 +146,7 @@ class driver
}
/**
- * Build LIMIT query
- * Doing some validation here.
+ * {@inheritDoc}
*/
function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
@@ -164,7 +163,7 @@ class driver
}
/**
- * Fetch all rows
+ * {@inheritDoc}
*/
function sql_fetchrowset($query_id = false)
{
@@ -188,8 +187,7 @@ class driver
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -231,8 +229,7 @@ class driver
}
/**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
+ * {@inheritDoc}
*/
function sql_fetchfield($field, $rownum = false, $query_id = false)
{
@@ -263,11 +260,7 @@ class driver
}
/**
- * Correctly adjust LIKE expression for special characters
- * Some DBMS are handling them in a different way
- *
- * @param string $expression The expression to use. Every wildcard is escaped, except $this->any_char and $this->one_char
- * @return string LIKE expression including the keyword!
+ * {@inheritDoc}
*/
function sql_like_expression($expression)
{
@@ -278,14 +271,7 @@ class driver
}
/**
- * Build a case expression
- *
- * Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database!
- *
- * @param string $condition The condition which must be true, to use action_true rather then action_else
- * @param string $action_true SQL expression that is used, if the condition is true
- * @param string $action_else SQL expression that is used, if the condition is false, optional
- * @return string CASE expression including the condition and statements
+ * {@inheritDoc}
*/
public function sql_case($condition, $action_true, $action_false = false)
{
@@ -297,11 +283,7 @@ class driver
}
/**
- * Build a concatenated expression
- *
- * @param string $expr1 Base SQL expression where we append the second one
- * @param string $expr2 SQL expression that is appended to the first expression
- * @return string Concatenated string
+ * {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
@@ -309,9 +291,7 @@ class driver
}
/**
- * Returns whether results of a query need to be buffered to run a transaction while iterating over them.
- *
- * @return bool Whether buffering is required.
+ * {@inheritDoc}
*/
function sql_buffer_nested_transactions()
{
@@ -319,15 +299,14 @@ class driver
}
/**
- * SQL Transaction
- * @access private
+ * {@inheritDoc}
*/
function sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
- // If we are within a transaction we will not open another one, but enclose the current one to not loose data (prevening auto commit)
+ // If we are within a transaction we will not open another one, but enclose the current one to not loose data (preventing auto commit)
if ($this->transaction)
{
$this->transactions++;
@@ -345,14 +324,16 @@ class driver
break;
case 'commit':
- // If there was a previously opened transaction we do not commit yet... but count back the number of inner transactions
+ // If there was a previously opened transaction we do not commit yet...
+ // but count back the number of inner transactions
if ($this->transaction && $this->transactions)
{
$this->transactions--;
return true;
}
- // Check if there is a transaction (no transaction can happen if there was an error, with a combined rollback and error returning enabled)
+ // Check if there is a transaction (no transaction can happen if
+ // there was an error, with a combined rollback and error returning enabled)
// This implies we have transaction always set for autocommit db's
if (!$this->transaction)
{
@@ -385,11 +366,7 @@ class driver
}
/**
- * Build sql statement from array for insert/update/select statements
- *
- * Idea for this from Ikonboard
- * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT
- *
+ * {@inheritDoc}
*/
function sql_build_array($query, $assoc_ary = false)
{
@@ -423,7 +400,7 @@ class driver
{
trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR);
}
- else if ($query == 'UPDATE' || $query == 'SELECT')
+ else if ($query == 'UPDATE' || $query == 'SELECT' || $query == 'DELETE')
{
$values = array();
foreach ($assoc_ary as $key => $var)
@@ -437,14 +414,7 @@ class driver
}
/**
- * Build IN or NOT IN sql comparison string, uses <> or = on single element
- * arrays to improve comparison speed
- *
- * @access public
- * @param string $field name of the sql column that shall be compared
- * @param array $array array of values that are allowed (IN) or not allowed (NOT IN)
- * @param bool $negate true for NOT IN (), false for IN () (default)
- * @param bool $allow_empty_set If true, allow $array to be empty, this function will return 1=1 or 1=0 then. Default to false.
+ * {@inheritDoc}
*/
function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
{
@@ -489,12 +459,7 @@ class driver
}
/**
- * Run binary AND operator on DB column.
- * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}"
- *
- * @param string $column_name The column name to use
- * @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29
- * @param string $compare Any custom SQL code after the check (for example "= 0")
+ * {@inheritDoc}
*/
function sql_bit_and($column_name, $bit, $compare = '')
{
@@ -507,12 +472,7 @@ class driver
}
/**
- * Run binary OR operator on DB column.
- * Results in sql statement: "{$column_name} | (1 << {$bit}) {$compare}"
- *
- * @param string $column_name The column name to use
- * @param int $bit The value to use for the OR operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29
- * @param string $compare Any custom SQL code after the check (for example "= 0")
+ * {@inheritDoc}
*/
function sql_bit_or($column_name, $bit, $compare = '')
{
@@ -525,10 +485,7 @@ class driver
}
/**
- * Returns SQL string to cast a string expression to an int.
- *
- * @param string $expression An expression evaluating to string
- * @return string Expression returning an int
+ * {@inheritDoc}
*/
function cast_expr_to_bigint($expression)
{
@@ -536,10 +493,7 @@ class driver
}
/**
- * Returns SQL string to cast an integer expression to a string.
- *
- * @param string $expression An expression evaluating to int
- * @return string Expression returning a string
+ * {@inheritDoc}
*/
function cast_expr_to_string($expression)
{
@@ -547,11 +501,7 @@ class driver
}
/**
- * Run LOWER() on DB column of type text (i.e. neither varchar nor char).
- *
- * @param string $column_name The column name to use
- *
- * @return string A SQL statement like "LOWER($column_name)"
+ * {@inheritDoc}
*/
function sql_lower_text($column_name)
{
@@ -559,13 +509,7 @@ class driver
}
/**
- * Run more than one insert statement.
- *
- * @param string $table table name to run the statements on
- * @param array $sql_ary multi-dimensional array holding the statement data.
- *
- * @return bool false if no statements were executed.
- * @access public
+ * {@inheritDoc}
*/
function sql_multi_insert($table, $sql_ary)
{
@@ -637,9 +581,7 @@ class driver
}
/**
- * Build sql statement from array for select and select distinct statements
- *
- * Possible query values: SELECT, SELECT_DISTINCT
+ * {@inheritDoc}
*/
function sql_build_query($query, $array)
{
@@ -742,7 +684,7 @@ class driver
}
/**
- * display sql error page
+ * {@inheritDoc}
*/
function sql_error($sql = '')
{
@@ -812,7 +754,7 @@ class driver
}
/**
- * Explain queries
+ * {@inheritDoc}
*/
function sql_report($mode, $query = '')
{
@@ -1002,14 +944,7 @@ class driver
}
/**
- * Gets the estimated number of rows in a specified table.
- *
- * @param string $table_name Table name
- *
- * @return string Number of rows in $table_name.
- * Prefixed with ~ if estimated (otherwise exact).
- *
- * @access public
+ * {@inheritDoc}
*/
function get_estimated_row_count($table_name)
{
@@ -1017,13 +952,7 @@ class driver
}
/**
- * Gets the exact number of rows in a specified table.
- *
- * @param string $table_name Table name
- *
- * @return string Exact number of rows in $table_name.
- *
- * @access public
+ * {@inheritDoc}
*/
function get_row_count($table_name)
{
diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php
new file mode 100644
index 0000000000..a9051616c9
--- /dev/null
+++ b/phpBB/phpbb/db/driver/driver_interface.php
@@ -0,0 +1,355 @@
+<?php
+/**
+*
+* @package dbal
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\driver;
+
+interface driver_interface
+{
+ /**
+ * Gets the exact number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ * @return string Exact number of rows in $table_name.
+ */
+ public function get_row_count($table_name);
+
+ /**
+ * Gets the estimated number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ * @return string Number of rows in $table_name.
+ * Prefixed with ~ if estimated (otherwise exact).
+ */
+ public function get_estimated_row_count($table_name);
+
+ /**
+ * Run LOWER() on DB column of type text (i.e. neither varchar nor char).
+ *
+ * @param string $column_name The column name to use
+ * @return string A SQL statement like "LOWER($column_name)"
+ */
+ public function sql_lower_text($column_name);
+
+ /**
+ * Display sql error page
+ *
+ * @param string $sql The SQL query causing the error
+ * @return mixed Returns the full error message, if $this->return_on_error
+ * is set, null otherwise
+ */
+ public function sql_error($sql = '');
+
+ /**
+ * Returns whether results of a query need to be buffered to run a
+ * transaction while iterating over them.
+ *
+ * @return bool Whether buffering is required.
+ */
+ public function sql_buffer_nested_transactions();
+
+ /**
+ * Run binary OR operator on DB column.
+ *
+ * @param string $column_name The column name to use
+ * @param int $bit The value to use for the OR operator,
+ * will be converted to (1 << $bit). Is used by options,
+ * using the number schema... 0, 1, 2...29
+ * @param string $compare Any custom SQL code after the check (e.g. "= 0")
+ * @return string A SQL statement like "$column | (1 << $bit) {$compare}"
+ */
+ public function sql_bit_or($column_name, $bit, $compare = '');
+
+ /**
+ * Version information about used database
+ *
+ * @param bool $raw Only return the fetched sql_server_version
+ * @param bool $use_cache Is it safe to retrieve the value from the cache
+ * @return string sql server version
+ */
+ public function sql_server_info($raw = false, $use_cache = true);
+
+ /**
+ * Return on error or display error message
+ *
+ * @param bool $fail Should we return on errors, or stop
+ * @return null
+ */
+ public function sql_return_on_error($fail = false);
+
+ /**
+ * Build sql statement from an array
+ *
+ * @param string $query Should be on of the following strings:
+ * INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE
+ * @param array $assoc_ary Array with "column => value" pairs
+ * @return string A SQL statement like "c1 = 'a' AND c2 = 'b'"
+ */
+ public function sql_build_array($query, $assoc_ary = array());
+
+ /**
+ * Fetch all rows
+ *
+ * @param mixed $query_id Already executed query to get the rows from,
+ * if false, the last query will be used.
+ * @return mixed Nested array if the query had rows, false otherwise
+ */
+ public function sql_fetchrowset($query_id = false);
+
+ /**
+ * SQL Transaction
+ *
+ * @param string $status Should be one of the following strings:
+ * begin, commit, rollback
+ * @return mixed Buffered, seekable result handle, false on error
+ */
+ public function sql_transaction($status = 'begin');
+
+ /**
+ * Build a concatenated expression
+ *
+ * @param string $expr1 Base SQL expression where we append the second one
+ * @param string $expr2 SQL expression that is appended to the first expression
+ * @return string Concatenated string
+ */
+ public function sql_concatenate($expr1, $expr2);
+
+ /**
+ * Build a case expression
+ *
+ * Note: The two statements action_true and action_false must have the same
+ * data type (int, vchar, ...) in the database!
+ *
+ * @param string $condition The condition which must be true,
+ * to use action_true rather then action_else
+ * @param string $action_true SQL expression that is used, if the condition is true
+ * @param mixed $action_false SQL expression that is used, if the condition is false
+ * @return string CASE expression including the condition and statements
+ */
+ public function sql_case($condition, $action_true, $action_false = false);
+
+ /**
+ * Build sql statement from array for select and select distinct statements
+ *
+ * Possible query values: SELECT, SELECT_DISTINCT
+ *
+ * @param string $query Should be one of: SELECT, SELECT_DISTINCT
+ * @param array $array Array with the query data:
+ * SELECT A comma imploded list of columns to select
+ * FROM Array with "table => alias" pairs,
+ * (alias can also be an array)
+ * Optional: LEFT_JOIN Array of join entries:
+ * FROM Table that should be joined
+ * ON Condition for the join
+ * Optional: WHERE Where SQL statement
+ * Optional: GROUP_BY Group by SQL statement
+ * Optional: ORDER_BY Order by SQL statement
+ * @return string A SQL statement ready for execution
+ */
+ public function sql_build_query($query, $array);
+
+ /**
+ * Fetch field
+ * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
+ *
+ * @param string $field Name of the column
+ * @param mixed $rownum Row number, if false the current row will be used
+ * and the row curser will point to the next row
+ * Note: $rownum is 0 based
+ * @param mixed $query_id Already executed query to get the rows from,
+ * if false, the last query will be used.
+ * @return mixed String value of the field in the selected row,
+ * false, if the row does not exist
+ */
+ public function sql_fetchfield($field, $rownum = false, $query_id = false);
+
+ /**
+ * Fetch current row
+ *
+ * @param mixed $query_id Already executed query to get the rows from,
+ * if false, the last query will be used.
+ * @return mixed Array with the current row,
+ * false, if the row does not exist
+ */
+ public function sql_fetchrow($query_id = false);
+
+ /**
+ * Returns SQL string to cast a string expression to an int.
+ *
+ * @param string $expression An expression evaluating to string
+ * @return string Expression returning an int
+ */
+ public function cast_expr_to_bigint($expression);
+
+ /**
+ * Get last inserted id after insert statement
+ *
+ * @return string Autoincrement value of the last inserted row
+ */
+ public function sql_nextid();
+
+ /**
+ * Add to query count
+ *
+ * @param bool $cached Is this query cached?
+ * @return null
+ */
+ public function sql_add_num_queries($cached = false);
+
+ /**
+ * Build LIMIT query
+ *
+ * @param string $query The SQL query to execute
+ * @param int $total The number of rows to select
+ * @param int $offset
+ * @param int $cache_ttl Either 0 to avoid caching or
+ * the time in seconds which the result shall be kept in cache
+ * @return mixed Buffered, seekable result handle, false on error
+ */
+ public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0);
+
+ /**
+ * Base query method
+ *
+ * @param string $query The SQL query to execute
+ * @param int $cache_ttl Either 0 to avoid caching or
+ * the time in seconds which the result shall be kept in cache
+ * @return mixed Buffered, seekable result handle, false on error
+ */
+ public function sql_query($query = '', $cache_ttl = 0);
+
+ /**
+ * Returns SQL string to cast an integer expression to a string.
+ *
+ * @param string $expression An expression evaluating to int
+ * @return string Expression returning a string
+ */
+ public function cast_expr_to_string($expression);
+
+ /**
+ * Connect to server
+ *
+ * @param string $sqlserver Address of the database server
+ * @param string $sqluser User name of the SQL user
+ * @param string $sqlpassword Password of the SQL user
+ * @param string $database Name of the database
+ * @param mixed $port Port of the database server
+ * @param bool $persistency
+ * @param bool $new_link Should a new connection be established
+ * @return mixed Connection ID on success, string error message otherwise
+ */
+ public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false);
+
+ /**
+ * Run binary AND operator on DB column.
+ * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}"
+ *
+ * @param string $column_name The column name to use
+ * @param int $bit The value to use for the AND operator,
+ * will be converted to (1 << $bit). Is used by
+ * options, using the number schema: 0, 1, 2...29
+ * @param string $compare Any custom SQL code after the check (for example "= 0")
+ * @return string A SQL statement like: "{$column} & (1 << {$bit}) {$compare}"
+ */
+ public function sql_bit_and($column_name, $bit, $compare = '');
+
+ /**
+ * Free sql result
+ *
+ * @param mixed $query_id Already executed query result,
+ * if false, the last query will be used.
+ * @return null
+ */
+ public function sql_freeresult($query_id = false);
+
+ /**
+ * Return number of sql queries and cached sql queries used
+ *
+ * @param bool $cached Should we return the number of cached or normal queries?
+ * @return int Number of queries that have been executed
+ */
+ public function sql_num_queries($cached = false);
+
+ /**
+ * Run more than one insert statement.
+ *
+ * @param string $table Table name to run the statements on
+ * @param array $sql_ary Multi-dimensional array holding the statement data
+ * @return bool false if no statements were executed.
+ */
+ public function sql_multi_insert($table, $sql_ary);
+
+ /**
+ * Return number of affected rows
+ *
+ * @return mixed Number of the affected rows by the last query
+ * false if no query has been run before
+ */
+ public function sql_affectedrows();
+
+ /**
+ * DBAL garbage collection, close SQL connection
+ *
+ * @return mixed False if no connection was opened before,
+ * Server response otherwise
+ */
+ public function sql_close();
+
+ /**
+ * Seek to given row number
+ *
+ * @param mixed $rownum Row number the curser should point to
+ * Note: $rownum is 0 based
+ * @param mixed $query_id ID of the query to set the row cursor on
+ * if false, the last query will be used.
+ * $query_id will then be set correctly
+ * @return bool False if something went wrong
+ */
+ public function sql_rowseek($rownum, &$query_id);
+
+ /**
+ * Escape string used in sql query
+ *
+ * @param string $msg String to be escaped
+ * @return string Escaped version of $msg
+ */
+ public function sql_escape($msg);
+
+ /**
+ * Correctly adjust LIKE expression for special characters
+ * Some DBMS are handling them in a different way
+ *
+ * @param string $expression The expression to use. Every wildcard is
+ * escaped, except $this->any_char and $this->one_char
+ * @return string A SQL statement like: "LIKE 'bertie_%'"
+ */
+ public function sql_like_expression($expression);
+
+ /**
+ * Explain queries
+ *
+ * @param string $mode Available modes: display, start, stop,
+ * add_select_row, fromcache, record_fromcache
+ * @param string $query The Query that should be explained
+ * @return mixed Either a full HTML page, boolean or null
+ */
+ public function sql_report($mode, $query = '');
+
+ /**
+ * Build IN or NOT IN sql comparison string, uses <> or = on single element
+ * arrays to improve comparison speed
+ *
+ * @param string $field Name of the sql column that shall be compared
+ * @param array $array Array of values that are (not) allowed
+ * @param bool $negate true for NOT IN (), false for IN ()
+ * @param bool $allow_empty_set If true, allow $array to be empty,
+ * this function will return 1=1 or 1=0 then.
+ * @return string A SQL statement like: "IN (1, 2, 3, 4)" or "= 1"
+ */
+ public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false);
+}
diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php
index ed56a5d154..a4967c7ffe 100644
--- a/phpBB/phpbb/db/driver/firebird.php
+++ b/phpBB/phpbb/db/driver/firebird.php
@@ -22,7 +22,7 @@ class firebird extends \phpbb\db\driver\driver
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -79,10 +79,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache forced to false for Interbase
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -127,13 +124,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -297,7 +288,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -313,7 +304,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -351,7 +342,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -379,7 +370,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -405,7 +396,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
@@ -441,7 +432,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * @inheritdoc
+ * {@inheritDoc}
*/
function cast_expr_to_bigint($expression)
{
@@ -450,7 +441,7 @@ class firebird extends \phpbb\db\driver\driver
}
/**
- * @inheritdoc
+ * {@inheritDoc}
*/
function cast_expr_to_string($expression)
{
diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php
index 6ebc891673..588cd7a7e8 100644
--- a/phpBB/phpbb/db/driver/mssql.php
+++ b/phpBB/phpbb/db/driver/mssql.php
@@ -19,7 +19,7 @@ class mssql extends \phpbb\db\driver\driver
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -55,10 +55,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -124,13 +121,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -215,7 +206,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -223,7 +214,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -259,8 +250,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -280,7 +270,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -299,7 +289,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -325,7 +315,7 @@ class mssql extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php
index 113f1c6902..1e3fb8235a 100644
--- a/phpBB/phpbb/db/driver/mssql_base.php
+++ b/phpBB/phpbb/db/driver/mssql_base.php
@@ -24,7 +24,7 @@ abstract class mssql_base extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php
index f8c70f1cd7..34b913dc8a 100644
--- a/phpBB/phpbb/db/driver/mssql_odbc.php
+++ b/phpBB/phpbb/db/driver/mssql_odbc.php
@@ -26,7 +26,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -83,10 +83,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -144,13 +141,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -236,7 +227,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -244,8 +235,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Fetch current row
- * @note number of bytes returned depends on odbc.defaultlrl php.ini setting. If it is limited to 4K for example only 4K of data is returned max.
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -265,7 +255,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -286,7 +276,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php
index 125db9c8d4..b449de2ae4 100644
--- a/phpBB/phpbb/db/driver/mssqlnative.php
+++ b/phpBB/phpbb/db/driver/mssqlnative.php
@@ -24,7 +24,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -53,10 +53,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -113,13 +110,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -215,7 +206,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -223,7 +214,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -263,7 +254,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -283,7 +274,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php
index e311f0dd74..1a4fd364df 100644
--- a/phpBB/phpbb/db/driver/mysql.php
+++ b/phpBB/phpbb/db/driver/mysql.php
@@ -24,8 +24,7 @@ class mysql extends \phpbb\db\driver\mysql_base
var $connect_error = '';
/**
- * Connect to server
- * @access public
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -103,10 +102,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -154,13 +150,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -213,7 +203,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -221,7 +211,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -241,8 +231,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -262,7 +251,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -270,7 +259,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -296,7 +285,7 @@ class mysql extends \phpbb\db\driver\mysql_base
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php
index 87b6d153a9..d0f6a9e8fa 100644
--- a/phpBB/phpbb/db/driver/mysql_base.php
+++ b/phpBB/phpbb/db/driver/mysql_base.php
@@ -43,14 +43,7 @@ abstract class mysql_base extends \phpbb\db\driver\driver
}
/**
- * Gets the estimated number of rows in a specified table.
- *
- * @param string $table_name Table name
- *
- * @return string Number of rows in $table_name.
- * Prefixed with ~ if estimated (otherwise exact).
- *
- * @access public
+ * {@inheritDoc}
*/
function get_estimated_row_count($table_name)
{
@@ -72,13 +65,7 @@ abstract class mysql_base extends \phpbb\db\driver\driver
}
/**
- * Gets the exact number of rows in a specified table.
- *
- * @param string $table_name Table name
- *
- * @return string Exact number of rows in $table_name.
- *
- * @access public
+ * {@inheritDoc}
*/
function get_row_count($table_name)
{
diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php
index adc8f96302..6814599b24 100644
--- a/phpBB/phpbb/db/driver/mysqli.php
+++ b/phpBB/phpbb/db/driver/mysqli.php
@@ -21,7 +21,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -96,10 +96,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -151,13 +148,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -205,7 +196,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -213,7 +204,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -239,8 +230,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -260,7 +250,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -268,7 +258,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -288,7 +278,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php
index 36ed43d4a7..8a304b5042 100644
--- a/phpBB/phpbb/db/driver/oracle.php
+++ b/phpBB/phpbb/db/driver/oracle.php
@@ -19,7 +19,7 @@ class oracle extends \phpbb\db\driver\driver
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -72,10 +72,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache forced to false for Oracle
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -240,13 +237,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -473,7 +464,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -481,7 +472,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -532,8 +523,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -570,7 +560,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -602,7 +592,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -628,7 +618,7 @@ class oracle extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php
index 5dbd1ca74f..9e091f0a5d 100644
--- a/phpBB/phpbb/db/driver/postgres.php
+++ b/phpBB/phpbb/db/driver/postgres.php
@@ -20,7 +20,7 @@ class postgres extends \phpbb\db\driver\driver
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -115,10 +115,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache If true, it is safe to retrieve the value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -166,13 +163,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -253,7 +244,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -261,7 +252,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -281,8 +272,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -302,7 +292,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -331,7 +321,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -357,8 +347,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
- * Note: Do not use for bytea values if we may use them at a later stage
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
@@ -375,7 +364,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * @inheritdoc
+ * {@inheritDoc}
*/
function cast_expr_to_bigint($expression)
{
@@ -383,7 +372,7 @@ class postgres extends \phpbb\db\driver\driver
}
/**
- * @inheritdoc
+ * {@inheritDoc}
*/
function cast_expr_to_string($expression)
{
diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php
index 59ec895c0f..86a585f4eb 100644
--- a/phpBB/phpbb/db/driver/sqlite.php
+++ b/phpBB/phpbb/db/driver/sqlite.php
@@ -19,7 +19,7 @@ class sqlite extends \phpbb\db\driver\driver
var $connect_error = '';
/**
- * Connect to server
+ * {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
@@ -58,10 +58,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Version information about used database
- * @param bool $raw if true, only return the fetched sql_server_version
- * @param bool $use_cache if true, it is safe to retrieve the stored value from the cache
- * @return string sql server version
+ * {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
@@ -108,13 +105,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
+ * {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
@@ -185,7 +176,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Return number of affected rows
+ * {@inheritDoc}
*/
function sql_affectedrows()
{
@@ -193,7 +184,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Fetch current row
+ * {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
@@ -213,8 +204,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Seek to given row number
- * rownum is zero-based
+ * {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
@@ -234,7 +224,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Get last inserted id after insert statement
+ * {@inheritDoc}
*/
function sql_nextid()
{
@@ -242,7 +232,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Free sql result
+ * {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
@@ -262,7 +252,7 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Escape string used in sql query
+ * {@inheritDoc}
*/
function sql_escape($msg)
{
@@ -270,7 +260,8 @@ class sqlite extends \phpbb\db\driver\driver
}
/**
- * Correctly adjust LIKE expression for special characters
+ * {@inheritDoc}
+ *
* For SQLite an underscore is a not-known character... this may change with SQLite3
*/
function sql_like_expression($expression)
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php
new file mode 100644
index 0000000000..41ade22a29
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_0.php
@@ -0,0 +1,1177 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v30x;
+
+class release_3_0_0 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return phpbb_version_compare($this->config['version'], '3.0.0', '>=');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_tables' => array(
+ $this->table_prefix . 'attachments' => array(
+ 'COLUMNS' => array(
+ 'attach_id' => array('UINT', NULL, 'auto_increment'),
+ 'post_msg_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ 'in_message' => array('BOOL', 0),
+ 'poster_id' => array('UINT', 0),
+ 'is_orphan' => array('BOOL', 1),
+ 'physical_filename' => array('VCHAR', ''),
+ 'real_filename' => array('VCHAR', ''),
+ 'download_count' => array('UINT', 0),
+ 'attach_comment' => array('TEXT_UNI', ''),
+ 'extension' => array('VCHAR:100', ''),
+ 'mimetype' => array('VCHAR:100', ''),
+ 'filesize' => array('UINT:20', 0),
+ 'filetime' => array('TIMESTAMP', 0),
+ 'thumbnail' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'attach_id',
+ 'KEYS' => array(
+ 'filetime' => array('INDEX', 'filetime'),
+ 'post_msg_id' => array('INDEX', 'post_msg_id'),
+ 'topic_id' => array('INDEX', 'topic_id'),
+ 'poster_id' => array('INDEX', 'poster_id'),
+ 'is_orphan' => array('INDEX', 'is_orphan'),
+ ),
+ ),
+
+ $this->table_prefix . 'acl_groups' => array(
+ 'COLUMNS' => array(
+ 'group_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'auth_option_id' => array('UINT', 0),
+ 'auth_role_id' => array('UINT', 0),
+ 'auth_setting' => array('TINT:2', 0),
+ ),
+ 'KEYS' => array(
+ 'group_id' => array('INDEX', 'group_id'),
+ 'auth_opt_id' => array('INDEX', 'auth_option_id'),
+ 'auth_role_id' => array('INDEX', 'auth_role_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'acl_options' => array(
+ 'COLUMNS' => array(
+ 'auth_option_id' => array('UINT', NULL, 'auto_increment'),
+ 'auth_option' => array('VCHAR:50', ''),
+ 'is_global' => array('BOOL', 0),
+ 'is_local' => array('BOOL', 0),
+ 'founder_only' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'auth_option_id',
+ 'KEYS' => array(
+ 'auth_option' => array('INDEX', 'auth_option'),
+ ),
+ ),
+
+ $this->table_prefix . 'acl_roles' => array(
+ 'COLUMNS' => array(
+ 'role_id' => array('UINT', NULL, 'auto_increment'),
+ 'role_name' => array('VCHAR_UNI', ''),
+ 'role_description' => array('TEXT_UNI', ''),
+ 'role_type' => array('VCHAR:10', ''),
+ 'role_order' => array('USINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'role_id',
+ 'KEYS' => array(
+ 'role_type' => array('INDEX', 'role_type'),
+ 'role_order' => array('INDEX', 'role_order'),
+ ),
+ ),
+
+ $this->table_prefix . 'acl_roles_data' => array(
+ 'COLUMNS' => array(
+ 'role_id' => array('UINT', 0),
+ 'auth_option_id' => array('UINT', 0),
+ 'auth_setting' => array('TINT:2', 0),
+ ),
+ 'PRIMARY_KEY' => array('role_id', 'auth_option_id'),
+ 'KEYS' => array(
+ 'ath_op_id' => array('INDEX', 'auth_option_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'acl_users' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'auth_option_id' => array('UINT', 0),
+ 'auth_role_id' => array('UINT', 0),
+ 'auth_setting' => array('TINT:2', 0),
+ ),
+ 'KEYS' => array(
+ 'user_id' => array('INDEX', 'user_id'),
+ 'auth_option_id' => array('INDEX', 'auth_option_id'),
+ 'auth_role_id' => array('INDEX', 'auth_role_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'banlist' => array(
+ 'COLUMNS' => array(
+ 'ban_id' => array('UINT', NULL, 'auto_increment'),
+ 'ban_userid' => array('UINT', 0),
+ 'ban_ip' => array('VCHAR:40', ''),
+ 'ban_email' => array('VCHAR_UNI:100', ''),
+ 'ban_start' => array('TIMESTAMP', 0),
+ 'ban_end' => array('TIMESTAMP', 0),
+ 'ban_exclude' => array('BOOL', 0),
+ 'ban_reason' => array('VCHAR_UNI', ''),
+ 'ban_give_reason' => array('VCHAR_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'ban_id',
+ 'KEYS' => array(
+ 'ban_end' => array('INDEX', 'ban_end'),
+ 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')),
+ 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')),
+ 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')),
+ ),
+ ),
+
+ $this->table_prefix . 'bbcodes' => array(
+ 'COLUMNS' => array(
+ 'bbcode_id' => array('TINT:3', 0),
+ 'bbcode_tag' => array('VCHAR:16', ''),
+ 'bbcode_helpline' => array('VCHAR_UNI', ''),
+ 'display_on_posting' => array('BOOL', 0),
+ 'bbcode_match' => array('TEXT_UNI', ''),
+ 'bbcode_tpl' => array('MTEXT_UNI', ''),
+ 'first_pass_match' => array('MTEXT_UNI', ''),
+ 'first_pass_replace' => array('MTEXT_UNI', ''),
+ 'second_pass_match' => array('MTEXT_UNI', ''),
+ 'second_pass_replace' => array('MTEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'bbcode_id',
+ 'KEYS' => array(
+ 'display_on_post' => array('INDEX', 'display_on_posting'),
+ ),
+ ),
+
+ $this->table_prefix . 'bookmarks' => array(
+ 'COLUMNS' => array(
+ 'topic_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => array('topic_id', 'user_id'),
+ ),
+
+ $this->table_prefix . 'bots' => array(
+ 'COLUMNS' => array(
+ 'bot_id' => array('UINT', NULL, 'auto_increment'),
+ 'bot_active' => array('BOOL', 1),
+ 'bot_name' => array('STEXT_UNI', ''),
+ 'user_id' => array('UINT', 0),
+ 'bot_agent' => array('VCHAR', ''),
+ 'bot_ip' => array('VCHAR', ''),
+ ),
+ 'PRIMARY_KEY' => 'bot_id',
+ 'KEYS' => array(
+ 'bot_active' => array('INDEX', 'bot_active'),
+ ),
+ ),
+
+ $this->table_prefix . 'config' => array(
+ 'COLUMNS' => array(
+ 'config_name' => array('VCHAR', ''),
+ 'config_value' => array('VCHAR_UNI', ''),
+ 'is_dynamic' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'config_name',
+ 'KEYS' => array(
+ 'is_dynamic' => array('INDEX', 'is_dynamic'),
+ ),
+ ),
+
+ $this->table_prefix . 'confirm' => array(
+ 'COLUMNS' => array(
+ 'confirm_id' => array('CHAR:32', ''),
+ 'session_id' => array('CHAR:32', ''),
+ 'confirm_type' => array('TINT:3', 0),
+ 'code' => array('VCHAR:8', ''),
+ 'seed' => array('UINT:10', 0),
+ ),
+ 'PRIMARY_KEY' => array('session_id', 'confirm_id'),
+ 'KEYS' => array(
+ 'confirm_type' => array('INDEX', 'confirm_type'),
+ ),
+ ),
+
+ $this->table_prefix . 'disallow' => array(
+ 'COLUMNS' => array(
+ 'disallow_id' => array('UINT', NULL, 'auto_increment'),
+ 'disallow_username' => array('VCHAR_UNI:255', ''),
+ ),
+ 'PRIMARY_KEY' => 'disallow_id',
+ ),
+
+ $this->table_prefix . 'drafts' => array(
+ 'COLUMNS' => array(
+ 'draft_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'save_time' => array('TIMESTAMP', 0),
+ 'draft_subject' => array('XSTEXT_UNI', ''),
+ 'draft_message' => array('MTEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'draft_id',
+ 'KEYS' => array(
+ 'save_time' => array('INDEX', 'save_time'),
+ ),
+ ),
+
+ $this->table_prefix . 'extensions' => array(
+ 'COLUMNS' => array(
+ 'extension_id' => array('UINT', NULL, 'auto_increment'),
+ 'group_id' => array('UINT', 0),
+ 'extension' => array('VCHAR:100', ''),
+ ),
+ 'PRIMARY_KEY' => 'extension_id',
+ ),
+
+ $this->table_prefix . 'extension_groups' => array(
+ 'COLUMNS' => array(
+ 'group_id' => array('UINT', NULL, 'auto_increment'),
+ 'group_name' => array('VCHAR_UNI', ''),
+ 'cat_id' => array('TINT:2', 0),
+ 'allow_group' => array('BOOL', 0),
+ 'download_mode' => array('BOOL', 1),
+ 'upload_icon' => array('VCHAR', ''),
+ 'max_filesize' => array('UINT:20', 0),
+ 'allowed_forums' => array('TEXT', ''),
+ 'allow_in_pm' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'group_id',
+ ),
+
+ $this->table_prefix . 'forums' => array(
+ 'COLUMNS' => array(
+ 'forum_id' => array('UINT', NULL, 'auto_increment'),
+ 'parent_id' => array('UINT', 0),
+ 'left_id' => array('UINT', 0),
+ 'right_id' => array('UINT', 0),
+ 'forum_parents' => array('MTEXT', ''),
+ 'forum_name' => array('STEXT_UNI', ''),
+ 'forum_desc' => array('TEXT_UNI', ''),
+ 'forum_desc_bitfield' => array('VCHAR:255', ''),
+ 'forum_desc_options' => array('UINT:11', 7),
+ 'forum_desc_uid' => array('VCHAR:8', ''),
+ 'forum_link' => array('VCHAR_UNI', ''),
+ 'forum_password' => array('VCHAR_UNI:40', ''),
+ 'forum_style' => array('USINT', 0),
+ 'forum_image' => array('VCHAR', ''),
+ 'forum_rules' => array('TEXT_UNI', ''),
+ 'forum_rules_link' => array('VCHAR_UNI', ''),
+ 'forum_rules_bitfield' => array('VCHAR:255', ''),
+ 'forum_rules_options' => array('UINT:11', 7),
+ 'forum_rules_uid' => array('VCHAR:8', ''),
+ 'forum_topics_per_page' => array('TINT:4', 0),
+ 'forum_type' => array('TINT:4', 0),
+ 'forum_status' => array('TINT:4', 0),
+ 'forum_posts' => array('UINT', 0),
+ 'forum_topics' => array('UINT', 0),
+ 'forum_topics_real' => array('UINT', 0),
+ 'forum_last_post_id' => array('UINT', 0),
+ 'forum_last_poster_id' => array('UINT', 0),
+ 'forum_last_post_subject' => array('XSTEXT_UNI', ''),
+ 'forum_last_post_time' => array('TIMESTAMP', 0),
+ 'forum_last_poster_name'=> array('VCHAR_UNI', ''),
+ 'forum_last_poster_colour'=> array('VCHAR:6', ''),
+ 'forum_flags' => array('TINT:4', 32),
+ 'display_on_index' => array('BOOL', 1),
+ 'enable_indexing' => array('BOOL', 1),
+ 'enable_icons' => array('BOOL', 1),
+ 'enable_prune' => array('BOOL', 0),
+ 'prune_next' => array('TIMESTAMP', 0),
+ 'prune_days' => array('UINT', 0),
+ 'prune_viewed' => array('UINT', 0),
+ 'prune_freq' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'forum_id',
+ 'KEYS' => array(
+ 'left_right_id' => array('INDEX', array('left_id', 'right_id')),
+ 'forum_lastpost_id' => array('INDEX', 'forum_last_post_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'forums_access' => array(
+ 'COLUMNS' => array(
+ 'forum_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'session_id' => array('CHAR:32', ''),
+ ),
+ 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'),
+ ),
+
+ $this->table_prefix . 'forums_track' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'mark_time' => array('TIMESTAMP', 0),
+ ),
+ 'PRIMARY_KEY' => array('user_id', 'forum_id'),
+ ),
+
+ $this->table_prefix . 'forums_watch' => array(
+ 'COLUMNS' => array(
+ 'forum_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'notify_status' => array('BOOL', 0),
+ ),
+ 'KEYS' => array(
+ 'forum_id' => array('INDEX', 'forum_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ 'notify_stat' => array('INDEX', 'notify_status'),
+ ),
+ ),
+
+ $this->table_prefix . 'groups' => array(
+ 'COLUMNS' => array(
+ 'group_id' => array('UINT', NULL, 'auto_increment'),
+ 'group_type' => array('TINT:4', 1),
+ 'group_founder_manage' => array('BOOL', 0),
+ 'group_name' => array('VCHAR_CI', ''),
+ 'group_desc' => array('TEXT_UNI', ''),
+ 'group_desc_bitfield' => array('VCHAR:255', ''),
+ 'group_desc_options' => array('UINT:11', 7),
+ 'group_desc_uid' => array('VCHAR:8', ''),
+ 'group_display' => array('BOOL', 0),
+ 'group_avatar' => array('VCHAR', ''),
+ 'group_avatar_type' => array('TINT:2', 0),
+ 'group_avatar_width' => array('USINT', 0),
+ 'group_avatar_height' => array('USINT', 0),
+ 'group_rank' => array('UINT', 0),
+ 'group_colour' => array('VCHAR:6', ''),
+ 'group_sig_chars' => array('UINT', 0),
+ 'group_receive_pm' => array('BOOL', 0),
+ 'group_message_limit' => array('UINT', 0),
+ 'group_legend' => array('BOOL', 1),
+ ),
+ 'PRIMARY_KEY' => 'group_id',
+ 'KEYS' => array(
+ 'group_legend' => array('INDEX', 'group_legend'),
+ ),
+ ),
+
+ $this->table_prefix . 'icons' => array(
+ 'COLUMNS' => array(
+ 'icons_id' => array('UINT', NULL, 'auto_increment'),
+ 'icons_url' => array('VCHAR', ''),
+ 'icons_width' => array('TINT:4', 0),
+ 'icons_height' => array('TINT:4', 0),
+ 'icons_order' => array('UINT', 0),
+ 'display_on_posting' => array('BOOL', 1),
+ ),
+ 'PRIMARY_KEY' => 'icons_id',
+ 'KEYS' => array(
+ 'display_on_posting' => array('INDEX', 'display_on_posting'),
+ ),
+ ),
+
+ $this->table_prefix . 'lang' => array(
+ 'COLUMNS' => array(
+ 'lang_id' => array('TINT:4', NULL, 'auto_increment'),
+ 'lang_iso' => array('VCHAR:30', ''),
+ 'lang_dir' => array('VCHAR:30', ''),
+ 'lang_english_name' => array('VCHAR_UNI:100', ''),
+ 'lang_local_name' => array('VCHAR_UNI:255', ''),
+ 'lang_author' => array('VCHAR_UNI:255', ''),
+ ),
+ 'PRIMARY_KEY' => 'lang_id',
+ 'KEYS' => array(
+ 'lang_iso' => array('INDEX', 'lang_iso'),
+ ),
+ ),
+
+ $this->table_prefix . 'log' => array(
+ 'COLUMNS' => array(
+ 'log_id' => array('UINT', NULL, 'auto_increment'),
+ 'log_type' => array('TINT:4', 0),
+ 'user_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ 'reportee_id' => array('UINT', 0),
+ 'log_ip' => array('VCHAR:40', ''),
+ 'log_time' => array('TIMESTAMP', 0),
+ 'log_operation' => array('TEXT_UNI', ''),
+ 'log_data' => array('MTEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'log_id',
+ 'KEYS' => array(
+ 'log_type' => array('INDEX', 'log_type'),
+ 'forum_id' => array('INDEX', 'forum_id'),
+ 'topic_id' => array('INDEX', 'topic_id'),
+ 'reportee_id' => array('INDEX', 'reportee_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'moderator_cache' => array(
+ 'COLUMNS' => array(
+ 'forum_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'username' => array('VCHAR_UNI:255', ''),
+ 'group_id' => array('UINT', 0),
+ 'group_name' => array('VCHAR_UNI', ''),
+ 'display_on_index' => array('BOOL', 1),
+ ),
+ 'KEYS' => array(
+ 'disp_idx' => array('INDEX', 'display_on_index'),
+ 'forum_id' => array('INDEX', 'forum_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'modules' => array(
+ 'COLUMNS' => array(
+ 'module_id' => array('UINT', NULL, 'auto_increment'),
+ 'module_enabled' => array('BOOL', 1),
+ 'module_display' => array('BOOL', 1),
+ 'module_basename' => array('VCHAR', ''),
+ 'module_class' => array('VCHAR:10', ''),
+ 'parent_id' => array('UINT', 0),
+ 'left_id' => array('UINT', 0),
+ 'right_id' => array('UINT', 0),
+ 'module_langname' => array('VCHAR', ''),
+ 'module_mode' => array('VCHAR', ''),
+ 'module_auth' => array('VCHAR', ''),
+ ),
+ 'PRIMARY_KEY' => 'module_id',
+ 'KEYS' => array(
+ 'left_right_id' => array('INDEX', array('left_id', 'right_id')),
+ 'module_enabled' => array('INDEX', 'module_enabled'),
+ 'class_left_id' => array('INDEX', array('module_class', 'left_id')),
+ ),
+ ),
+
+ $this->table_prefix . 'poll_options' => array(
+ 'COLUMNS' => array(
+ 'poll_option_id' => array('TINT:4', 0),
+ 'topic_id' => array('UINT', 0),
+ 'poll_option_text' => array('TEXT_UNI', ''),
+ 'poll_option_total' => array('UINT', 0),
+ ),
+ 'KEYS' => array(
+ 'poll_opt_id' => array('INDEX', 'poll_option_id'),
+ 'topic_id' => array('INDEX', 'topic_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'poll_votes' => array(
+ 'COLUMNS' => array(
+ 'topic_id' => array('UINT', 0),
+ 'poll_option_id' => array('TINT:4', 0),
+ 'vote_user_id' => array('UINT', 0),
+ 'vote_user_ip' => array('VCHAR:40', ''),
+ ),
+ 'KEYS' => array(
+ 'topic_id' => array('INDEX', 'topic_id'),
+ 'vote_user_id' => array('INDEX', 'vote_user_id'),
+ 'vote_user_ip' => array('INDEX', 'vote_user_ip'),
+ ),
+ ),
+
+ $this->table_prefix . 'posts' => array(
+ 'COLUMNS' => array(
+ 'post_id' => array('UINT', NULL, 'auto_increment'),
+ 'topic_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'poster_id' => array('UINT', 0),
+ 'icon_id' => array('UINT', 0),
+ 'poster_ip' => array('VCHAR:40', ''),
+ 'post_time' => array('TIMESTAMP', 0),
+ 'post_approved' => array('BOOL', 1),
+ 'post_reported' => array('BOOL', 0),
+ 'enable_bbcode' => array('BOOL', 1),
+ 'enable_smilies' => array('BOOL', 1),
+ 'enable_magic_url' => array('BOOL', 1),
+ 'enable_sig' => array('BOOL', 1),
+ 'post_username' => array('VCHAR_UNI:255', ''),
+ 'post_subject' => array('XSTEXT_UNI', '', 'true_sort'),
+ 'post_text' => array('MTEXT_UNI', ''),
+ 'post_checksum' => array('VCHAR:32', ''),
+ 'post_attachment' => array('BOOL', 0),
+ 'bbcode_bitfield' => array('VCHAR:255', ''),
+ 'bbcode_uid' => array('VCHAR:8', ''),
+ 'post_postcount' => array('BOOL', 1),
+ 'post_edit_time' => array('TIMESTAMP', 0),
+ 'post_edit_reason' => array('STEXT_UNI', ''),
+ 'post_edit_user' => array('UINT', 0),
+ 'post_edit_count' => array('USINT', 0),
+ 'post_edit_locked' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'post_id',
+ 'KEYS' => array(
+ 'forum_id' => array('INDEX', 'forum_id'),
+ 'topic_id' => array('INDEX', 'topic_id'),
+ 'poster_ip' => array('INDEX', 'poster_ip'),
+ 'poster_id' => array('INDEX', 'poster_id'),
+ 'post_approved' => array('INDEX', 'post_approved'),
+ 'tid_post_time' => array('INDEX', array('topic_id', 'post_time')),
+ ),
+ ),
+
+ $this->table_prefix . 'privmsgs' => array(
+ 'COLUMNS' => array(
+ 'msg_id' => array('UINT', NULL, 'auto_increment'),
+ 'root_level' => array('UINT', 0),
+ 'author_id' => array('UINT', 0),
+ 'icon_id' => array('UINT', 0),
+ 'author_ip' => array('VCHAR:40', ''),
+ 'message_time' => array('TIMESTAMP', 0),
+ 'enable_bbcode' => array('BOOL', 1),
+ 'enable_smilies' => array('BOOL', 1),
+ 'enable_magic_url' => array('BOOL', 1),
+ 'enable_sig' => array('BOOL', 1),
+ 'message_subject' => array('XSTEXT_UNI', ''),
+ 'message_text' => array('MTEXT_UNI', ''),
+ 'message_edit_reason' => array('STEXT_UNI', ''),
+ 'message_edit_user' => array('UINT', 0),
+ 'message_attachment' => array('BOOL', 0),
+ 'bbcode_bitfield' => array('VCHAR:255', ''),
+ 'bbcode_uid' => array('VCHAR:8', ''),
+ 'message_edit_time' => array('TIMESTAMP', 0),
+ 'message_edit_count' => array('USINT', 0),
+ 'to_address' => array('TEXT_UNI', ''),
+ 'bcc_address' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'msg_id',
+ 'KEYS' => array(
+ 'author_ip' => array('INDEX', 'author_ip'),
+ 'message_time' => array('INDEX', 'message_time'),
+ 'author_id' => array('INDEX', 'author_id'),
+ 'root_level' => array('INDEX', 'root_level'),
+ ),
+ ),
+
+ $this->table_prefix . 'privmsgs_folder' => array(
+ 'COLUMNS' => array(
+ 'folder_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'folder_name' => array('VCHAR_UNI', ''),
+ 'pm_count' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'folder_id',
+ 'KEYS' => array(
+ 'user_id' => array('INDEX', 'user_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'privmsgs_rules' => array(
+ 'COLUMNS' => array(
+ 'rule_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'rule_check' => array('UINT', 0),
+ 'rule_connection' => array('UINT', 0),
+ 'rule_string' => array('VCHAR_UNI', ''),
+ 'rule_user_id' => array('UINT', 0),
+ 'rule_group_id' => array('UINT', 0),
+ 'rule_action' => array('UINT', 0),
+ 'rule_folder_id' => array('INT:11', 0),
+ ),
+ 'PRIMARY_KEY' => 'rule_id',
+ 'KEYS' => array(
+ 'user_id' => array('INDEX', 'user_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'privmsgs_to' => array(
+ 'COLUMNS' => array(
+ 'msg_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'author_id' => array('UINT', 0),
+ 'pm_deleted' => array('BOOL', 0),
+ 'pm_new' => array('BOOL', 1),
+ 'pm_unread' => array('BOOL', 1),
+ 'pm_replied' => array('BOOL', 0),
+ 'pm_marked' => array('BOOL', 0),
+ 'pm_forwarded' => array('BOOL', 0),
+ 'folder_id' => array('INT:11', 0),
+ ),
+ 'KEYS' => array(
+ 'msg_id' => array('INDEX', 'msg_id'),
+ 'author_id' => array('INDEX', 'author_id'),
+ 'usr_flder_id' => array('INDEX', array('user_id', 'folder_id')),
+ ),
+ ),
+
+ $this->table_prefix . 'profile_fields' => array(
+ 'COLUMNS' => array(
+ 'field_id' => array('UINT', NULL, 'auto_increment'),
+ 'field_name' => array('VCHAR_UNI', ''),
+ 'field_type' => array('TINT:4', 0),
+ 'field_ident' => array('VCHAR:20', ''),
+ 'field_length' => array('VCHAR:20', ''),
+ 'field_minlen' => array('VCHAR', ''),
+ 'field_maxlen' => array('VCHAR', ''),
+ 'field_novalue' => array('VCHAR_UNI', ''),
+ 'field_default_value' => array('VCHAR_UNI', ''),
+ 'field_validation' => array('VCHAR_UNI:20', ''),
+ 'field_required' => array('BOOL', 0),
+ 'field_show_on_reg' => array('BOOL', 0),
+ 'field_hide' => array('BOOL', 0),
+ 'field_no_view' => array('BOOL', 0),
+ 'field_active' => array('BOOL', 0),
+ 'field_order' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'field_id',
+ 'KEYS' => array(
+ 'fld_type' => array('INDEX', 'field_type'),
+ 'fld_ordr' => array('INDEX', 'field_order'),
+ ),
+ ),
+
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'user_id',
+ ),
+
+ $this->table_prefix . 'profile_fields_lang' => array(
+ 'COLUMNS' => array(
+ 'field_id' => array('UINT', 0),
+ 'lang_id' => array('UINT', 0),
+ 'option_id' => array('UINT', 0),
+ 'field_type' => array('TINT:4', 0),
+ 'lang_value' => array('VCHAR_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => array('field_id', 'lang_id', 'option_id'),
+ ),
+
+ $this->table_prefix . 'profile_lang' => array(
+ 'COLUMNS' => array(
+ 'field_id' => array('UINT', 0),
+ 'lang_id' => array('UINT', 0),
+ 'lang_name' => array('VCHAR_UNI', ''),
+ 'lang_explain' => array('TEXT_UNI', ''),
+ 'lang_default_value' => array('VCHAR_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => array('field_id', 'lang_id'),
+ ),
+
+ $this->table_prefix . 'ranks' => array(
+ 'COLUMNS' => array(
+ 'rank_id' => array('UINT', NULL, 'auto_increment'),
+ 'rank_title' => array('VCHAR_UNI', ''),
+ 'rank_min' => array('UINT', 0),
+ 'rank_special' => array('BOOL', 0),
+ 'rank_image' => array('VCHAR', ''),
+ ),
+ 'PRIMARY_KEY' => 'rank_id',
+ ),
+
+ $this->table_prefix . 'reports' => array(
+ 'COLUMNS' => array(
+ 'report_id' => array('UINT', NULL, 'auto_increment'),
+ 'reason_id' => array('USINT', 0),
+ 'post_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'user_notify' => array('BOOL', 0),
+ 'report_closed' => array('BOOL', 0),
+ 'report_time' => array('TIMESTAMP', 0),
+ 'report_text' => array('MTEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'report_id',
+ ),
+
+ $this->table_prefix . 'reports_reasons' => array(
+ 'COLUMNS' => array(
+ 'reason_id' => array('USINT', NULL, 'auto_increment'),
+ 'reason_title' => array('VCHAR_UNI', ''),
+ 'reason_description' => array('MTEXT_UNI', ''),
+ 'reason_order' => array('USINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'reason_id',
+ ),
+
+ $this->table_prefix . 'search_results' => array(
+ 'COLUMNS' => array(
+ 'search_key' => array('VCHAR:32', ''),
+ 'search_time' => array('TIMESTAMP', 0),
+ 'search_keywords' => array('MTEXT_UNI', ''),
+ 'search_authors' => array('MTEXT', ''),
+ ),
+ 'PRIMARY_KEY' => 'search_key',
+ ),
+
+ $this->table_prefix . 'search_wordlist' => array(
+ 'COLUMNS' => array(
+ 'word_id' => array('UINT', NULL, 'auto_increment'),
+ 'word_text' => array('VCHAR_UNI', ''),
+ 'word_common' => array('BOOL', 0),
+ 'word_count' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'word_id',
+ 'KEYS' => array(
+ 'wrd_txt' => array('UNIQUE', 'word_text'),
+ 'wrd_cnt' => array('INDEX', 'word_count'),
+ ),
+ ),
+
+ $this->table_prefix . 'search_wordmatch' => array(
+ 'COLUMNS' => array(
+ 'post_id' => array('UINT', 0),
+ 'word_id' => array('UINT', 0),
+ 'title_match' => array('BOOL', 0),
+ ),
+ 'KEYS' => array(
+ 'unq_mtch' => array('UNIQUE', array('word_id', 'post_id', 'title_match')),
+ 'word_id' => array('INDEX', 'word_id'),
+ 'post_id' => array('INDEX', 'post_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'sessions' => array(
+ 'COLUMNS' => array(
+ 'session_id' => array('CHAR:32', ''),
+ 'session_user_id' => array('UINT', 0),
+ 'session_last_visit' => array('TIMESTAMP', 0),
+ 'session_start' => array('TIMESTAMP', 0),
+ 'session_time' => array('TIMESTAMP', 0),
+ 'session_ip' => array('VCHAR:40', ''),
+ 'session_browser' => array('VCHAR:150', ''),
+ 'session_forwarded_for' => array('VCHAR:255', ''),
+ 'session_page' => array('VCHAR_UNI', ''),
+ 'session_viewonline' => array('BOOL', 1),
+ 'session_autologin' => array('BOOL', 0),
+ 'session_admin' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'session_id',
+ 'KEYS' => array(
+ 'session_time' => array('INDEX', 'session_time'),
+ 'session_user_id' => array('INDEX', 'session_user_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'sessions_keys' => array(
+ 'COLUMNS' => array(
+ 'key_id' => array('CHAR:32', ''),
+ 'user_id' => array('UINT', 0),
+ 'last_ip' => array('VCHAR:40', ''),
+ 'last_login' => array('TIMESTAMP', 0),
+ ),
+ 'PRIMARY_KEY' => array('key_id', 'user_id'),
+ 'KEYS' => array(
+ 'last_login' => array('INDEX', 'last_login'),
+ ),
+ ),
+
+ $this->table_prefix . 'sitelist' => array(
+ 'COLUMNS' => array(
+ 'site_id' => array('UINT', NULL, 'auto_increment'),
+ 'site_ip' => array('VCHAR:40', ''),
+ 'site_hostname' => array('VCHAR', ''),
+ 'ip_exclude' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'site_id',
+ ),
+
+ $this->table_prefix . 'smilies' => array(
+ 'COLUMNS' => array(
+ 'smiley_id' => array('UINT', NULL, 'auto_increment'),
+// We may want to set 'code' to VCHAR:50 or check if unicode support is possible... at the moment only ASCII characters are allowed.
+ 'code' => array('VCHAR_UNI:50', ''),
+ 'emotion' => array('VCHAR_UNI:50', ''),
+ 'smiley_url' => array('VCHAR:50', ''),
+ 'smiley_width' => array('USINT', 0),
+ 'smiley_height' => array('USINT', 0),
+ 'smiley_order' => array('UINT', 0),
+ 'display_on_posting'=> array('BOOL', 1),
+ ),
+ 'PRIMARY_KEY' => 'smiley_id',
+ 'KEYS' => array(
+ 'display_on_post' => array('INDEX', 'display_on_posting'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles' => array(
+ 'COLUMNS' => array(
+ 'style_id' => array('USINT', NULL, 'auto_increment'),
+ 'style_name' => array('VCHAR_UNI:255', ''),
+ 'style_copyright' => array('VCHAR_UNI', ''),
+ 'style_active' => array('BOOL', 1),
+ 'template_id' => array('USINT', 0),
+ 'theme_id' => array('USINT', 0),
+ 'imageset_id' => array('USINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'style_id',
+ 'KEYS' => array(
+ 'style_name' => array('UNIQUE', 'style_name'),
+ 'template_id' => array('INDEX', 'template_id'),
+ 'theme_id' => array('INDEX', 'theme_id'),
+ 'imageset_id' => array('INDEX', 'imageset_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles_template' => array(
+ 'COLUMNS' => array(
+ 'template_id' => array('USINT', NULL, 'auto_increment'),
+ 'template_name' => array('VCHAR_UNI:255', ''),
+ 'template_copyright' => array('VCHAR_UNI', ''),
+ 'template_path' => array('VCHAR:100', ''),
+ 'bbcode_bitfield' => array('VCHAR:255', 'kNg='),
+ 'template_storedb' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'template_id',
+ 'KEYS' => array(
+ 'tmplte_nm' => array('UNIQUE', 'template_name'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles_template_data' => array(
+ 'COLUMNS' => array(
+ 'template_id' => array('USINT', 0),
+ 'template_filename' => array('VCHAR:100', ''),
+ 'template_included' => array('TEXT', ''),
+ 'template_mtime' => array('TIMESTAMP', 0),
+ 'template_data' => array('MTEXT_UNI', ''),
+ ),
+ 'KEYS' => array(
+ 'tid' => array('INDEX', 'template_id'),
+ 'tfn' => array('INDEX', 'template_filename'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles_theme' => array(
+ 'COLUMNS' => array(
+ 'theme_id' => array('USINT', NULL, 'auto_increment'),
+ 'theme_name' => array('VCHAR_UNI:255', ''),
+ 'theme_copyright' => array('VCHAR_UNI', ''),
+ 'theme_path' => array('VCHAR:100', ''),
+ 'theme_storedb' => array('BOOL', 0),
+ 'theme_mtime' => array('TIMESTAMP', 0),
+ 'theme_data' => array('MTEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'theme_id',
+ 'KEYS' => array(
+ 'theme_name' => array('UNIQUE', 'theme_name'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles_imageset' => array(
+ 'COLUMNS' => array(
+ 'imageset_id' => array('USINT', NULL, 'auto_increment'),
+ 'imageset_name' => array('VCHAR_UNI:255', ''),
+ 'imageset_copyright' => array('VCHAR_UNI', ''),
+ 'imageset_path' => array('VCHAR:100', ''),
+ ),
+ 'PRIMARY_KEY' => 'imageset_id',
+ 'KEYS' => array(
+ 'imgset_nm' => array('UNIQUE', 'imageset_name'),
+ ),
+ ),
+
+ $this->table_prefix . 'styles_imageset_data' => array(
+ 'COLUMNS' => array(
+ 'image_id' => array('USINT', NULL, 'auto_increment'),
+ 'image_name' => array('VCHAR:200', ''),
+ 'image_filename' => array('VCHAR:200', ''),
+ 'image_lang' => array('VCHAR:30', ''),
+ 'image_height' => array('USINT', 0),
+ 'image_width' => array('USINT', 0),
+ 'imageset_id' => array('USINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'image_id',
+ 'KEYS' => array(
+ 'i_d' => array('INDEX', 'imageset_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'topics' => array(
+ 'COLUMNS' => array(
+ 'topic_id' => array('UINT', NULL, 'auto_increment'),
+ 'forum_id' => array('UINT', 0),
+ 'icon_id' => array('UINT', 0),
+ 'topic_attachment' => array('BOOL', 0),
+ 'topic_approved' => array('BOOL', 1),
+ 'topic_reported' => array('BOOL', 0),
+ 'topic_title' => array('XSTEXT_UNI', '', 'true_sort'),
+ 'topic_poster' => array('UINT', 0),
+ 'topic_time' => array('TIMESTAMP', 0),
+ 'topic_time_limit' => array('TIMESTAMP', 0),
+ 'topic_views' => array('UINT', 0),
+ 'topic_replies' => array('UINT', 0),
+ 'topic_replies_real' => array('UINT', 0),
+ 'topic_status' => array('TINT:3', 0),
+ 'topic_type' => array('TINT:3', 0),
+ 'topic_first_post_id' => array('UINT', 0),
+ 'topic_first_poster_name' => array('VCHAR_UNI', ''),
+ 'topic_first_poster_colour' => array('VCHAR:6', ''),
+ 'topic_last_post_id' => array('UINT', 0),
+ 'topic_last_poster_id' => array('UINT', 0),
+ 'topic_last_poster_name' => array('VCHAR_UNI', ''),
+ 'topic_last_poster_colour' => array('VCHAR:6', ''),
+ 'topic_last_post_subject' => array('XSTEXT_UNI', ''),
+ 'topic_last_post_time' => array('TIMESTAMP', 0),
+ 'topic_last_view_time' => array('TIMESTAMP', 0),
+ 'topic_moved_id' => array('UINT', 0),
+ 'topic_bumped' => array('BOOL', 0),
+ 'topic_bumper' => array('UINT', 0),
+ 'poll_title' => array('STEXT_UNI', ''),
+ 'poll_start' => array('TIMESTAMP', 0),
+ 'poll_length' => array('TIMESTAMP', 0),
+ 'poll_max_options' => array('TINT:4', 1),
+ 'poll_last_vote' => array('TIMESTAMP', 0),
+ 'poll_vote_change' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => 'topic_id',
+ 'KEYS' => array(
+ 'forum_id' => array('INDEX', 'forum_id'),
+ 'forum_id_type' => array('INDEX', array('forum_id', 'topic_type')),
+ 'last_post_time' => array('INDEX', 'topic_last_post_time'),
+ 'topic_approved' => array('INDEX', 'topic_approved'),
+ 'forum_appr_last' => array('INDEX', array('forum_id', 'topic_approved', 'topic_last_post_id')),
+ 'fid_time_moved' => array('INDEX', array('forum_id', 'topic_last_post_time', 'topic_moved_id')),
+ ),
+ ),
+
+ $this->table_prefix . 'topics_track' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ 'forum_id' => array('UINT', 0),
+ 'mark_time' => array('TIMESTAMP', 0),
+ ),
+ 'PRIMARY_KEY' => array('user_id', 'topic_id'),
+ 'KEYS' => array(
+ 'forum_id' => array('INDEX', 'forum_id'),
+ ),
+ ),
+
+ $this->table_prefix . 'topics_posted' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ 'topic_posted' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => array('user_id', 'topic_id'),
+ ),
+
+ $this->table_prefix . 'topics_watch' => array(
+ 'COLUMNS' => array(
+ 'topic_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'notify_status' => array('BOOL', 0),
+ ),
+ 'KEYS' => array(
+ 'topic_id' => array('INDEX', 'topic_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ 'notify_stat' => array('INDEX', 'notify_status'),
+ ),
+ ),
+
+ $this->table_prefix . 'user_group' => array(
+ 'COLUMNS' => array(
+ 'group_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'group_leader' => array('BOOL', 0),
+ 'user_pending' => array('BOOL', 1),
+ ),
+ 'KEYS' => array(
+ 'group_id' => array('INDEX', 'group_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ 'group_leader' => array('INDEX', 'group_leader'),
+ ),
+ ),
+
+ $this->table_prefix . 'users' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_type' => array('TINT:2', 0),
+ 'group_id' => array('UINT', 3),
+ 'user_permissions' => array('MTEXT', ''),
+ 'user_perm_from' => array('UINT', 0),
+ 'user_ip' => array('VCHAR:40', ''),
+ 'user_regdate' => array('TIMESTAMP', 0),
+ 'username' => array('VCHAR_CI', ''),
+ 'username_clean' => array('VCHAR_CI', ''),
+ 'user_password' => array('VCHAR_UNI:40', ''),
+ 'user_passchg' => array('TIMESTAMP', 0),
+ 'user_pass_convert' => array('BOOL', 0),
+ 'user_email' => array('VCHAR_UNI:100', ''),
+ 'user_email_hash' => array('BINT', 0),
+ 'user_birthday' => array('VCHAR:10', ''),
+ 'user_lastvisit' => array('TIMESTAMP', 0),
+ 'user_lastmark' => array('TIMESTAMP', 0),
+ 'user_lastpost_time' => array('TIMESTAMP', 0),
+ 'user_lastpage' => array('VCHAR_UNI:200', ''),
+ 'user_last_confirm_key' => array('VCHAR:10', ''),
+ 'user_last_search' => array('TIMESTAMP', 0),
+ 'user_warnings' => array('TINT:4', 0),
+ 'user_last_warning' => array('TIMESTAMP', 0),
+ 'user_login_attempts' => array('TINT:4', 0),
+ 'user_inactive_reason' => array('TINT:2', 0),
+ 'user_inactive_time' => array('TIMESTAMP', 0),
+ 'user_posts' => array('UINT', 0),
+ 'user_lang' => array('VCHAR:30', ''),
+ 'user_timezone' => array('DECIMAL', 0),
+ 'user_dst' => array('BOOL', 0),
+ 'user_dateformat' => array('VCHAR_UNI:30', 'd M Y H:i'),
+ 'user_style' => array('USINT', 0),
+ 'user_rank' => array('UINT', 0),
+ 'user_colour' => array('VCHAR:6', ''),
+ 'user_new_privmsg' => array('INT:4', 0),
+ 'user_unread_privmsg' => array('INT:4', 0),
+ 'user_last_privmsg' => array('TIMESTAMP', 0),
+ 'user_message_rules' => array('BOOL', 0),
+ 'user_full_folder' => array('INT:11', -3),
+ 'user_emailtime' => array('TIMESTAMP', 0),
+ 'user_topic_show_days' => array('USINT', 0),
+ 'user_topic_sortby_type' => array('VCHAR:1', 't'),
+ 'user_topic_sortby_dir' => array('VCHAR:1', 'd'),
+ 'user_post_show_days' => array('USINT', 0),
+ 'user_post_sortby_type' => array('VCHAR:1', 't'),
+ 'user_post_sortby_dir' => array('VCHAR:1', 'a'),
+ 'user_notify' => array('BOOL', 0),
+ 'user_notify_pm' => array('BOOL', 1),
+ 'user_notify_type' => array('TINT:4', 0),
+ 'user_allow_pm' => array('BOOL', 1),
+ 'user_allow_viewonline' => array('BOOL', 1),
+ 'user_allow_viewemail' => array('BOOL', 1),
+ 'user_allow_massemail' => array('BOOL', 1),
+ 'user_options' => array('UINT:11', 895),
+ 'user_avatar' => array('VCHAR', ''),
+ 'user_avatar_type' => array('TINT:2', 0),
+ 'user_avatar_width' => array('USINT', 0),
+ 'user_avatar_height' => array('USINT', 0),
+ 'user_sig' => array('MTEXT_UNI', ''),
+ 'user_sig_bbcode_uid' => array('VCHAR:8', ''),
+ 'user_sig_bbcode_bitfield' => array('VCHAR:255', ''),
+ 'user_from' => array('VCHAR_UNI:100', ''),
+ 'user_icq' => array('VCHAR:15', ''),
+ 'user_aim' => array('VCHAR_UNI', ''),
+ 'user_yim' => array('VCHAR_UNI', ''),
+ 'user_msnm' => array('VCHAR_UNI', ''),
+ 'user_jabber' => array('VCHAR_UNI', ''),
+ 'user_website' => array('VCHAR_UNI:200', ''),
+ 'user_occ' => array('TEXT_UNI', ''),
+ 'user_interests' => array('TEXT_UNI', ''),
+ 'user_actkey' => array('VCHAR:32', ''),
+ 'user_newpasswd' => array('VCHAR_UNI:40', ''),
+ 'user_form_salt' => array('VCHAR_UNI:32', ''),
+
+ ),
+ 'PRIMARY_KEY' => 'user_id',
+ 'KEYS' => array(
+ 'user_birthday' => array('INDEX', 'user_birthday'),
+ 'user_email_hash' => array('INDEX', 'user_email_hash'),
+ 'user_type' => array('INDEX', 'user_type'),
+ 'username_clean' => array('UNIQUE', 'username_clean'),
+ ),
+ ),
+
+ $this->table_prefix . 'warnings' => array(
+ 'COLUMNS' => array(
+ 'warning_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'post_id' => array('UINT', 0),
+ 'log_id' => array('UINT', 0),
+ 'warning_time' => array('TIMESTAMP', 0),
+ ),
+ 'PRIMARY_KEY' => 'warning_id',
+ ),
+
+ $this->table_prefix . 'words' => array(
+ 'COLUMNS' => array(
+ 'word_id' => array('UINT', NULL, 'auto_increment'),
+ 'word' => array('VCHAR_UNI', ''),
+ 'replacement' => array('VCHAR_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'word_id',
+ ),
+
+ $this->table_prefix . 'zebra' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'zebra_id' => array('UINT', 0),
+ 'friend' => array('BOOL', 0),
+ 'foe' => array('BOOL', 0),
+ ),
+ 'PRIMARY_KEY' => array('user_id', 'zebra_id'),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'attachments',
+ $this->table_prefix . 'acl_groups',
+ $this->table_prefix . 'acl_options',
+ $this->table_prefix . 'acl_roles',
+ $this->table_prefix . 'acl_roles_data',
+ $this->table_prefix . 'acl_users',
+ $this->table_prefix . 'banlist',
+ $this->table_prefix . 'bbcodes',
+ $this->table_prefix . 'bookmarks',
+ $this->table_prefix . 'bots',
+ $this->table_prefix . 'config',
+ $this->table_prefix . 'confirm',
+ $this->table_prefix . 'disallow',
+ $this->table_prefix . 'drafts',
+ $this->table_prefix . 'extensions',
+ $this->table_prefix . 'extension_groups',
+ $this->table_prefix . 'forums',
+ $this->table_prefix . 'forums_access',
+ $this->table_prefix . 'forums_track',
+ $this->table_prefix . 'forums_watch',
+ $this->table_prefix . 'groups',
+ $this->table_prefix . 'icons',
+ $this->table_prefix . 'lang',
+ $this->table_prefix . 'log',
+ $this->table_prefix . 'moderator_cache',
+ $this->table_prefix . 'modules',
+ $this->table_prefix . 'poll_options',
+ $this->table_prefix . 'poll_votes',
+ $this->table_prefix . 'posts',
+ $this->table_prefix . 'privmsgs',
+ $this->table_prefix . 'privmsgs_folder',
+ $this->table_prefix . 'privmsgs_rules',
+ $this->table_prefix . 'privmsgs_to',
+ $this->table_prefix . 'profile_fields',
+ $this->table_prefix . 'profile_fields_data',
+ $this->table_prefix . 'profile_fields_lang',
+ $this->table_prefix . 'profile_lang',
+ $this->table_prefix . 'ranks',
+ $this->table_prefix . 'reports',
+ $this->table_prefix . 'reports_reasons',
+ $this->table_prefix . 'search_results',
+ $this->table_prefix . 'search_wordlist',
+ $this->table_prefix . 'search_wordmatch',
+ $this->table_prefix . 'sessions',
+ $this->table_prefix . 'sessions_keys',
+ $this->table_prefix . 'sitelist',
+ $this->table_prefix . 'smilies',
+ $this->table_prefix . 'styles',
+ $this->table_prefix . 'styles_template',
+ $this->table_prefix . 'styles_template_data',
+ $this->table_prefix . 'styles_theme',
+ $this->table_prefix . 'styles_imageset',
+ $this->table_prefix . 'styles_imageset_data',
+ $this->table_prefix . 'topics',
+ $this->table_prefix . 'topics_track',
+ $this->table_prefix . 'topics_posted',
+ $this->table_prefix . 'topics_watch',
+ $this->table_prefix . 'user_group',
+ $this->table_prefix . 'users',
+ $this->table_prefix . 'warnings',
+ $this->table_prefix . 'words',
+ $this->table_prefix . 'zebra',
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php
index aed0f2784b..2b65bb0185 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php
index 305309c3bd..d6f3029f7e 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php
index fb50d67fb5..0ee2a46a00 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php
index 63ba1e8fc2..e676571a15 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php
index 7055063032..d2656397a2 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_10_rc3.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php
index 1246597efb..6b7c9735fa 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php
index 7e284235e1..91ffae2f05 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php
index 017038855d..55290dcbcf 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_11_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php
index 5a2d569724..c4bf3a30ef 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php
index 35a3015959..ab8463cc73 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php
index 3edb578fc8..f41f20954a 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php
index 510693a5b7..9171ceb26f 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_12_rc3.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php
index 862276528d..724a61ecce 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_1_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -16,6 +16,11 @@ class release_3_0_1_rc1 extends \phpbb\db\migration\migration
return phpbb_version_compare($this->config['version'], '3.0.1-RC1', '>=');
}
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v30x\release_3_0_0');
+ }
+
public function update_schema()
{
return array(
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php
index 7e2a08590e..53792d4ce1 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php
index 7a856383e2..691ad44406 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php
index 61562575eb..26fa4f015b 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_2_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php
index b2adbeaa43..5374e8786a 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php
index 57bd59bba3..367bf2c806 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_3_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
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 5d6140393b..94bba00079 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
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php
index a8af4dd76c..98aafc6d43 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php
index 7bbe7ffed9..92555adf78 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
index ffe2c6a44d..c6b77bc379 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php
index 04b14b5189..b56721bd80 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1part2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php
index 85ea2e9d20..fb0957fc45 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php
index 87d5e490f8..12b0122237 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php
index 7a0ef28601..351079e96c 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php
index 73a1fe9e6a..1ccfa1cb37 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc3.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php
index b6e5be2c2f..6451f4fe02 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc4.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php
index 2b0da30bc6..70cb1293e6 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php
index 3547ee77e1..db2175a99a 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_pl1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
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 de4d772808..3bdedf8c57 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
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php
index 800803a753..65ad905aa7 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_7_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php
index 6c8b1df6fc..c1e49f1dde 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php
index 1a14e5c961..e3c232f9e4 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php
index 9af2fce971..34e85f010a 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
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 3fb790bc0d..79ef839005 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
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php
index cd79d24ade..1eb7837faf 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php
index 7e59b8f9e8..bbeb76509f 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc3.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php
index e71d9defa6..bc75891f4d 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc4.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php
new file mode 100644
index 0000000000..aa44222cd8
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php
@@ -0,0 +1,77 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class acp_prune_users_module extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ $sql = 'SELECT module_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_class = 'acp'
+ AND module_langname = 'ACP_CAT_USERS'";
+ $result = $this->db->sql_query($sql);
+ $acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id');
+ $this->db->sql_freeresult($result);
+
+ $sql = 'SELECT parent_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_class = 'acp'
+ AND module_basename = 'acp_prune'
+ AND module_mode = 'users'";
+ $result = $this->db->sql_query($sql);
+ $acp_prune_users_parent = (int) $this->db->sql_fetchfield('parent_id');
+ $this->db->sql_freeresult($result);
+
+ // Skip migration if "Users" category has been deleted
+ // or the module has already been moved to that category
+ return !$acp_cat_users_id || $acp_cat_users_id === $acp_prune_users_parent;
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\beta1');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'move_prune_users_module'))),
+ );
+ }
+
+ public function move_prune_users_module()
+ {
+ $sql = 'SELECT module_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_class = 'acp'
+ AND module_basename = 'acp_prune'
+ AND module_mode = 'users'";
+ $result = $this->db->sql_query($sql);
+ $acp_prune_users_id = (int) $this->db->sql_fetchfield('module_id');
+ $this->db->sql_freeresult($result);
+
+ $sql = 'SELECT module_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_class = 'acp'
+ AND module_langname = 'ACP_CAT_USERS'";
+ $result = $this->db->sql_query($sql);
+ $acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id');
+ $this->db->sql_freeresult($result);
+
+ if (!class_exists('\acp_modules'))
+ {
+ include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
+ }
+ $module_manager = new \acp_modules();
+ $module_manager->module_class = 'acp';
+ $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id);
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/allow_cdn.php b/phpBB/phpbb/db/migration/data/v310/allow_cdn.php
index aa471df6e7..2cb9e58767 100644
--- a/phpBB/phpbb/db/migration/data/v310/allow_cdn.php
+++ b/phpBB/phpbb/db/migration/data/v310/allow_cdn.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/alpha1.php b/phpBB/phpbb/db/migration/data/v310/alpha1.php
index 403e301e64..704f5a7a29 100644
--- a/phpBB/phpbb/db/migration/data/v310/alpha1.php
+++ b/phpBB/phpbb/db/migration/data/v310/alpha1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/alpha3.php b/phpBB/phpbb/db/migration/data/v310/alpha3.php
new file mode 100644
index 0000000000..4bd2231bb9
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/alpha3.php
@@ -0,0 +1,30 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class alpha3 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\alpha2',
+ '\phpbb\db\migration\data\v310\avatar_types',
+ '\phpbb\db\migration\data\v310\passwords',
+ '\phpbb\db\migration\data\v310\profilefield_types',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.0-a3')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php
index 971a7e8504..daca99c255 100644
--- a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php
+++ b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php
new file mode 100644
index 0000000000..692647dcde
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth2.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class auth_provider_oauth2 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\auth_provider_oauth',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(
+ array($this, 'update_auth_link_module_auth'),
+ )),
+ );
+ }
+
+ public function update_auth_link_module_auth()
+ {
+ $sql = 'UPDATE ' . MODULES_TABLE . "
+ SET module_auth = 'authmethod_oauth'
+ WHERE module_class = 'ucp'
+ AND module_basename = 'ucp_auth_link'
+ AND module_mode = 'auth_link'
+ AND module_auth = ''";
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/avatar_types.php b/phpBB/phpbb/db/migration/data/v310/avatar_types.php
index bdbdccf0c5..17bb1f26ca 100644
--- a/phpBB/phpbb/db/migration/data/v310/avatar_types.php
+++ b/phpBB/phpbb/db/migration/data/v310/avatar_types.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/avatars.php b/phpBB/phpbb/db/migration/data/v310/avatars.php
index 80ce606f29..b6cd914dd9 100644
--- a/phpBB/phpbb/db/migration/data/v310/avatars.php
+++ b/phpBB/phpbb/db/migration/data/v310/avatars.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/beta1.php b/phpBB/phpbb/db/migration/data/v310/beta1.php
new file mode 100644
index 0000000000..36d0c62b6f
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/beta1.php
@@ -0,0 +1,33 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class beta1 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\alpha3',
+ '\phpbb\db\migration\data\v310\passwords_p2',
+ '\phpbb\db\migration\data\v310\postgres_fulltext_drop',
+ '\phpbb\db\migration\data\v310\profilefield_change_load_settings',
+ '\phpbb\db\migration\data\v310\profilefield_location',
+ '\phpbb\db\migration\data\v310\soft_delete_mod_convert2',
+ '\phpbb\db\migration\data\v310\ucp_popuppm_module',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.0-b1')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/beta2.php b/phpBB/phpbb/db/migration/data/v310/beta2.php
new file mode 100644
index 0000000000..4cf29dfb3d
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/beta2.php
@@ -0,0 +1,29 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class beta2 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\beta1',
+ '\phpbb\db\migration\data\v310\acp_prune_users_module',
+ '\phpbb\db\migration\data\v310\profilefield_location_cleanup',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.1.0-b2')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/board_contact_name.php b/phpBB/phpbb/db/migration/data/v310/board_contact_name.php
new file mode 100644
index 0000000000..37b4d50545
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/board_contact_name.php
@@ -0,0 +1,30 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class board_contact_name extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return isset($this->config['board_contact_name']);
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\beta2');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('board_contact_name', '')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/boardindex.php b/phpBB/phpbb/db/migration/data/v310/boardindex.php
index 27492f2d0d..17040a60b8 100644
--- a/phpBB/phpbb/db/migration/data/v310/boardindex.php
+++ b/phpBB/phpbb/db/migration/data/v310/boardindex.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/config_db_text.php b/phpBB/phpbb/db/migration/data/v310/config_db_text.php
index 1a7ee7a9a6..49f30d289f 100644
--- a/phpBB/phpbb/db/migration/data/v310/config_db_text.php
+++ b/phpBB/phpbb/db/migration/data/v310/config_db_text.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/dev.php b/phpBB/phpbb/db/migration/data/v310/dev.php
index c1db883616..da78db7b89 100644
--- a/phpBB/phpbb/db/migration/data/v310/dev.php
+++ b/phpBB/phpbb/db/migration/data/v310/dev.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -23,6 +23,7 @@ class dev extends \phpbb\db\migration\migration
'\phpbb\db\migration\data\v310\style_update_p2',
'\phpbb\db\migration\data\v310\timezone_p2',
'\phpbb\db\migration\data\v310\reported_posts_display',
+ '\phpbb\db\migration\data\v310\migrations_table',
);
}
diff --git a/phpBB/phpbb/db/migration/data/v310/extensions.php b/phpBB/phpbb/db/migration/data/v310/extensions.php
index d8b38dbc9e..a0d57087d4 100644
--- a/phpBB/phpbb/db/migration/data/v310/extensions.php
+++ b/phpBB/phpbb/db/migration/data/v310/extensions.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/forgot_password.php b/phpBB/phpbb/db/migration/data/v310/forgot_password.php
index 814093caa9..523f4e2c0a 100644
--- a/phpBB/phpbb/db/migration/data/v310/forgot_password.php
+++ b/phpBB/phpbb/db/migration/data/v310/forgot_password.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/jquery_update.php b/phpBB/phpbb/db/migration/data/v310/jquery_update.php
index bd2de2b4d4..187d6b876a 100644
--- a/phpBB/phpbb/db/migration/data/v310/jquery_update.php
+++ b/phpBB/phpbb/db/migration/data/v310/jquery_update.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/jquery_update2.php b/phpBB/phpbb/db/migration/data/v310/jquery_update2.php
new file mode 100644
index 0000000000..46a115d8ad
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/jquery_update2.php
@@ -0,0 +1,33 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class jquery_update2 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js';
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\jquery_update',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js')),
+ );
+ }
+
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/migrations_table.php b/phpBB/phpbb/db/migration/data/v310/migrations_table.php
new file mode 100644
index 0000000000..e70fd35819
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/migrations_table.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class migrations_table extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_table_exists($this->table_prefix . 'migrations');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_tables' => array(
+ $this->table_prefix . 'migrations' => array(
+ 'COLUMNS' => array(
+ 'migration_name' => array('VCHAR', ''),
+ 'migration_depends_on' => array('TEXT', ''),
+ 'migration_schema_done' => array('BOOL', 0),
+ 'migration_data_done' => array('BOOL', 0),
+ 'migration_data_state' => array('TEXT', ''),
+ 'migration_start_time' => array('TIMESTAMP', 0),
+ 'migration_end_time' => array('TIMESTAMP', 0),
+ ),
+ 'PRIMARY_KEY' => 'migration_name',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'migrations',
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php b/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php
index ffb790b135..e7d71f63e3 100644
--- a/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php
+++ b/phpBB/phpbb/db/migration/data/v310/mod_rewrite.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/namespaces.php b/phpBB/phpbb/db/migration/data/v310/namespaces.php
index f74ecbd874..aa0b2bbfac 100644
--- a/phpBB/phpbb/db/migration/data/v310/namespaces.php
+++ b/phpBB/phpbb/db/migration/data/v310/namespaces.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/notifications.php b/phpBB/phpbb/db/migration/data/v310/notifications.php
index 61be25bb5f..cf26436ccb 100644
--- a/phpBB/phpbb/db/migration/data/v310/notifications.php
+++ b/phpBB/phpbb/db/migration/data/v310/notifications.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php b/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php
index eb2eb361ee..a9d11d384c 100644
--- a/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php
+++ b/phpBB/phpbb/db/migration/data/v310/notifications_schema_fix.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/passwords.php b/phpBB/phpbb/db/migration/data/v310/passwords.php
new file mode 100644
index 0000000000..2bba9b7a70
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/passwords.php
@@ -0,0 +1,46 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class passwords extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v30x\release_3_0_11');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_password' => array('VCHAR:255', ''),
+ ),
+ $this->table_prefix . 'forums' => array(
+ 'forum_password' => array('VCHAR:255', ''),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_password' => array('VCHAR:40', ''),
+ ),
+ $this->table_prefix . 'forums' => array(
+ 'forum_password' => array('VCHAR:40', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_p2.php b/phpBB/phpbb/db/migration/data/v310/passwords_p2.php
new file mode 100644
index 0000000000..2768c8975d
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/passwords_p2.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class passwords_p2 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\passwords');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_newpasswd' => array('VCHAR:255', ''),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_newpasswd' => array('VCHAR:40', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php
new file mode 100644
index 0000000000..7d4aea3c95
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class postgres_fulltext_drop extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ // This migration is irrelevant for all non-PostgreSQL DBMSes.
+ return strpos($this->db->sql_layer, 'postgres') === false;
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\dev',
+ );
+ }
+
+ public function update_schema()
+ {
+ /*
+ * Drop FULLTEXT indexes related to PostgreSQL fulltext search.
+ * Doing so is equivalent to dropping the search index from the ACP.
+ * Possibly time-consuming recreation of the search index (i.e.
+ * FULLTEXT indexes) is left as a task to the admin to not
+ * unnecessarily stall the upgrade process. The new search index will
+ * then require about 40% less table space (also see PHPBB3-11040).
+ */
+ return array(
+ 'drop_keys' => array(
+ $this->table_prefix . 'posts' => array(
+ 'post_subject',
+ 'post_text',
+ 'post_content',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php b/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php
new file mode 100644
index 0000000000..87574cb858
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_aol.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_aol extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_yahoo_cleanup',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_aol';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_aol',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_aol',
+ 'field_length' => '40',
+ 'field_minlen' => '5',
+ 'field_maxlen' => '255',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_on_ml' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => '',
+ 'field_contact_url' => '',
+ );
+
+ protected $user_column_name = 'user_aim';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php
new file mode 100644
index 0000000000..a7088c6a7a
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_aol_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_aol_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_aim');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_aol',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_aim',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_aim' => array('VCHAR_UNI', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php b/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php
new file mode 100644
index 0000000000..7d09d8149a
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_change_load_settings.php
@@ -0,0 +1,30 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_change_load_settings extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_aol_cleanup',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('load_cpf_memberlist', '1')),
+ array('config.update', array('load_cpf_pm', '1')),
+ array('config.update', array('load_cpf_viewprofile', '1')),
+ array('config.update', array('load_cpf_viewtopic', '1')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php
new file mode 100644
index 0000000000..625e74fba1
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_cleanup.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_occ') &&
+ !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_interests');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_interests',
+ '\phpbb\db\migration\data\v310\profilefield_occupation',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_occ',
+ 'user_interests',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_occ' => array('MTEXT', ''),
+ 'user_interests' => array('MTEXT', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php b/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php
new file mode 100644
index 0000000000..c7617813eb
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_contact_field.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_contact_field extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_is_contact');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_on_memberlist',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_is_contact' => array('BOOL', 0),
+ 'field_contact_desc' => array('VCHAR', ''),
+ 'field_contact_url' => array('VCHAR', ''),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_is_contact',
+ 'field_contact_desc',
+ 'field_contact_url',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php b/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php
new file mode 100644
index 0000000000..2c8c8c511f
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_icq.php
@@ -0,0 +1,50 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_icq extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_contact_field',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_icq';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_icq',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_icq',
+ 'field_length' => '20',
+ 'field_minlen' => '3',
+ 'field_maxlen' => '15',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '[0-9]+',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => 'SEND_ICQ_MESSAGE',
+ 'field_contact_url' => 'https://www.icq.com/people/%s/',
+ );
+
+ protected $user_column_name = 'user_icq';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php
new file mode 100644
index 0000000000..0129a7248f
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_icq_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_icq_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_icq');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_icq',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_icq',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_icq' => array('VCHAR:20', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php b/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php
new file mode 100644
index 0000000000..53fae2ea1a
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_interests.php
@@ -0,0 +1,48 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_interests extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_types',
+ '\phpbb\db\migration\data\v310\profilefield_show_novalue',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_interests';
+
+ protected $profilefield_database_type = array('MTEXT', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_interests',
+ 'field_type' => 'profilefields.type.text',
+ 'field_ident' => 'phpbb_interests',
+ 'field_length' => '3|30',
+ 'field_minlen' => '2',
+ 'field_maxlen' => '500',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 0,
+ 'field_show_on_vt' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ );
+
+ protected $user_column_name = 'user_interests';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_location.php b/phpBB/phpbb/db/migration/data/v310/profilefield_location.php
new file mode 100644
index 0000000000..f4db79ca5e
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_location.php
@@ -0,0 +1,48 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_location extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_types',
+ '\phpbb\db\migration\data\v310\profilefield_on_memberlist',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_location';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_location',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_location',
+ 'field_length' => '20',
+ 'field_minlen' => '2',
+ 'field_maxlen' => '100',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ );
+
+ protected $user_column_name = 'user_from';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php
new file mode 100644
index 0000000000..54ff2a31eb
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_location_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_location_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_from');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_location',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_from',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_from' => array('VCHAR_UNI:100', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php b/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php
new file mode 100644
index 0000000000..9a710fbcbc
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_occupation.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_occupation extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_interests',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_occupation';
+
+ protected $profilefield_database_type = array('MTEXT', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_occupation',
+ 'field_type' => 'profilefields.type.text',
+ 'field_ident' => 'phpbb_occupation',
+ 'field_length' => '3|30',
+ 'field_minlen' => '2',
+ 'field_maxlen' => '500',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 0,
+ 'field_show_on_vt' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ );
+
+ protected $user_column_name = 'user_occ';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php b/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php
new file mode 100644
index 0000000000..4733b7713d
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_on_memberlist.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_on_memberlist extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_show_on_ml');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_cleanup',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_show_on_ml' => array('BOOL', 0),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_show_on_ml',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php b/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php
new file mode 100644
index 0000000000..d37103e2ce
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_show_novalue.php
@@ -0,0 +1,45 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_show_novalue extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields', 'field_show_novalue');
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\profilefield_types');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_show_novalue' => array('BOOL', 0),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_show_novalue',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_types.php b/phpBB/phpbb/db/migration/data/v310/profilefield_types.php
new file mode 100644
index 0000000000..9b54d87c9a
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_types.php
@@ -0,0 +1,106 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_types extends \phpbb\db\migration\migration
+{
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\alpha2',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'profile_fields' => array(
+ 'field_type' => array('VCHAR:100', ''),
+ ),
+ $this->table_prefix . 'profile_fields_lang' => array(
+ 'field_type' => array('VCHAR:100', ''),
+ ),
+ ),
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'update_profile_fields_type'))),
+ array('custom', array(array($this, 'update_profile_fields_lang_type'))),
+ );
+ }
+
+ public function update_profile_fields_type()
+ {
+ // Update profile field types
+ $sql = 'SELECT field_type
+ FROM ' . $this->table_prefix . 'profile_fields
+ GROUP BY field_type';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $sql = 'UPDATE ' . $this->table_prefix . "profile_fields
+ SET field_type = '" . $this->db->sql_escape($this->convert_phpbb30_field_type($row['field_type'])) . "'
+ WHERE field_type = '" . $this->db->sql_escape($row['field_type']) . "'";
+ $this->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ public function update_profile_fields_lang_type()
+ {
+ // Update profile field language types
+ $sql = 'SELECT field_type
+ FROM ' . $this->table_prefix . 'profile_fields_lang
+ GROUP BY field_type';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $sql = 'UPDATE ' . $this->table_prefix . "profile_fields_lang
+ SET field_type = '" . $this->db->sql_escape($this->convert_phpbb30_field_type($row['field_type'])) . "'
+ WHERE field_type = '" . $this->db->sql_escape($row['field_type']) . "'";
+ $this->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Determine the new field type for a given phpBB 3.0 field type
+ *
+ * @param $field_type string Field type in 3.0
+ * @return string Field new type which is used since 3.1
+ */
+ public function convert_phpbb30_field_type($field_type)
+ {
+ switch ($field_type)
+ {
+ case FIELD_INT:
+ return 'profilefields.type.int';
+ case FIELD_STRING:
+ return 'profilefields.type.string';
+ case FIELD_TEXT:
+ return 'profilefields.type.text';
+ case FIELD_BOOL:
+ return 'profilefields.type.bool';
+ case FIELD_DROPDOWN:
+ return 'profilefields.type.dropdown';
+ case FIELD_DATE:
+ return 'profilefields.type.date';
+ default:
+ return $field_type;
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_website.php b/phpBB/phpbb/db/migration/data/v310/profilefield_website.php
new file mode 100644
index 0000000000..818b66d2e4
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_website.php
@@ -0,0 +1,52 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_website extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_on_memberlist',
+ '\phpbb\db\migration\data\v310\profilefield_icq_cleanup',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_website';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_website',
+ 'field_type' => 'profilefields.type.url',
+ 'field_ident' => 'phpbb_website',
+ 'field_length' => '40',
+ 'field_minlen' => '12',
+ 'field_maxlen' => '255',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_on_ml' => 1,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => 'VISIT_WEBSITE',
+ 'field_contact_url' => '%s',
+ );
+
+ protected $user_column_name = 'user_website';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php
new file mode 100644
index 0000000000..35cc92199e
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_website_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_website_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_website');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_website',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_website',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_website' => array('VCHAR_UNI:200', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php
new file mode 100644
index 0000000000..8a42f1fea1
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_wlm extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_website_cleanup',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_wlm';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_wlm',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_wlm',
+ 'field_length' => '40',
+ 'field_minlen' => '5',
+ 'field_maxlen' => '255',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_on_ml' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => '',
+ 'field_contact_url' => '',
+ );
+
+ protected $user_column_name = 'user_msnm';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php
new file mode 100644
index 0000000000..98b92eb188
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_wlm_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_wlm_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_msnm');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_wlm',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_msnm',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_msnm' => array('VCHAR_UNI', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php
new file mode 100644
index 0000000000..808aec8099
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_yahoo extends \phpbb\db\migration\profilefield_base_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_wlm_cleanup',
+ );
+ }
+
+ protected $profilefield_name = 'phpbb_yahoo';
+
+ protected $profilefield_database_type = array('VCHAR', '');
+
+ protected $profilefield_data = array(
+ 'field_name' => 'phpbb_yahoo',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_yahoo',
+ 'field_length' => '40',
+ 'field_minlen' => '5',
+ 'field_maxlen' => '255',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_on_ml' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => 'SEND_YIM_MESSAGE',
+ 'field_contact_url' => 'http://edit.yahoo.com/config/send_webmesg?.target=%s&amp;.src=pg',
+ );
+
+ protected $user_column_name = 'user_yim';
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php
new file mode 100644
index 0000000000..c11d06576f
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/profilefield_yahoo_cleanup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class profilefield_yahoo_cleanup extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_yim');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\profilefield_yahoo',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_yim',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_yim' => array('VCHAR_UNI', ''),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php b/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php
new file mode 100644
index 0000000000..83f5f903e8
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/prune_shadow_topics.php
@@ -0,0 +1,46 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class prune_shadow_topics extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\dev');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'forums' => array(
+ 'enable_shadow_prune' => array('BOOL', 0),
+ 'prune_shadow_days' => array('UINT', 7),
+ 'prune_shadow_freq' => array('UINT', 1),
+ 'prune_shadow_next' => array('INT:11', 0),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'forums' => array(
+ 'enable_shadow_prune',
+ 'prune_shadow_days',
+ 'prune_shadow_freq',
+ 'prune_shadow_next',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php b/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php
index 56b7a0916c..c6618cf467 100644
--- a/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php
+++ b/phpBB/phpbb/db/migration/data/v310/reported_posts_display.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php
new file mode 100644
index 0000000000..c9255d88ee
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php
@@ -0,0 +1,128 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+/**
+ * Migration to convert the Soft Delete MOD for 3.0
+ *
+ * https://www.phpbb.com/customise/db/mod/soft_delete/
+ */
+class soft_delete_mod_convert extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\alpha3',
+ );
+ }
+
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_deleted');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('permission.remove', array('m_harddelete', true)),
+ array('permission.remove', array('m_harddelete', false)),
+
+ array('custom', array(array($this, 'convert_posts'))),
+ array('custom', array(array($this, 'convert_topics'))),
+ );
+ }
+
+ public function convert_posts($start)
+ {
+ $content_visibility = $this->get_content_visibility();
+
+ $limit = 250;
+ $i = 0;
+
+ $sql = 'SELECT p.*, t.topic_first_post_id, t.topic_last_post_id
+ FROM ' . $this->table_prefix . 'posts p, ' . $this->table_prefix . 'topics t
+ WHERE p.post_deleted > 0
+ AND t.topic_id = p.topic_id';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $content_visibility->set_post_visibility(
+ ITEM_DELETED,
+ $row['post_id'],
+ $row['topic_id'],
+ $row['forum_id'],
+ $row['post_deleted'],
+ $row['post_deleted_time'],
+ '',
+ ($row['post_id'] == $row['topic_first_post_id']) ? true : false,
+ ($row['post_id'] == $row['topic_last_post_id']) ? true : false
+ );
+
+ $i++;
+ }
+
+ $this->db->sql_freeresult($result);
+
+ if ($i == $limit)
+ {
+ return $start + $i;
+ }
+ }
+
+ public function convert_topics($start)
+ {
+ $content_visibility = $this->get_content_visibility();
+
+ $limit = 100;
+ $i = 0;
+
+ $sql = 'SELECT *
+ FROM ' . $this->table_prefix . 'topics
+ WHERE topic_deleted > 0';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $content_visibility->set_topic_visibility(
+ ITEM_DELETED,
+ $row['topic_id'],
+ $row['forum_id'],
+ $row['topic_deleted'],
+ $row['topic_deleted_time'],
+ ''
+ );
+
+ $i++;
+ }
+
+ $this->db->sql_freeresult($result);
+
+ if ($i == $limit)
+ {
+ return $start + $i;
+ }
+ }
+
+ protected function get_content_visibility()
+ {
+ return new \phpbb\content_visibility(
+ new \phpbb\auth\auth(),
+ $this->db,
+ new \phpbb\user(),
+ $this->phpbb_root_path,
+ $this->php_ext,
+ $this->table_prefix . 'forums',
+ $this->table_prefix . 'posts',
+ $this->table_prefix . 'topics',
+ $this->table_prefix . 'users'
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php
new file mode 100644
index 0000000000..ab4be269e6
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert2.php
@@ -0,0 +1,62 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+/**
+ * Migration to convert the Soft Delete MOD for 3.0
+ *
+ * https://www.phpbb.com/customise/db/mod/soft_delete/
+ */
+class soft_delete_mod_convert2 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\soft_delete_mod_convert',
+ );
+ }
+
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_deleted');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'forums' => array('forum_deleted_topic_count', 'forum_deleted_reply_count'),
+ $this->table_prefix . 'posts' => array('post_deleted', 'post_deleted_time'),
+ $this->table_prefix . 'topics' => array('topic_deleted', 'topic_deleted_time', 'topic_deleted_reply_count'),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'forums' => array(
+ 'forum_deleted_topic_count' => array('UINT', 0),
+ 'forum_deleted_reply_count' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'posts' => array(
+ 'post_deleted' => array('UINT', 0),
+ 'post_deleted_time' => array('TIMESTAMP', 0),
+ ),
+ $this->table_prefix . 'topics' => array(
+ 'topic_deleted' => array('UINT', 0),
+ 'topic_deleted_time' => array('TIMESTAMP', 0),
+ 'topic_deleted_reply_count' => array('UINT', 0),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php
index d1a31815b2..18c225d19f 100644
--- a/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php
+++ b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php
index f080c78c50..10243dc77f 100644
--- a/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php
+++ b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -149,6 +149,15 @@ class softdelete_p1 extends \phpbb\db\migration\migration
$limit = 10;
$converted_forums = 0;
+ if (!$start)
+ {
+ // Preserve the forum_posts value for link forums as it represents redirects.
+ $sql = 'UPDATE ' . $this->table_prefix . 'forums
+ SET forum_posts_approved = forum_posts
+ WHERE forum_type = ' . FORUM_LINK;
+ $this->db->sql_query($sql);
+ }
+
$sql = 'SELECT forum_id, topic_visibility, COUNT(topic_id) AS sum_topics, SUM(topic_posts_approved) AS sum_posts_approved, SUM(topic_posts_unapproved) AS sum_posts_unapproved
FROM ' . $this->table_prefix . 'topics
GROUP BY forum_id, topic_visibility
diff --git a/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php b/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php
index 38b190c766..6b84a1b980 100644
--- a/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php
+++ b/phpBB/phpbb/db/migration/data/v310/softdelete_p2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
index 26f1046287..fcba1d73ed 100644
--- a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
+++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p2.php b/phpBB/phpbb/db/migration/data/v310/style_update_p2.php
index 40d6a4dbbd..316741e11d 100644
--- a/phpBB/phpbb/db/migration/data/v310/style_update_p2.php
+++ b/phpBB/phpbb/db/migration/data/v310/style_update_p2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/teampage.php b/phpBB/phpbb/db/migration/data/v310/teampage.php
index 172435c672..f03c09e04f 100644
--- a/phpBB/phpbb/db/migration/data/v310/teampage.php
+++ b/phpBB/phpbb/db/migration/data/v310/teampage.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/data/v310/timezone.php b/phpBB/phpbb/db/migration/data/v310/timezone.php
index dd0c6a2093..2efedd4514 100644
--- a/phpBB/phpbb/db/migration/data/v310/timezone.php
+++ b/phpBB/phpbb/db/migration/data/v310/timezone.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -39,23 +39,48 @@ class timezone extends \phpbb\db\migration\migration
);
}
- public function update_timezones()
+ public function update_timezones($start)
{
- // Update user timezones
- $sql = 'SELECT user_dst, user_timezone
- FROM ' . $this->table_prefix . 'users
- GROUP BY user_timezone, user_dst';
- $result = $this->db->sql_query($sql);
+ $start = (int) $start;
+ $limit = 500;
+ $converted = 0;
+
+ $update_blocks = array();
+ $sql = 'SELECT user_id, user_timezone, user_dst
+ FROM ' . $this->table_prefix . 'users
+ ORDER BY user_id ASC';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
while ($row = $this->db->sql_fetchrow($result))
{
+ $converted++;
+
+ // In case this is somehow run twice on a row.
+ // Otherwise it would just end up as UTC on the second run
+ if (is_numeric($row['user_timezone']))
+ {
+ $update_blocks[$row['user_timezone'] . ':' . $row['user_dst']][] = (int) $row['user_id'];
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ // Update blocks of users who share the same timezone/dst
+ foreach ($update_blocks as $timezone => $user_ids)
+ {
+ $timezone = explode(':', $timezone);
+ $converted_timezone = $this->convert_phpbb30_timezone($timezone[0], $timezone[1]);
+
$sql = 'UPDATE ' . $this->table_prefix . "users
- SET user_timezone = '" . $this->db->sql_escape($this->convert_phpbb30_timezone($row['user_timezone'], $row['user_dst'])) . "'
- WHERE user_timezone = '" . $this->db->sql_escape($row['user_timezone']) . "'
- AND user_dst = " . (int) $row['user_dst'];
+ SET user_timezone = '" . $this->db->sql_escape($converted_timezone) . "'
+ WHERE " . $this->db->sql_in_set('user_id', $user_ids);
$this->sql_query($sql);
}
- $this->db->sql_freeresult($result);
+
+ if ($converted == $limit)
+ {
+ // There are still more to convert
+ return $start + $limit;
+ }
// Update board default timezone
$sql = 'UPDATE ' . $this->table_prefix . "config
diff --git a/phpBB/phpbb/db/migration/data/v310/timezone_p2.php b/phpBB/phpbb/db/migration/data/v310/timezone_p2.php
index 1066ab8571..891d8622a0 100644
--- a/phpBB/phpbb/db/migration/data/v310/timezone_p2.php
+++ b/phpBB/phpbb/db/migration/data/v310/timezone_p2.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/exception.php b/phpBB/phpbb/db/migration/exception.php
index cfe546d1ab..c6c1a45947 100644
--- a/phpBB/phpbb/db/migration/exception.php
+++ b/phpBB/phpbb/db/migration/exception.php
@@ -3,7 +3,7 @@
*
* @package db
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/helper.php b/phpBB/phpbb/db/migration/helper.php
new file mode 100644
index 0000000000..238b2dbe53
--- /dev/null
+++ b/phpBB/phpbb/db/migration/helper.php
@@ -0,0 +1,82 @@
+<?php
+/**
+*
+* @package db
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration;
+
+/**
+* The migrator is responsible for applying new migrations in the correct order.
+*
+* @package db
+*/
+class helper
+{
+ /**
+ * Get the schema steps from an array of schema changes
+ *
+ * This splits up $schema_changes into individual changes so that the
+ * changes can be chunked
+ *
+ * @param array $schema_changes from migration
+ * @return array
+ */
+ public function get_schema_steps($schema_changes)
+ {
+ $steps = array();
+
+ // Nested level of data (only supports 1/2 currently)
+ $nested_level = array(
+ 'drop_tables' => 1,
+ 'add_tables' => 1,
+ 'change_columns' => 2,
+ 'add_columns' => 2,
+ 'drop_keys' => 2,
+ 'drop_columns' => 2,
+ 'add_primary_keys' => 2, // perform_schema_changes only uses one level, but second is in the function
+ 'add_unique_index' => 2,
+ 'add_index' => 2,
+ );
+
+ foreach ($nested_level as $change_type => $data_depth)
+ {
+ if (!empty($schema_changes[$change_type]))
+ {
+ foreach ($schema_changes[$change_type] as $key => $value)
+ {
+ if ($data_depth === 1)
+ {
+ $steps[] = array(
+ 'dbtools.perform_schema_changes', array(array(
+ $change_type => array(
+ (!is_int($key)) ? $key : 0 => $value,
+ ),
+ )),
+ );
+ }
+ else if ($data_depth === 2)
+ {
+ foreach ($value as $key2 => $value2)
+ {
+ $steps[] = array(
+ 'dbtools.perform_schema_changes', array(array(
+ $change_type => array(
+ $key => array(
+ $key2 => $value2,
+ ),
+ ),
+ )),
+ );
+ }
+ }
+ }
+ }
+ }
+
+ return $steps;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php
index b32de00871..85c5fc5d08 100644
--- a/phpBB/phpbb/db/migration/migration.php
+++ b/phpBB/phpbb/db/migration/migration.php
@@ -3,7 +3,7 @@
*
* @package db
* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -23,7 +23,7 @@ abstract class migration
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\db\tools */
@@ -48,13 +48,13 @@ abstract class migration
* Constructor
*
* @param \phpbb\config\config $config
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\db\tools $db_tools
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $table_prefix
*/
- public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
+ public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
{
$this->config = $config;
$this->db = $db;
diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php
new file mode 100644
index 0000000000..3797d670f7
--- /dev/null
+++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php
@@ -0,0 +1,155 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration;
+
+abstract class profilefield_base_migration extends \phpbb\db\migration\migration
+{
+ protected $profilefield_name;
+
+ protected $profilefield_database_type;
+
+ protected $profilefield_data;
+
+ protected $user_column_name;
+
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields_data', 'pf_' . $this->profilefield_name);
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'pf_' . $this->profilefield_name => $this->profilefield_database_type,
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'pf_' . $this->profilefield_name,
+ ),
+ ),
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'create_custom_field'))),
+ array('custom', array(array($this, 'convert_user_field_to_custom_field'))),
+ );
+ }
+
+ public function create_custom_field()
+ {
+ $sql = 'SELECT MAX(field_order) as max_field_order
+ FROM ' . PROFILE_FIELDS_TABLE;
+ $result = $this->db->sql_query($sql);
+ $max_field_order = (int) $this->db->sql_fetchfield('max_field_order');
+ $this->db->sql_freeresult($result);
+
+ $sql_ary = array_merge($this->profilefield_data, array(
+ 'field_order' => $max_field_order + 1,
+ ));
+
+ $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+ $field_id = (int) $this->db->sql_nextid();
+
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE);
+
+ $sql = 'SELECT lang_id
+ FROM ' . LANG_TABLE;
+ $result = $this->db->sql_query($sql);
+ while ($lang_id = (int) $this->db->sql_fetchfield('lang_id'))
+ {
+ $insert_buffer->insert(array(
+ 'field_id' => $field_id,
+ 'lang_id' => $lang_id,
+ 'lang_name' => strtoupper(substr($this->profilefield_name, 6)),// Remove phpbb_ from field name
+ 'lang_explain' => '',
+ 'lang_default_value' => '',
+ ));
+ }
+ $this->db->sql_freeresult($result);
+
+ $insert_buffer->flush();
+ }
+
+ /**
+ * @param int $start Start of staggering step
+ * @return mixed int start of the next step, null if the end was reached
+ */
+ public function convert_user_field_to_custom_field($start)
+ {
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'profile_fields_data');
+ $limit = 250;
+ $converted_users = 0;
+
+ $sql = 'SELECT user_id, ' . $this->user_column_name . '
+ FROM ' . $this->table_prefix . 'users
+ WHERE ' . $this->user_column_name . " <> ''
+ ORDER BY user_id";
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $converted_users++;
+
+ $cp_data = array(
+ 'pf_' . $this->profilefield_name => $row[$this->user_column_name],
+ );
+
+ $sql = 'UPDATE ' . $this->table_prefix . 'profile_fields_data
+ SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . '
+ WHERE user_id = ' . (int) $row['user_id'];
+ $this->db->sql_query($sql);
+
+ if (!$this->db->sql_affectedrows())
+ {
+ $cp_data['user_id'] = (int) $row['user_id'];
+ $cp_data = array_merge($this->get_insert_sql_array(), $cp_data);
+ $insert_buffer->insert($cp_data);
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ $insert_buffer->flush();
+
+ if ($converted_users < $limit)
+ {
+ // No more users left, we are done...
+ return;
+ }
+
+ return $start + $limit;
+ }
+
+ protected function get_insert_sql_array()
+ {
+ static $profile_row;
+
+ if ($profile_row === null)
+ {
+ global $phpbb_container;
+ $manager = $phpbb_container->get('profilefields.manager');
+ $profile_row = $manager->build_insert_sql_array(array());
+ }
+
+ return $profile_row;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/schema_generator.php b/phpBB/phpbb/db/migration/schema_generator.php
new file mode 100644
index 0000000000..5d40b0b26f
--- /dev/null
+++ b/phpBB/phpbb/db/migration/schema_generator.php
@@ -0,0 +1,215 @@
+<?php
+/**
+*
+* @package db
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration;
+
+/**
+* The schema generator generates the schema based on the existing migrations
+*
+* @package db
+*/
+class schema_generator
+{
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\db\tools */
+ protected $db_tools;
+
+ /** @var array */
+ protected $class_names;
+
+ /** @var string */
+ protected $table_prefix;
+
+ /** @var string */
+ protected $phpbb_root_path;
+
+ /** @var string */
+ protected $php_ext;
+
+ /** @var array */
+ protected $tables;
+
+ /** @var array */
+ protected $dependencies = array();
+
+ /**
+ * Constructor
+ */
+ public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
+ {
+ $this->config = $config;
+ $this->db = $db;
+ $this->db_tools = $db_tools;
+ $this->class_names = $class_names;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->table_prefix = $table_prefix;
+ }
+
+ /**
+ * Loads all migrations and their application state from the database.
+ *
+ * @return array
+ */
+ public function get_schema()
+ {
+ if (!empty($this->tables))
+ {
+ return $this->tables;
+ }
+
+ $migrations = $this->class_names;
+
+ $tree = array();
+ $check_dependencies = true;
+ while (!empty($migrations))
+ {
+ foreach ($migrations as $migration_class)
+ {
+ $open_dependencies = array_diff($migration_class::depends_on(), $tree);
+
+ if (empty($open_dependencies))
+ {
+ $migration = new $migration_class($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix);
+ $tree[] = $migration_class;
+ $migration_key = array_search($migration_class, $migrations);
+
+ foreach ($migration->update_schema() as $change_type => $data)
+ {
+ if ($change_type === 'add_tables')
+ {
+ foreach ($data as $table => $table_data)
+ {
+ $this->tables[$table] = $table_data;
+ }
+ }
+ else if ($change_type === 'drop_tables')
+ {
+ foreach ($data as $table)
+ {
+ unset($this->tables[$table]);
+ }
+ }
+ else if ($change_type === 'add_columns')
+ {
+ foreach ($data as $table => $add_columns)
+ {
+ foreach ($add_columns as $column => $column_data)
+ {
+ $this->tables[$table]['COLUMNS'][$column] = $column_data;
+ }
+ }
+ }
+ else if ($change_type === 'change_columns')
+ {
+ foreach ($data as $table => $change_columns)
+ {
+ foreach ($change_columns as $column => $column_data)
+ {
+ $this->tables[$table]['COLUMNS'][$column] = $column_data;
+ }
+ }
+ }
+ else if ($change_type === 'drop_columns')
+ {
+ foreach ($data as $table => $drop_columns)
+ {
+ if (is_array($drop_columns))
+ {
+ foreach ($drop_columns as $column)
+ {
+ unset($this->tables[$table]['COLUMNS'][$column]);
+ }
+ }
+ else
+ {
+ unset($this->tables[$table]['COLUMNS'][$drop_columns]);
+ }
+ }
+ }
+ else if ($change_type === 'add_unique_index')
+ {
+ foreach ($data as $table => $add_index)
+ {
+ foreach ($add_index as $key => $index_data)
+ {
+ $this->tables[$table]['KEYS'][$key] = array('UNIQUE', $index_data);
+ }
+ }
+ }
+ else if ($change_type === 'add_index')
+ {
+ foreach ($data as $table => $add_index)
+ {
+ foreach ($add_index as $key => $index_data)
+ {
+ $this->tables[$table]['KEYS'][$key] = array('INDEX', $index_data);
+ }
+ }
+ }
+ else if ($change_type === 'drop_keys')
+ {
+ foreach ($data as $table => $drop_keys)
+ {
+ foreach ($drop_keys as $key)
+ {
+ unset($this->tables[$table]['KEYS'][$key]);
+ }
+ }
+ }
+ else
+ {
+ var_dump($change_type);
+ }
+ }
+ unset($migrations[$migration_key]);
+ }
+ else if ($check_dependencies)
+ {
+ $this->dependencies = array_merge($this->dependencies, $open_dependencies);
+ }
+ }
+
+ // Only run this check after the first run
+ if ($check_dependencies)
+ {
+ $this->check_dependencies();
+ $check_dependencies = false;
+ }
+ }
+
+ ksort($this->tables);
+ return $this->tables;
+ }
+
+ /**
+ * Check if one of the migrations files' dependencies can't be resolved
+ * by the supplied list of migrations
+ *
+ * @throws UnexpectedValueException If a dependency can't be resolved
+ */
+ protected function check_dependencies()
+ {
+ // Strip duplicate values from array
+ $this->dependencies = array_unique($this->dependencies);
+
+ foreach ($this->dependencies as $dependency)
+ {
+ if (!in_array($dependency, $this->class_names))
+ {
+ throw new \UnexpectedValueException("Unable to resolve the dependency '$dependency'");
+ }
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/migration/tool/config.php b/phpBB/phpbb/db/migration/tool/config.php
index 36a1931f4e..96d358f647 100644
--- a/phpBB/phpbb/db/migration/tool/config.php
+++ b/phpBB/phpbb/db/migration/tool/config.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 3e39d87c04..96cc6b54a5 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -19,7 +19,7 @@ class module implements \phpbb\db\migration\tool\tool_interface
/** @var \phpbb\cache\service */
protected $cache;
- /** @var dbal */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\user */
@@ -37,14 +37,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
/**
* Constructor
*
- * @param \phpbb\db\driver\driver $db
- * @param mixed $cache
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\cache\service $cache
* @param \phpbb\user $user
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $modules_table
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\cache\service $cache, \phpbb\user $user, $phpbb_root_path, $php_ext, $modules_table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $phpbb_root_path, $php_ext, $modules_table)
{
$this->db = $db;
$this->cache = $cache;
@@ -163,11 +163,10 @@ class module implements \phpbb\db\migration\tool\tool_interface
* )
* Optionally you may not send 'modes' and it will insert all of the
* modules in that info file.
- * @param string|bool $include_path If you would like to use a custom include
* path, specify that here
* @return null
*/
- public function add($class, $parent = 0, $data = array(), $include_path = false)
+ public function add($class, $parent = 0, $data = array())
{
// Allows '' to be sent as 0
$parent = $parent ?: 0;
@@ -328,11 +327,10 @@ class module implements \phpbb\db\migration\tool\tool_interface
* @param int|string|bool $parent The parent module_id|module_langname(0 for no parent).
* Use false to ignore the parent check and check class wide.
* @param int|string $module The module id|module_langname
- * @param string|bool $include_path If you would like to use a custom include path,
* specify that here
* @return null
*/
- public function remove($class, $parent = 0, $module = '', $include_path = false)
+ public function remove($class, $parent = 0, $module = '')
{
// Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto
if (is_array($module))
@@ -340,7 +338,7 @@ class module implements \phpbb\db\migration\tool\tool_interface
if (isset($module['module_langname']))
{
// Manual Method
- return $this->remove($class, $parent, $module['module_langname'], $include_path);
+ return $this->remove($class, $parent, $module['module_langname']);
}
// Failed.
@@ -407,22 +405,10 @@ class module implements \phpbb\db\migration\tool\tool_interface
$module_ids[] = (int) $module_id;
}
$this->db->sql_freeresult($result);
-
- $module_name = $module;
}
else
{
- $module = (int) $module;
- $sql = 'SELECT module_langname
- FROM ' . $this->modules_table . "
- WHERE module_id = $module
- AND module_class = '" . $this->db->sql_escape($class) . "'
- $parent_sql";
- $result = $this->db->sql_query($sql);
- $module_name = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- $module_ids[] = $module;
+ $module_ids[] = (int) $module;
}
if (!class_exists('acp_modules'))
diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php
index fd2de9c8fb..6cb3f213f1 100644
--- a/phpBB/phpbb/db/migration/tool/permission.php
+++ b/phpBB/phpbb/db/migration/tool/permission.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -22,7 +22,7 @@ class permission implements \phpbb\db\migration\tool\tool_interface
/** @var \phpbb\cache\service */
protected $cache;
- /** @var dbal */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var string */
@@ -34,13 +34,13 @@ class permission implements \phpbb\db\migration\tool\tool_interface
/**
* Constructor
*
- * @param \phpbb\db\driver\driver $db
- * @param mixed $cache
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\cache\service $cache
* @param \phpbb\auth\auth $auth
* @param string $phpbb_root_path
* @param string $php_ext
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->cache = $cache;
diff --git a/phpBB/phpbb/db/migration/tool/tool_interface.php b/phpBB/phpbb/db/migration/tool/tool_interface.php
index e7b89d8858..5eb1a2f521 100644
--- a/phpBB/phpbb/db/migration/tool/tool_interface.php
+++ b/phpBB/phpbb/db/migration/tool/tool_interface.php
@@ -3,7 +3,7 @@
*
* @package migration
* @copyright (c) 2012 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 8186493800..5ad8563e5c 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -3,7 +3,7 @@
*
* @package db
* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -19,12 +19,15 @@ class migrator
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\db\tools */
protected $db_tools;
+ /** @var \phpbb\db\migration\helper */
+ protected $helper;
+
/** @var string */
protected $table_prefix;
@@ -65,11 +68,12 @@ class migrator
/**
* Constructor of the database migrator
*/
- public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools)
+ public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
{
$this->config = $config;
$this->db = $db;
$this->db_tools = $db_tools;
+ $this->helper = $helper;
$this->migrations_table = $migrations_table;
@@ -83,6 +87,8 @@ class migrator
$this->tools[$tool->get_name()] = $tool;
}
+ $this->tools['dbtools'] = $this->db_tools;
+
$this->load_migration_state();
}
@@ -229,9 +235,12 @@ class migrator
if (!$state['migration_schema_done'])
{
- $this->last_run_migration['task'] = 'apply_schema_changes';
- $this->apply_schema_changes($migration->update_schema());
- $state['migration_schema_done'] = true;
+ $this->last_run_migration['task'] = 'process_schema_step';
+ $steps = $this->helper->get_schema_steps($migration->update_schema());
+ $result = $this->process_data_step($steps, $state['migration_data_state']);
+
+ $state['migration_data_state'] = ($result === true) ? '' : $result;
+ $state['migration_schema_done'] = ($result === true);
}
else if (!$state['migration_data_done'])
{
@@ -329,33 +338,28 @@ class migrator
$this->set_migration_state($name, $state);
}
- else
+ else if ($state['migration_schema_done'])
{
- $this->apply_schema_changes($migration->revert_schema());
+ $steps = $this->helper->get_schema_steps($migration->revert_schema());
+ $result = $this->process_data_step($steps, $state['migration_data_state']);
- $sql = 'DELETE FROM ' . $this->migrations_table . "
- WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
- $this->db->sql_query($sql);
+ $state['migration_data_state'] = ($result === true) ? '' : $result;
+ $state['migration_schema_done'] = ($result === true) ? false : true;
+
+ if (!$state['migration_schema_done'])
+ {
+ $sql = 'DELETE FROM ' . $this->migrations_table . "
+ WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
+ $this->db->sql_query($sql);
- unset($this->migration_state[$name]);
+ unset($this->migration_state[$name]);
+ }
}
return true;
}
/**
- * Apply schema changes from a migration
- *
- * Just calls db_tools->perform_schema_changes
- *
- * @param array $schema_changes from migration
- */
- protected function apply_schema_changes($schema_changes)
- {
- $this->db_tools->perform_schema_changes($schema_changes);
- }
-
- /**
* Process the data step of the migration
*
* @param array $steps The steps to run
@@ -498,16 +502,24 @@ class migrator
return $this->get_callable_from_step($step);
break;
+
case 'custom':
if (!is_callable($parameters[0]))
{
throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE', $step);
}
- return array(
- $parameters[0],
- array($last_result),
- );
+ if ($reverse)
+ {
+ return false;
+ }
+ else
+ {
+ return array(
+ $parameters[0],
+ array($last_result),
+ );
+ }
break;
default:
diff --git a/phpBB/phpbb/db/sql_insert_buffer.php b/phpBB/phpbb/db/sql_insert_buffer.php
index 41026ad425..0236a55b82 100644
--- a/phpBB/phpbb/db/sql_insert_buffer.php
+++ b/phpBB/phpbb/db/sql_insert_buffer.php
@@ -49,7 +49,7 @@ namespace phpbb\db;
*/
class sql_insert_buffer
{
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var string */
@@ -62,11 +62,11 @@ class sql_insert_buffer
protected $buffer = array();
/**
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param string $table_name
* @param int $max_buffered_rows
*/
- public function __construct(\phpbb\db\driver\driver $db, $table_name, $max_buffered_rows = 500)
+ public function __construct(\phpbb\db\driver\driver_interface $db, $table_name, $max_buffered_rows = 500)
{
$this->db = $db;
$this->table_name = $table_name;
diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php
index 4360c89ac3..2b0132075b 100644
--- a/phpBB/phpbb/db/tools.php
+++ b/phpBB/phpbb/db/tools.php
@@ -34,6 +34,12 @@ class tools
var $dbms_type_map = array();
/**
+ * Is the used MS SQL Server a SQL Server 2000?
+ * @var bool
+ */
+ protected $is_sql_server_2000;
+
+ /**
* Get the column types for every database we support
*
* @return array
@@ -304,10 +310,10 @@ class tools
/**
* Constructor. Set DB Object and set {@link $return_statements return_statements}.
*
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param bool $return_statements True if only statements should be returned and no SQL being executed
*/
- public function __construct(\phpbb\db\driver\driver $db, $return_statements = false)
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
{
$this->db = $db;
$this->return_statements = $return_statements;
@@ -467,9 +473,6 @@ class tools
// Determine if we have created a PRIMARY KEY in the earliest
$primary_key_gen = false;
- // Determine if the table must be created with TEXTIMAGE
- $create_textimage = false;
-
// Determine if the table requires a sequence
$create_sequence = false;
@@ -486,13 +489,22 @@ class tools
break;
}
+ if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
+ {
+ if (!isset($table_data['PRIMARY_KEY']))
+ {
+ $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
+ $table_data['PRIMARY_KEY'] = 'mssqlindex';
+ }
+ }
+
// Iterate through the columns to create a table
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
{
// here lies an array, filled with information compiled on the column's data
$prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
- if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen"
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
{
trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
}
@@ -516,12 +528,6 @@ class tools
$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
}
- // create textimage DDL based off of the existance of certain column types
- if (!$create_textimage)
- {
- $create_textimage = isset($prepared_column['textimage']) && $prepared_column['textimage'];
- }
-
// create sequence DDL based off of the existance of auto incrementing columns
if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
{
@@ -536,13 +542,9 @@ class tools
switch ($this->sql_layer)
{
case 'firebird':
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
-
case 'mssql':
case 'mssqlnative':
- $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : '');
+ $table_sql .= "\n);";
$statements[] = $table_sql;
break;
}
@@ -896,7 +898,7 @@ class tools
}
}
- // Add unqiue indexes?
+ // Add unique indexes?
if (!empty($schema_changes['add_unique_index']))
{
foreach ($schema_changes['add_unique_index'] as $table => $index_array)
@@ -1307,7 +1309,7 @@ class tools
}
/**
- * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes.
+ * Check if a specified index exists in table. Does not return PRIMARY KEY indexes.
*
* @param string $table_name Table to check the index at
* @param string $index_name The index name to check
@@ -1474,52 +1476,7 @@ class tools
}
// Get type
- if (strpos($column_data[0], ':') !== false)
- {
- list($orig_column_type, $column_length) = explode(':', $column_data[0]);
- if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']))
- {
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length);
- }
- else
- {
- if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule']))
- {
- switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0])
- {
- case 'div':
- $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1];
- $column_length = ceil($column_length);
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
- break;
- }
- }
-
- if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit']))
- {
- switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0])
- {
- case 'mult':
- $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1];
- if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2])
- {
- $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3];
- }
- else
- {
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
- }
- break;
- }
- }
- }
- $orig_column_type .= ':';
- }
- else
- {
- $orig_column_type = $column_data[0];
- $column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]];
- }
+ list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]);
// Adjust default value if db-dependent specified
if (is_array($column_data[1]))
@@ -1695,6 +1652,65 @@ class tools
}
/**
+ * Get the column's database type from the type map
+ *
+ * @param string $column_map_type
+ * @return array column type for this database
+ * and map type without length
+ */
+ function get_column_type($column_map_type)
+ {
+ if (strpos($column_map_type, ':') !== false)
+ {
+ list($orig_column_type, $column_length) = explode(':', $column_map_type);
+ if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']))
+ {
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length);
+ }
+ else
+ {
+ if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule']))
+ {
+ switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0])
+ {
+ case 'div':
+ $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1];
+ $column_length = ceil($column_length);
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
+ break;
+ }
+ }
+
+ if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit']))
+ {
+ switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0])
+ {
+ case 'mult':
+ $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1];
+ if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2])
+ {
+ $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3];
+ }
+ else
+ {
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
+ }
+ break;
+ }
+ }
+ }
+ $orig_column_type .= ':';
+ }
+ else
+ {
+ $orig_column_type = $column_map_type;
+ $column_type = $this->dbms_type_map[$this->sql_layer][$column_map_type];
+ }
+
+ return array($column_type, $orig_column_type);
+ }
+
+ /**
* Add new column
*/
function sql_column_add($table_name, $column_name, $column_data, $inline = false)
@@ -1836,23 +1852,46 @@ class tools
case 'mssql':
case 'mssqlnative':
- // remove default cosntraints first
- // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
- $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000)
- SET @drop_default_name =
- (SELECT so.name FROM sysobjects so
- JOIN sysconstraints sc ON so.id = sc.constid
- WHERE object_name(so.parent_obj) = '{$table_name}'
- AND so.xtype = 'D'
- AND sc.colid = (SELECT colid FROM syscolumns
- WHERE id = object_id('{$table_name}')
- AND name = '{$column_name}'))
- IF @drop_default_name <> ''
- BEGIN
- SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']'
- EXEC(@cmd)
- END";
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->mssql_get_existing_indexes($table_name, $column_name);
+
+ // Drop any indexes
+ $recreate_indexes = array();
+ if (!empty($indexes))
+ {
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_index_drop($table_name, $index_name);
+ $statements = array_merge($statements, $result);
+ if (sizeof($index_data) > 1)
+ {
+ // Remove this column from the index and recreate it
+ $recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
+ }
+ }
+ }
+
+ // Drop default value constraint
+ $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Remove the column
$statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
+
+ if (!empty($recreate_indexes))
+ {
+ // Recreate indexes after we removed the column
+ foreach ($recreate_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
break;
case 'mysql_40':
@@ -2055,7 +2094,7 @@ class tools
$sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
$sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
$sql .= '[' . implode("],\n\t\t[", $column) . ']';
- $sql .= ') ON [PRIMARY]';
+ $sql .= ')';
$statements[] = $sql;
break;
@@ -2153,7 +2192,7 @@ class tools
case 'mssql':
case 'mssqlnative':
- $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
+ $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
break;
}
@@ -2206,7 +2245,7 @@ class tools
case 'mssql':
case 'mssqlnative':
- $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
+ $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
break;
}
@@ -2334,28 +2373,46 @@ class tools
case 'mssql':
case 'mssqlnative':
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->mssql_get_existing_indexes($table_name, $column_name);
+
+ // Drop any indexes
+ if (!empty($indexes))
+ {
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_index_drop($table_name, $index_name);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ // Drop default value constraint
+ $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Change the column
$statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
if (!empty($column_data['default']))
{
- // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage
- $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000)
- SET @drop_default_name =
- (SELECT so.name FROM sysobjects so
- JOIN sysconstraints sc ON so.id = sc.constid
- WHERE object_name(so.parent_obj) = '{$table_name}'
- AND so.xtype = 'D'
- AND sc.colid = (SELECT colid FROM syscolumns
- WHERE id = object_id('{$table_name}')
- AND name = '{$column_name}'))
- IF @drop_default_name <> ''
- BEGIN
- SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']'
- EXEC(@cmd)
- END
- SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]'
- EXEC(@cmd)";
+ // Add new default value constraint
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $this->db->sql_escape($column_data['default']) . ' FOR [' . $column_name . ']';
}
+
+ if (!empty($indexes))
+ {
+ // Recreate indexes after we changed the column
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
break;
case 'mysql_40':
@@ -2489,4 +2546,159 @@ class tools
return $this->_sql_run_sql($statements);
}
+
+ /**
+ * Get queries to drop the default constraints of a column
+ *
+ * We need to drop the default constraints of a column,
+ * before being able to change their type or deleting them.
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @return array Array with SQL statements
+ */
+ protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
+ {
+ $statements = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT so.name AS def_name
+ FROM sysobjects so
+ JOIN sysconstraints sc ON so.id = sc.constid
+ WHERE object_name(so.parent_obj) = '{$table_name}'
+ AND so.xtype = 'D'
+ AND sc.colid = (SELECT colid FROM syscolumns
+ WHERE id = object_id('{$table_name}')
+ AND name = '{$column_name}')";
+ }
+ else
+ {
+ $sql = "SELECT dobj.name AS def_name
+ FROM sys.columns col
+ LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
+ WHERE col.object_id = object_id('{$table_name}')
+ AND col.name = '{$column_name}'
+ AND dobj.name IS NOT NULL";
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
+ }
+ $this->db->sql_freeresult($result);
+
+ return $statements;
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @return array Array with Index name => columns
+ */
+ protected function mssql_get_existing_indexes($table_name, $column_name)
+ {
+ $existing_indexes = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'";
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'";
+ }
+
+ $result = $this->db->sql_query($sql);
+ $existing_indexes = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $existing_indexes[$row['phpbb_index_name']] = array();
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($existing_indexes))
+ {
+ return array();
+ }
+
+ if ($this->mssql_is_sql_server_2000())
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $existing_indexes;
+ }
+
+ /**
+ * Is the used MS SQL Server a SQL Server 2000?
+ *
+ * @return bool
+ */
+ protected function mssql_is_sql_server_2000()
+ {
+ if ($this->is_sql_server_2000 === null)
+ {
+ $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
+ $result = $this->db->sql_query($sql);
+ $properties = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
+ }
+
+ return $this->is_sql_server_2000;
+ }
}
diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php
new file mode 100644
index 0000000000..af86882885
--- /dev/null
+++ b/phpBB/phpbb/event/md_exporter.php
@@ -0,0 +1,439 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\event;
+
+/**
+* Class md_exporter
+* Crawls through a markdown file and grabs all events
+*
+* @package phpbb\event
+*/
+class md_exporter
+{
+ /** @var string Path where we look for files*/
+ protected $path;
+
+ /** @var string phpBB Root Path */
+ protected $root_path;
+
+ /** @var string */
+ protected $filter;
+
+ /** @var string */
+ protected $current_event;
+
+ /** @var array */
+ protected $events;
+
+ /**
+ * @param string $phpbb_root_path
+ * @param mixed $extension String 'vendor/ext' to filter, null for phpBB core
+ */
+ public function __construct($phpbb_root_path, $extension = null)
+ {
+ $this->root_path = $phpbb_root_path;
+ $this->path = $this->root_path;
+ if ($extension)
+ {
+ $this->path .= 'ext/' . $extension . '/';
+ }
+
+ $this->events = array();
+ $this->events_by_file = array();
+ $this->filter = $this->current_event = '';
+ }
+
+ /**
+ * Get the list of all events
+ *
+ * @return array Array with events: name => details
+ */
+ public function get_events()
+ {
+ return $this->events;
+ }
+
+ /**
+ * @param string $md_file Relative from phpBB root
+ * @return int Number of events found
+ * @throws \LogicException
+ */
+ public function crawl_phpbb_directory_adm($md_file)
+ {
+ $this->crawl_eventsmd($md_file, 'adm');
+
+ $file_list = $this->get_recursive_file_list($this->path . 'adm/style/');
+ foreach ($file_list as $file)
+ {
+ $file_name = 'adm/style/' . $file;
+ $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name));
+ }
+
+ return sizeof($this->events);
+ }
+
+ /**
+ * @param string $md_file Relative from phpBB root
+ * @return int Number of events found
+ * @throws \LogicException
+ */
+ public function crawl_phpbb_directory_styles($md_file)
+ {
+ $this->crawl_eventsmd($md_file, 'styles');
+
+ $styles = array('prosilver', 'subsilver2');
+ foreach ($styles as $style)
+ {
+ $file_list = $this->get_recursive_file_list(
+ $this->path . 'styles/' . $style . '/template/'
+ );
+
+ foreach ($file_list as $file)
+ {
+ $file_name = 'styles/' . $style . '/template/' . $file;
+ $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name));
+ }
+ }
+
+ return sizeof($this->events);
+ }
+
+ /**
+ * @param string $md_file Relative from phpBB root
+ * @param string $filter Should be 'styles' or 'adm'
+ * @return int Number of events found
+ * @throws \LogicException
+ */
+ public function crawl_eventsmd($md_file, $filter)
+ {
+ if (!file_exists($this->path . $md_file))
+ {
+ throw new \LogicException("The event docs file '{$md_file}' could not be found");
+ }
+
+ $file_content = file_get_contents($this->path . $md_file);
+ $this->filter = $filter;
+
+ $events = explode("\n\n", $file_content);
+ foreach ($events as $event)
+ {
+ // Last row of the file
+ if (strpos($event, "\n===\n") === false)
+ {
+ continue;
+ }
+
+ list($event_name, $details) = explode("\n===\n", $event, 2);
+ $this->validate_event_name($event_name);
+ $this->current_event = $event_name;
+
+ if (isset($this->events[$this->current_event]))
+ {
+ throw new \LogicException("The event '{$this->current_event}' is defined multiple times");
+ }
+
+ if (($this->filter == 'adm' && strpos($this->current_event, 'acp_') !== 0)
+ || ($this->filter == 'styles' && strpos($this->current_event, 'acp_') === 0))
+ {
+ continue;
+ }
+
+ list($file_details, $details) = explode("\n* Since: ", $details, 2);
+ list($since, $description) = explode("\n* Purpose: ", $details, 2);
+
+ $files = $this->validate_file_list($file_details);
+ $since = $this->validate_since($since);
+
+ $this->events[$event_name] = array(
+ 'event' => $this->current_event,
+ 'files' => $files,
+ 'since' => $since,
+ 'description' => $description,
+ );
+ }
+
+ return sizeof($this->events);
+ }
+
+ /**
+ * Format the php events as a wiki table
+ * @return string Number of events found
+ */
+ public function export_events_for_wiki()
+ {
+ if ($this->filter === 'adm')
+ {
+ $wiki_page = '= ACP Template Events =' . "\n";
+ $wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";
+ $wiki_page .= '! Identifier !! Placement !! Added in Release !! Explanation' . "\n";
+ }
+ else
+ {
+ $wiki_page = '= Template Events =' . "\n";
+ $wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";
+ $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Subsilver Placement (If applicable) !! Added in Release !! Explanation' . "\n";
+ }
+
+ foreach ($this->events as $event_name => $event)
+ {
+ $wiki_page .= "|- id=\"{$event_name}\"\n";
+ $wiki_page .= "| [[#{$event_name}|{$event_name}]] || ";
+
+ if ($this->filter === 'adm')
+ {
+ $wiki_page .= implode(', ', $event['files']['adm']);
+ }
+ else
+ {
+ $wiki_page .= implode(', ', $event['files']['prosilver']) . ' || ' . implode(', ', $event['files']['subsilver2']);
+ }
+
+ $wiki_page .= " || {$event['since']} || " . str_replace("\n", ' ', $event['description']) . "\n";
+ }
+ $wiki_page .= '|}' . "\n";
+
+ return $wiki_page;
+ }
+
+ /**
+ * Validates a template event name
+ *
+ * @param $event_name
+ * @return null
+ * @throws \LogicException
+ */
+ public function validate_event_name($event_name)
+ {
+ if (!preg_match('#^([a-z][a-z0-9]*(?:_[a-z][a-z0-9]*)+)$#', $event_name))
+ {
+ throw new \LogicException("Invalid event name '{$event_name}'");
+ }
+ }
+
+ /**
+ * Validate "Since" Information
+ *
+ * @param string $since
+ * @return string
+ * @throws \LogicException
+ */
+ public function validate_since($since)
+ {
+ if (!preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?$#', $since))
+ {
+ throw new \LogicException("Invalid since information found for event '{$this->current_event}'");
+ }
+
+ return $since;
+ }
+
+ /**
+ * Validate the files list
+ *
+ * @param string $file_details
+ * @return array
+ * @throws \LogicException
+ */
+ public function validate_file_list($file_details)
+ {
+ $files_list = array(
+ 'prosilver' => array(),
+ 'subsilver2' => array(),
+ 'adm' => array(),
+ );
+
+ // Multi file list
+ if (strpos($file_details, "* Locations:\n + ") === 0)
+ {
+ $file_details = substr($file_details, strlen("* Locations:\n + "));
+ $files = explode("\n + ", $file_details);
+ foreach ($files as $file)
+ {
+ if (!file_exists($this->path . $file) || substr($file, -5) !== '.html')
+ {
+ throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1);
+ }
+
+ if (($this->filter !== 'adm') && strpos($file, 'styles/prosilver/template/') === 0)
+ {
+ $files_list['prosilver'][] = substr($file, strlen('styles/prosilver/template/'));
+ }
+ else if (($this->filter !== 'adm') && strpos($file, 'styles/subsilver2/template/') === 0)
+ {
+ $files_list['subsilver2'][] = substr($file, strlen('styles/subsilver2/template/'));
+ }
+ else if (($this->filter === 'adm') && strpos($file, 'adm/style/') === 0)
+ {
+ $files_list['adm'][] = substr($file, strlen('adm/style/'));
+ }
+ else
+ {
+ throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 2);
+ }
+
+ $this->events_by_file[$file][] = $this->current_event;
+ }
+ }
+ else if ($this->filter == 'adm')
+ {
+ $file = substr($file_details, strlen('* Location: '));
+ if (!file_exists($this->path . $file) || substr($file, -5) !== '.html')
+ {
+ throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1);
+ }
+
+ $files_list['adm'][] = substr($file, strlen('adm/style/'));
+
+ $this->events_by_file[$file][] = $this->current_event;
+ }
+ else
+ {
+ throw new \LogicException("Invalid file list found for event '{$this->current_event}'", 2);
+ }
+
+ return $files_list;
+ }
+
+ /**
+ * Get all template events in a template file
+ *
+ * @param string $file
+ * @return array
+ * @throws \LogicException
+ */
+ public function crawl_file_for_events($file)
+ {
+ if (!file_exists($this->path . $file))
+ {
+ throw new \LogicException("File '{$file}' does not exist", 1);
+ }
+
+ $event_list = array();
+ $file_content = file_get_contents($this->path . $file);
+
+ $events = explode('<!-- EVENT ', $file_content);
+ // Remove the code before the first event
+ array_shift($events);
+ foreach ($events as $event)
+ {
+ $event = explode(' -->', $event, 2);
+ $event_list[] = array_shift($event);
+ }
+
+ return $event_list;
+ }
+
+ /**
+ * Validates whether all events from $file are in the md file and vice-versa
+ *
+ * @param string $file
+ * @param array $events
+ * @return true
+ * @throws \LogicException
+ */
+ public function validate_events_from_file($file, array $events)
+ {
+ if (empty($this->events_by_file[$file]) && empty($events))
+ {
+ return true;
+ }
+ else if (empty($this->events_by_file[$file]))
+ {
+ $event_list = implode("', '", $events);
+ throw new \LogicException("File '{$file}' should not contain events, but contains: "
+ . "'{$event_list}'", 1);
+ }
+ else if (empty($events))
+ {
+ $event_list = implode("', '", $this->events_by_file[$file]);
+ throw new \LogicException("File '{$file}' contains no events, but should contain: "
+ . "'{$event_list}'", 1);
+ }
+
+ $missing_events_from_file = array();
+ foreach ($this->events_by_file[$file] as $event)
+ {
+ if (!in_array($event, $events))
+ {
+ $missing_events_from_file[] = $event;
+ }
+ }
+
+ if (!empty($missing_events_from_file))
+ {
+ $event_list = implode("', '", $missing_events_from_file);
+ throw new \LogicException("File '{$file}' does not contain events: '{$event_list}'", 2);
+ }
+
+ $missing_events_from_md = array();
+ foreach ($events as $event)
+ {
+ if (!in_array($event, $this->events_by_file[$file]))
+ {
+ $missing_events_from_md[] = $event;
+ }
+ }
+
+ if (!empty($missing_events_from_md))
+ {
+ $event_list = implode("', '", $missing_events_from_md);
+ throw new \LogicException("File '{$file}' contains additional events: '{$event_list}'", 3);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a list of files in $dir
+ *
+ * Works recursive with any depth
+ *
+ * @param string $dir Directory to go through
+ * @return array List of files (including directories)
+ */
+ public function get_recursive_file_list($dir)
+ {
+ try
+ {
+ $iterator = new \RecursiveIteratorIterator(
+ new \phpbb\recursive_dot_prefix_filter_iterator(
+ new \RecursiveDirectoryIterator(
+ $dir,
+ \FilesystemIterator::SKIP_DOTS
+ )
+ ),
+ \RecursiveIteratorIterator::SELF_FIRST
+ );
+ }
+ catch (\Exception $e)
+ {
+ return array();
+ }
+
+ $files = array();
+ foreach ($iterator as $file_info)
+ {
+ /** @var \RecursiveDirectoryIterator $file_info */
+ if ($file_info->isDir())
+ {
+ continue;
+ }
+
+ $relative_path = $iterator->getInnerIterator()->getSubPathname();
+
+ if (substr($relative_path, -5) == '.html')
+ {
+ $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path);
+ }
+ }
+
+ return $files;
+ }
+}
diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php
new file mode 100644
index 0000000000..d86ee3c045
--- /dev/null
+++ b/phpBB/phpbb/event/php_exporter.php
@@ -0,0 +1,608 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\event;
+
+/**
+* Class php_exporter
+* Crawls through a list of files and grabs all php-events
+*
+* @package phpbb\event
+*/
+class php_exporter
+{
+ /** @var string Path where we look for files*/
+ protected $path;
+
+ /** @var string phpBB Root Path */
+ protected $root_path;
+
+ /** @var string */
+ protected $current_file;
+
+ /** @var string */
+ protected $current_event;
+
+ /** @var int */
+ protected $current_event_line;
+
+ /** @var array */
+ protected $events;
+
+ /** @var array */
+ protected $file_lines;
+
+ /**
+ * @param string $phpbb_root_path
+ * @param mixed $extension String 'vendor/ext' to filter, null for phpBB core
+ */
+ public function __construct($phpbb_root_path, $extension = null)
+ {
+ $this->root_path = $phpbb_root_path;
+ $this->path = $phpbb_root_path;
+ $this->events = $this->file_lines = array();
+ $this->current_file = $this->current_event = '';
+ $this->current_event_line = 0;
+
+ $this->path = $this->root_path;
+ if ($extension)
+ {
+ $this->path .= 'ext/' . $extension . '/';
+ }
+ }
+
+ /**
+ * Get the list of all events
+ *
+ * @return array Array with events: name => details
+ */
+ public function get_events()
+ {
+ return $this->events;
+ }
+
+ /**
+ * Set current event data
+ *
+ * @param string $name Name of the current event (used for error messages)
+ * @param int $line Line where the current event is placed in
+ * @return null
+ */
+ public function set_current_event($name, $line)
+ {
+ $this->current_event = $name;
+ $this->current_event_line = $line;
+ }
+
+ /**
+ * Set the content of this file
+ *
+ * @param array $content Array with the lines of the file
+ * @return null
+ */
+ public function set_content($content)
+ {
+ $this->file_lines = $content;
+ }
+
+ /**
+ * Crawl the phpBB/ directory for php events
+ * @return int The number of events found
+ */
+ public function crawl_phpbb_directory_php()
+ {
+ $files = $this->get_recursive_file_list();
+ $this->events = array();
+ foreach ($files as $file)
+ {
+ $this->crawl_php_file($file);
+ }
+ ksort($this->events);
+
+ return sizeof($this->events);
+ }
+
+ /**
+ * Returns a list of files in $dir
+ *
+ * @return array List of files (including the path)
+ */
+ public function get_recursive_file_list()
+ {
+ try
+ {
+ $iterator = new \RecursiveIteratorIterator(
+ new \phpbb\event\recursive_event_filter_iterator(
+ new \RecursiveDirectoryIterator(
+ $this->path,
+ \FilesystemIterator::SKIP_DOTS
+ ),
+ $this->path
+ ),
+ \RecursiveIteratorIterator::LEAVES_ONLY
+ );
+ }
+ catch (\Exception $e)
+ {
+ return array();
+ }
+
+ $files = array();
+ foreach ($iterator as $file_info)
+ {
+ /** @var \RecursiveDirectoryIterator $file_info */
+ $relative_path = $iterator->getInnerIterator()->getSubPathname();
+ $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path);
+ }
+
+ return $files;
+ }
+
+ /**
+ * Format the php events as a wiki table
+ * @return string
+ */
+ public function export_events_for_wiki()
+ {
+ $wiki_page = '= PHP Events (Hook Locations) =' . "\n";
+ $wiki_page .= '{| class="sortable zebra" cellspacing="0" cellpadding="5"' . "\n";
+ $wiki_page .= '! Identifier !! Placement !! Arguments !! Added in Release !! Explanation' . "\n";
+ foreach ($this->events as $event)
+ {
+ $wiki_page .= '|- id="' . $event['event'] . '"' . "\n";
+ $wiki_page .= '| [[#' . $event['event'] . '|' . $event['event'] . ']] || ' . $event['file'] . ' || ' . implode(', ', $event['arguments']) . ' || ' . $event['since'] . ' || ' . $event['description'] . "\n";
+ }
+ $wiki_page .= '|}' . "\n";
+
+ return $wiki_page;
+ }
+
+ /**
+ * @param string $file
+ * @return int Number of events found in this file
+ * @throws \LogicException
+ */
+ public function crawl_php_file($file)
+ {
+ $this->current_file = $file;
+ $this->file_lines = array();
+ $content = file_get_contents($this->path . $this->current_file);
+ $num_events_found = 0;
+
+ if (strpos($content, "dispatcher->trigger_event('") || strpos($content, "dispatcher->dispatch('"))
+ {
+ $this->set_content(explode("\n", $content));
+ for ($i = 0, $num_lines = sizeof($this->file_lines); $i < $num_lines; $i++)
+ {
+ $event_line = false;
+ $found_trigger_event = strpos($this->file_lines[$i], "dispatcher->trigger_event('");
+ $arguments = array();
+ if ($found_trigger_event !== false)
+ {
+ $event_line = $i;
+ $this->set_current_event($this->get_event_name($event_line, false), $event_line);
+
+ // Find variables of the event
+ $arguments = $this->get_vars_from_array();
+ $doc_vars = $this->get_vars_from_docblock();
+ $this->validate_vars_docblock_array($arguments, $doc_vars);
+ }
+ else
+ {
+ $found_dispatch = strpos($this->file_lines[$i], "dispatcher->dispatch('");
+ if ($found_dispatch !== false)
+ {
+ $event_line = $i;
+ $this->set_current_event($this->get_event_name($event_line, true), $event_line);
+ }
+ }
+
+ if ($event_line)
+ {
+ // Validate @event
+ $event_line_num = $this->find_event();
+ $this->validate_event($this->current_event, $this->file_lines[$event_line_num]);
+
+ // Validate @since
+ $since_line_num = $this->find_since();
+ $since = $this->validate_since($this->file_lines[$since_line_num]);
+
+ // Find event description line
+ $description_line_num = $this->find_description();
+ $description = substr(trim($this->file_lines[$description_line_num]), strlen('* '));
+
+ if (isset($this->events[$this->current_event]))
+ {
+ throw new \LogicException("The event '{$this->current_event}' from file "
+ . "'{$this->current_file}:{$event_line_num}' already exists in file "
+ . "'{$this->events[$this->current_event]['file']}'", 10);
+ }
+
+ sort($arguments);
+ $this->events[$this->current_event] = array(
+ 'event' => $this->current_event,
+ 'file' => $this->current_file,
+ 'arguments' => $arguments,
+ 'since' => $since,
+ 'description' => $description,
+ );
+ $num_events_found++;
+ }
+ }
+ }
+
+ return $num_events_found;
+ }
+
+ /**
+ * Find the name of the event inside the dispatch() line
+ *
+ * @param int $event_line
+ * @param bool $is_dispatch Do we look for dispatch() or trigger_event() ?
+ * @return string Name of the event
+ * @throws \LogicException
+ */
+ public function get_event_name($event_line, $is_dispatch)
+ {
+ $event_text_line = $this->file_lines[$event_line];
+ $event_text_line = ltrim($event_text_line, "\t");
+
+ if ($is_dispatch)
+ {
+ $regex = '#\$([a-z](?:[a-z0-9_]|->)*)';
+ $regex .= '->dispatch\(';
+ $regex .= '\'' . $this->preg_match_event_name() . '\'';
+ $regex .= '\);#';
+ }
+ else
+ {
+ $regex = '#extract\(\$([a-z](?:[a-z0-9_]|->)*)';
+ $regex .= '->trigger_event\(';
+ $regex .= '\'' . $this->preg_match_event_name() . '\'';
+ $regex .= ', compact\(\$vars\)\)\);#';
+ }
+
+ $match = array();
+ preg_match($regex, $event_text_line, $match);
+ if (!isset($match[2]))
+ {
+ throw new \LogicException("Can not find event name in line '{$event_text_line}' "
+ . "in file '{$this->current_file}:{$event_line}'", 1);
+ }
+
+ return $match[2];
+ }
+
+ /**
+ * Returns a regex match for the event name
+ *
+ * @return string
+ */
+ protected function preg_match_event_name()
+ {
+ return '([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+)';
+ }
+
+ /**
+ * Find the $vars array
+ *
+ * @return array List of variables
+ * @throws \LogicException
+ */
+ public function get_vars_from_array()
+ {
+ $line = ltrim($this->file_lines[$this->current_event_line - 1], "\t");
+ if ($line === ');')
+ {
+ $vars_array = $this->get_vars_from_multi_line_array();
+ }
+ else
+ {
+ $vars_array = $this->get_vars_from_single_line_array($line);
+ }
+
+ foreach ($vars_array as $var)
+ {
+ if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var))
+ {
+ throw new \LogicException("Found invalid var '{$var}' in array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
+ }
+ }
+
+ sort($vars_array);
+ return $vars_array;
+ }
+
+ /**
+ * Find the variables in single line array
+ *
+ * @param string $line
+ * @param bool $throw_multiline Throw an exception when there are too
+ * many arguments in one line.
+ * @return array List of variables
+ * @throws \LogicException
+ */
+ public function get_vars_from_single_line_array($line, $throw_multiline = true)
+ {
+ $match = array();
+ preg_match('#^\$vars = array\(\'([a-zA-Z0-9_\' ,]+)\'\);$#', $line, $match);
+
+ if (isset($match[1]))
+ {
+ $vars_array = explode("', '", $match[1]);
+ if ($throw_multiline && sizeof($vars_array) > 6)
+ {
+ throw new \LogicException('Should use multiple lines for $vars definition '
+ . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+ return $vars_array;
+ }
+ else
+ {
+ throw new \LogicException("Can not find '\$vars = array();'-line for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
+ }
+ }
+
+ /**
+ * Find the variables in single line array
+ *
+ * @return array List of variables
+ * @throws \LogicException
+ */
+ public function get_vars_from_multi_line_array()
+ {
+ $current_vars_line = 2;
+ $var_lines = array();
+ while (ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t") !== '$vars = array(')
+ {
+ $var_lines[] = substr(trim($this->file_lines[$this->current_event_line - $current_vars_line]), 0, -1);
+
+ $current_vars_line++;
+ if ($current_vars_line > $this->current_event_line)
+ {
+ // Reached the start of the file
+ throw new \LogicException("Can not find end of \$vars array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+ }
+
+ return $this->get_vars_from_single_line_array('$vars = array(' . implode(", ", $var_lines) . ');', false);
+ }
+
+ /**
+ * Find the $vars array
+ *
+ * @return array List of variables
+ * @throws \LogicException
+ */
+ public function get_vars_from_docblock()
+ {
+ $doc_vars = array();
+ $current_doc_line = 1;
+ $found_comment_end = false;
+ while (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") !== '/**')
+ {
+ if (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") === '*/')
+ {
+ $found_comment_end = true;
+ }
+
+ if ($found_comment_end)
+ {
+ $var_line = trim($this->file_lines[$this->current_event_line - $current_doc_line]);
+ $var_line = preg_replace('!\s+!', ' ', $var_line);
+ if (strpos($var_line, '* @var ') === 0)
+ {
+ $doc_line = explode(' ', $var_line, 5);
+ if (sizeof($doc_line) !== 5)
+ {
+ throw new \LogicException("Found invalid line '{$this->file_lines[$this->current_event_line - $current_doc_line]}' "
+ . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
+ }
+ $doc_vars[] = $doc_line[3];
+ }
+ }
+
+ $current_doc_line++;
+ if ($current_doc_line > $this->current_event_line)
+ {
+ // Reached the start of the file
+ throw new \LogicException("Can not find end of docblock for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+ }
+
+ if (empty($doc_vars))
+ {
+ // Reached the start of the file
+ throw new \LogicException("Can not find @var lines for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
+ }
+
+ foreach ($doc_vars as $var)
+ {
+ if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var))
+ {
+ throw new \LogicException("Found invalid @var '{$var}' in docblock for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 4);
+ }
+ }
+
+ sort($doc_vars);
+ return $doc_vars;
+ }
+
+ /**
+ * Find the "@since" Information line
+ *
+ * @return int Absolute line number
+ * @throws \LogicException
+ */
+ public function find_since()
+ {
+ return $this->find_tag('since', array('event', 'var'));
+ }
+
+ /**
+ * Find the "@event" Information line
+ *
+ * @return int Absolute line number
+ */
+ public function find_event()
+ {
+ return $this->find_tag('event', array());
+ }
+
+ /**
+ * Find a "@*" Information line
+ *
+ * @param string $find_tag Name of the tag we are trying to find
+ * @param array $disallowed_tags List of tags that must not appear between
+ * the tag and the actual event
+ * @return int Absolute line number
+ * @throws \LogicException
+ */
+ public function find_tag($find_tag, $disallowed_tags)
+ {
+ $find_tag_line = 0;
+ $found_comment_end = false;
+ while (strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t"), '* @' . $find_tag . ' ') !== 0)
+ {
+ if ($found_comment_end && ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '/**')
+ {
+ // Reached the start of this doc block
+ throw new \LogicException("Can not find '@{$find_tag}' information for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
+ }
+
+ foreach ($disallowed_tags as $disallowed_tag)
+ {
+ if ($found_comment_end && strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t"), '* @' . $disallowed_tag) === 0)
+ {
+ // Found @var after the @since
+ throw new \LogicException("Found '@{$disallowed_tag}' information after '@{$find_tag}' for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
+ }
+ }
+
+ if (ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '*/')
+ {
+ $found_comment_end = true;
+ }
+
+ $find_tag_line++;
+ if ($find_tag_line >= $this->current_event_line)
+ {
+ // Reached the start of the file
+ throw new \LogicException("Can not find '@{$find_tag}' information for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+ }
+
+ return $this->current_event_line - $find_tag_line;
+ }
+
+ /**
+ * Find a "@*" Information line
+ *
+ * @return int Absolute line number
+ * @throws \LogicException
+ */
+ public function find_description()
+ {
+ $find_desc_line = 0;
+ while (ltrim($this->file_lines[$this->current_event_line - $find_desc_line], "\t") !== '/**')
+ {
+ $find_desc_line++;
+ if ($find_desc_line > $this->current_event_line)
+ {
+ // Reached the start of the file
+ throw new \LogicException("Can not find a description for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
+ }
+ }
+
+ $find_desc_line = $this->current_event_line - $find_desc_line + 1;
+
+ $desc = trim($this->file_lines[$find_desc_line]);
+ if (strpos($desc, '* @') === 0 || $desc[0] !== '*' || substr($desc, 1) == '')
+ {
+ // First line of the doc block is a @-line, empty or only contains "*"
+ throw new \LogicException("Can not find a description for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+
+ return $find_desc_line;
+ }
+
+ /**
+ * Validate "@since" Information
+ *
+ * @param string $line
+ * @return string
+ * @throws \LogicException
+ */
+ public function validate_since($line)
+ {
+ $match = array();
+ preg_match('#^\* @since (\d+\.\d+\.\d+(?:-(?:a|b|rc|pl)\d+)?)$#', ltrim($line, "\t"), $match);
+ if (!isset($match[1]))
+ {
+ throw new \LogicException("Invalid '@since' information for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'");
+ }
+
+ return $match[1];
+ }
+
+ /**
+ * Validate "@event" Information
+ *
+ * @param string $event_name
+ * @param string $line
+ * @return string
+ * @throws \LogicException
+ */
+ public function validate_event($event_name, $line)
+ {
+ $event = substr(ltrim($line, "\t"), strlen('* @event '));
+
+ if ($event !== trim($event))
+ {
+ throw new \LogicException("Invalid '@event' information for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
+ }
+
+ if ($event !== $event_name)
+ {
+ throw new \LogicException("Event name does not match '@event' tag for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
+ }
+
+ return $event;
+ }
+
+ /**
+ * Validates that two arrays contain the same strings
+ *
+ * @param array $vars_array Variables found in the array line
+ * @param array $vars_docblock Variables found in the doc block
+ * @return null
+ * @throws \LogicException
+ */
+ public function validate_vars_docblock_array($vars_array, $vars_docblock)
+ {
+ $vars_array = array_unique($vars_array);
+ $vars_docblock = array_unique($vars_docblock);
+ $sizeof_vars_array = sizeof($vars_array);
+
+ if ($sizeof_vars_array !== sizeof($vars_docblock) || $sizeof_vars_array !== sizeof(array_intersect($vars_array, $vars_docblock)))
+ {
+ throw new \LogicException("\$vars array does not match the list of '@var' tags for event "
+ . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'");
+ }
+ }
+}
diff --git a/phpBB/phpbb/event/recursive_event_filter_iterator.php b/phpBB/phpbb/event/recursive_event_filter_iterator.php
new file mode 100644
index 0000000000..ef2f2ec0ed
--- /dev/null
+++ b/phpBB/phpbb/event/recursive_event_filter_iterator.php
@@ -0,0 +1,70 @@
+<?php
+/**
+*
+* @package event
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\event;
+
+/**
+* Class recursive_event_filter_iterator
+*
+* This filter ignores directories and files starting with a dot.
+* It also skips some directories that do not contain events anyway,
+* such as e.g. files/, store/ and vendor/
+*
+* @package phpbb\event
+*/
+class recursive_event_filter_iterator extends \RecursiveFilterIterator
+{
+ protected $root_path;
+
+ /**
+ * Construct
+ *
+ * @param \RecursiveIterator $iterator
+ * @param string $root_path
+ */
+ public function __construct(\RecursiveIterator $iterator, $root_path)
+ {
+ $this->root_path = str_replace(DIRECTORY_SEPARATOR, '/', $root_path);
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Return the inner iterator's children contained in a recursive_event_filter_iterator
+ *
+ * @return recursive_event_filter_iterator
+ */
+ public function getChildren() {
+ return new self($this->getInnerIterator()->getChildren(), $this->root_path);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function accept()
+ {
+ $relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $this->current());
+ $filename = $this->current()->getFilename();
+
+ return (substr($relative_path, -4) === '.php' || $this->current()->isDir())
+ && $filename[0] !== '.'
+ && strpos($relative_path, $this->root_path . 'cache/') !== 0
+ && strpos($relative_path, $this->root_path . 'develop/') !== 0
+ && strpos($relative_path, $this->root_path . 'docs/') !== 0
+ && strpos($relative_path, $this->root_path . 'ext/') !== 0
+ && strpos($relative_path, $this->root_path . 'files/') !== 0
+ && strpos($relative_path, $this->root_path . 'includes/utf/') !== 0
+ && strpos($relative_path, $this->root_path . 'language/') !== 0
+ && strpos($relative_path, $this->root_path . 'phpbb/db/migration/data/') !== 0
+ && strpos($relative_path, $this->root_path . 'phpbb/event/') !== 0
+ && strpos($relative_path, $this->root_path . 'store/') !== 0
+ && strpos($relative_path, $this->root_path . 'tests/') !== 0
+ && strpos($relative_path, $this->root_path . 'vendor/') !== 0
+ ;
+ }
+}
diff --git a/phpBB/phpbb/extension/exception.php b/phpBB/phpbb/extension/exception.php
index b1f4997fdd..82327c9d5e 100644
--- a/phpBB/phpbb/extension/exception.php
+++ b/phpBB/phpbb/extension/exception.php
@@ -18,4 +18,4 @@ class exception extends \UnexpectedValueException
{
return $this->getMessage();
}
-} \ No newline at end of file
+}
diff --git a/phpBB/phpbb/extension/finder.php b/phpBB/phpbb/extension/finder.php
index c9c16ae6d5..6cc6e1808a 100644
--- a/phpBB/phpbb/extension/finder.php
+++ b/phpBB/phpbb/extension/finder.php
@@ -475,14 +475,19 @@ class finder
}
$directory_pattern = '#' . $directory_pattern . '#';
- $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST);
+ $iterator = new \RecursiveIteratorIterator(
+ new \phpbb\recursive_dot_prefix_filter_iterator(
+ new \RecursiveDirectoryIterator(
+ $path,
+ \FilesystemIterator::SKIP_DOTS
+ )
+ ),
+ \RecursiveIteratorIterator::SELF_FIRST
+ );
+
foreach ($iterator as $file_info)
{
$filename = $file_info->getFilename();
- if ($filename == '.' || $filename == '..')
- {
- continue;
- }
if ($file_info->isDir() == $is_dir)
{
diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php
index 23b281deaa..b22fbf07a6 100644
--- a/phpBB/phpbb/extension/manager.php
+++ b/phpBB/phpbb/extension/manager.php
@@ -34,7 +34,7 @@ class manager
* Creates a manager and loads information from database
*
* @param ContainerInterface $container A container
- * @param \phpbb\db\driver\driver $db A database connection
+ * @param \phpbb\db\driver\driver_interface $db A database connection
* @param \phpbb\config\config $config \phpbb\config\config
* @param \phpbb\filesystem $filesystem
* @param string $extension_table The name of the table holding extensions
@@ -43,7 +43,7 @@ class manager
* @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext
*/
- public function __construct(ContainerInterface $container, \phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext')
+ public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext')
{
$this->container = $container;
$this->phpbb_root_path = $phpbb_root_path;
@@ -212,6 +212,11 @@ class manager
$this->cache->purge();
}
+ if ($active)
+ {
+ $this->config->increment('assets_version', 1);
+ }
+
return !$active;
}
diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php
index 66cdb86513..c90445ee09 100644
--- a/phpBB/phpbb/extension/metadata_manager.php
+++ b/phpBB/phpbb/extension/metadata_manager.php
@@ -196,7 +196,7 @@ class metadata_manager
$fields = array(
'name' => '#^[a-zA-Z0-9_\x7f-\xff]{2,}/[a-zA-Z0-9_\x7f-\xff]{2,}$#',
'type' => '#^phpbb-extension$#',
- 'licence' => '#.+#',
+ 'license' => '#.+#',
'version' => '#.+#',
);
@@ -351,7 +351,7 @@ class metadata_manager
'META_HOMEPAGE' => (isset($this->metadata['homepage'])) ? $this->metadata['homepage'] : '',
'META_VERSION' => (isset($this->metadata['version'])) ? htmlspecialchars($this->metadata['version']) : '',
'META_TIME' => (isset($this->metadata['time'])) ? htmlspecialchars($this->metadata['time']) : '',
- 'META_LICENCE' => htmlspecialchars($this->metadata['licence']),
+ 'META_LICENSE' => htmlspecialchars($this->metadata['license']),
'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? htmlspecialchars($this->metadata['require']['php']) : '',
'META_REQUIRE_PHP_FAIL' => !$this->validate_require_php(),
diff --git a/phpBB/phpbb/feed/attachments_base.php b/phpBB/phpbb/feed/attachments_base.php
new file mode 100644
index 0000000000..a9a8175928
--- /dev/null
+++ b/phpBB/phpbb/feed/attachments_base.php
@@ -0,0 +1,83 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\feed;
+
+/**
+* Abstract class for feeds displaying attachments
+*
+* @package phpBB3
+*/
+abstract class attachments_base extends \phpbb\feed\base
+{
+ /**
+ * Attachments that may be displayed
+ */
+ protected $attachments = array();
+
+ /**
+ * Retrieve the list of attachments that may be displayed
+ */
+ protected function fetch_attachments()
+ {
+ $sql_array = array(
+ 'SELECT' => 'a.*',
+ 'FROM' => array(
+ ATTACHMENTS_TABLE => 'a'
+ ),
+ 'WHERE' => 'a.in_message = 0 ',
+ 'ORDER_BY' => 'a.filetime DESC, a.post_msg_id ASC',
+ );
+
+ if (isset($this->topic_id))
+ {
+ $sql_array['WHERE'] .= 'AND a.topic_id = ' . (int) $this->topic_id;
+ }
+ else if (isset($this->forum_id))
+ {
+ $sql_array['LEFT_JOIN'] = array(
+ array(
+ 'FROM' => array(TOPICS_TABLE => 't'),
+ 'ON' => 'a.topic_id = t.topic_id',
+ )
+ );
+ $sql_array['WHERE'] .= 'AND t.forum_id = ' . (int) $this->forum_id;
+ }
+
+ $sql = $this->db->sql_build_query('SELECT', $sql_array);
+ $result = $this->db->sql_query($sql);
+
+ // Set attachments in feed items
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->attachments[$row['post_msg_id']][] = $row;
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function open()
+ {
+ parent::open();
+ $this->fetch_attachments();
+ }
+
+ /**
+ * Get attachments related to a given post
+ *
+ * @param $post_id int Post id
+ * @return mixed Attachments related to $post_id
+ */
+ public function get_attachments($post_id)
+ {
+ return $this->attachments[$post_id];
+ }
+}
diff --git a/phpBB/phpbb/feed/base.php b/phpBB/phpbb/feed/base.php
index e6c1e606fa..0e3a80ebb8 100644
--- a/phpBB/phpbb/feed/base.php
+++ b/phpBB/phpbb/feed/base.php
@@ -25,7 +25,7 @@ abstract class base
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\cache\driver\driver_interface */
@@ -70,7 +70,7 @@ abstract class base
*
* @param \phpbb\feed\helper $helper Feed helper
* @param \phpbb\config\config $config Config object
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param \phpbb\cache\driver\driver_interface $cache Cache object
* @param \phpbb\user $user User object
* @param \phpbb\auth\auth $auth Auth object
@@ -78,7 +78,7 @@ abstract class base
* @param string $phpEx php file extension
* @return null
*/
- function __construct(\phpbb\feed\helper $helper, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\auth\auth $auth, \phpbb\content_visibility $content_visibility, $phpEx)
+ function __construct(\phpbb\feed\helper $helper, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\auth\auth $auth, \phpbb\content_visibility $content_visibility, $phpEx)
{
$this->config = $config;
$this->helper = $helper;
diff --git a/phpBB/phpbb/feed/factory.php b/phpBB/phpbb/feed/factory.php
index d370160563..742b279ef4 100644
--- a/phpBB/phpbb/feed/factory.php
+++ b/phpBB/phpbb/feed/factory.php
@@ -24,7 +24,7 @@ class factory
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/**
@@ -32,10 +32,10 @@ class factory
*
* @param objec $container Container object
* @param \phpbb\config\config $config Config object
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @return null
*/
- public function __construct($container, \phpbb\config\config $config, \phpbb\db\driver\driver $db)
+ public function __construct($container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
{
$this->container = $container;
$this->config = $config;
diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php
index 8026824ab7..8e6490923d 100644
--- a/phpBB/phpbb/feed/forum.php
+++ b/phpBB/phpbb/feed/forum.php
@@ -80,6 +80,8 @@ class forum extends \phpbb\feed\post_base
unset($forum_ids_passworded);
}
+
+ parent::open();
}
function get_sql()
@@ -109,7 +111,7 @@ class forum extends \phpbb\feed\post_base
}
$this->sql = array(
- 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
diff --git a/phpBB/phpbb/feed/helper.php b/phpBB/phpbb/feed/helper.php
index 3f2759b85e..12acf997ac 100644
--- a/phpBB/phpbb/feed/helper.php
+++ b/phpBB/phpbb/feed/helper.php
@@ -24,6 +24,9 @@ class helper
/** @var string */
protected $phpbb_root_path;
+ /** @var string */
+ protected $phpEx;
+
/**
* Constructor
*
@@ -32,11 +35,12 @@ class helper
* @param string $phpbb_root_path Root path
* @return null
*/
- public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path)
+ public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path, $phpEx)
{
$this->config = $config;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
+ $this->phpEx = $phpEx;
}
/**
@@ -81,8 +85,16 @@ class helper
/**
* Generate text content
+ *
+ * @param string $content is feed text content
+ * @param string $uid is bbcode_uid
+ * @param string $bitfield is bbcode bitfield
+ * @param int $options bbcode flag options
+ * @param int $forum_id is the forum id
+ * @param array $post_attachments is an array containing the attachments and their respective info
+ * @return string the html content to be printed for the feed
*/
- public function generate_content($content, $uid, $bitfield, $options)
+ public function generate_content($content, $uid, $bitfield, $options, $forum_id, $post_attachments)
{
if (empty($content))
{
@@ -129,8 +141,21 @@ class helper
// Remove some specials html tag, because somewhere there are a mod to allow html tags ;)
$content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', ' <strong>$1</strong> ', $content);
+ // Parse inline images to display with the feed
+ if (!empty($post_attachments))
+ {
+ $update_count = array();
+ parse_attachments($forum_id, $content, $post_attachments, $update_count);
+ $post_attachments = implode('<br />', $post_attachments);
+
+ // Convert attachments' relative path to absolute path
+ $post_attachments = str_replace($this->phpbb_root_path . 'download/file.' . $this->phpEx, $this->get_board_url() . '/download/file.' . $this->phpEx, $post_attachments);
+
+ $content .= $post_attachments;
+ }
+
// Remove Comments from inline attachments [ia]
- $content = preg_replace('#<div class="(inline-attachment|attachtitle)">(.*?)<!-- ia(.*?) -->(.*?)<!-- ia(.*?) -->(.*?)</div>#si','$4',$content);
+ $content = preg_replace('#<dd>(.*?)</dd>#','',$content);
// Replace some entities with their unicode counterpart
$entities = array(
diff --git a/phpBB/phpbb/feed/news.php b/phpBB/phpbb/feed/news.php
index 7888e73239..1b7c452a92 100644
--- a/phpBB/phpbb/feed/news.php
+++ b/phpBB/phpbb/feed/news.php
@@ -85,7 +85,7 @@ class news extends \phpbb\feed\topic_base
$this->sql = array(
'SELECT' => 'f.forum_id, f.forum_name,
t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment',
'FROM' => array(
TOPICS_TABLE => 't',
POSTS_TABLE => 'p',
diff --git a/phpBB/phpbb/feed/overall.php b/phpBB/phpbb/feed/overall.php
index 4545ba5c64..d99200475e 100644
--- a/phpBB/phpbb/feed/overall.php
+++ b/phpBB/phpbb/feed/overall.php
@@ -53,7 +53,7 @@ class overall extends \phpbb\feed\post_base
// Get the actual data
$this->sql = array(
'SELECT' => 'f.forum_id, f.forum_name, ' .
- 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'u.username, u.user_id',
'FROM' => array(
USERS_TABLE => 'u',
diff --git a/phpBB/phpbb/feed/post_base.php b/phpBB/phpbb/feed/post_base.php
index 42c5eea9e3..de98f446f3 100644
--- a/phpBB/phpbb/feed/post_base.php
+++ b/phpBB/phpbb/feed/post_base.php
@@ -14,9 +14,10 @@ namespace phpbb\feed;
*
* @package phpBB3
*/
-abstract class post_base extends \phpbb\feed\base
+abstract class post_base extends \phpbb\feed\attachments_base
{
var $num_items = 'feed_limit_post';
+ var $attachments = array();
function set_keys()
{
diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php
index 09f377dd10..fb49aa65cc 100644
--- a/phpBB/phpbb/feed/topic.php
+++ b/phpBB/phpbb/feed/topic.php
@@ -83,12 +83,14 @@ class topic extends \phpbb\feed\post_base
unset($forum_ids_passworded);
}
+
+ parent::open();
}
function get_sql()
{
$this->sql = array(
- 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
diff --git a/phpBB/phpbb/feed/topic_base.php b/phpBB/phpbb/feed/topic_base.php
index 7e28e67b82..e8639a6fa6 100644
--- a/phpBB/phpbb/feed/topic_base.php
+++ b/phpBB/phpbb/feed/topic_base.php
@@ -14,7 +14,7 @@ namespace phpbb\feed;
*
* @package phpBB3
*/
-abstract class topic_base extends \phpbb\feed\base
+abstract class topic_base extends \phpbb\feed\attachments_base
{
var $num_items = 'feed_limit_topic';
diff --git a/phpBB/phpbb/feed/topics.php b/phpBB/phpbb/feed/topics.php
index bdc858e947..e8b9f6de6c 100644
--- a/phpBB/phpbb/feed/topics.php
+++ b/phpBB/phpbb/feed/topics.php
@@ -57,7 +57,7 @@ class topics extends \phpbb\feed\topic_base
$this->sql = array(
'SELECT' => 'f.forum_id, f.forum_name,
t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment',
'FROM' => array(
TOPICS_TABLE => 't',
POSTS_TABLE => 'p',
diff --git a/phpBB/phpbb/feed/topics_active.php b/phpBB/phpbb/feed/topics_active.php
index cc0adac2eb..809a536c2a 100644
--- a/phpBB/phpbb/feed/topics_active.php
+++ b/phpBB/phpbb/feed/topics_active.php
@@ -74,7 +74,7 @@ class topics_active extends \phpbb\feed\topic_base
'SELECT' => 'f.forum_id, f.forum_name,
t.topic_id, t.topic_title, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views,
t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment',
'FROM' => array(
TOPICS_TABLE => 't',
POSTS_TABLE => 'p',
diff --git a/phpBB/phpbb/groupposition/exception.php b/phpBB/phpbb/groupposition/exception.php
index f43502235d..9b55669524 100644
--- a/phpBB/phpbb/groupposition/exception.php
+++ b/phpBB/phpbb/groupposition/exception.php
@@ -3,7 +3,7 @@
*
* @package groupposition
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/groupposition/legend.php b/phpBB/phpbb/groupposition/legend.php
index 47ba06c006..42af005622 100644
--- a/phpBB/phpbb/groupposition/legend.php
+++ b/phpBB/phpbb/groupposition/legend.php
@@ -26,7 +26,7 @@ class legend implements \phpbb\groupposition\groupposition_interface
/**
* Database object
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -39,10 +39,10 @@ class legend implements \phpbb\groupposition\groupposition_interface
/**
* Constructor
*
- * @param \phpbb\db\driver\driver $db Database object
+ * @param \phpbb\db\driver\driver_interface $db Database object
* @param \phpbb\user $user User object
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\user $user)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user)
{
$this->db = $db;
$this->user = $user;
diff --git a/phpBB/phpbb/groupposition/teampage.php b/phpBB/phpbb/groupposition/teampage.php
index d934571ebc..4f1b102720 100644
--- a/phpBB/phpbb/groupposition/teampage.php
+++ b/phpBB/phpbb/groupposition/teampage.php
@@ -30,7 +30,7 @@ class teampage implements \phpbb\groupposition\groupposition_interface
/**
* Database object
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -49,11 +49,11 @@ class teampage implements \phpbb\groupposition\groupposition_interface
/**
* Constructor
*
- * @param \phpbb\db\driver\driver $db Database object
+ * @param \phpbb\db\driver\driver_interface $db Database object
* @param \phpbb\user $user User object
* @param \phpbb\cache\driver\driver_interface $cache Cache object
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\user $user, \phpbb\cache\driver\driver_interface $cache)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\cache\driver\driver_interface $cache)
{
$this->db = $db;
$this->user = $user;
diff --git a/phpBB/phpbb/json_response.php b/phpBB/phpbb/json_response.php
index 45c2f6cac4..e17525519a 100644
--- a/phpBB/phpbb/json_response.php
+++ b/phpBB/phpbb/json_response.php
@@ -3,7 +3,7 @@
*
* @package phpBB3
* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/lock/db.php b/phpBB/phpbb/lock/db.php
index 461adda045..2b437ef899 100644
--- a/phpBB/phpbb/lock/db.php
+++ b/phpBB/phpbb/lock/db.php
@@ -42,7 +42,7 @@ class db
/**
* A database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
private $db;
@@ -53,9 +53,9 @@ class db
*
* @param string $config_name A config variable to be used for locking
* @param array $config The phpBB configuration
- * @param \phpbb\db\driver\driver $db A database connection
+ * @param \phpbb\db\driver\driver_interface $db A database connection
*/
- public function __construct($config_name, \phpbb\config\config $config, \phpbb\db\driver\driver $db)
+ public function __construct($config_name, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
{
$this->config_name = $config_name;
$this->config = $config;
diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php
index a6ee06ebf2..e4c5ce47d9 100644
--- a/phpBB/phpbb/log/log.php
+++ b/phpBB/phpbb/log/log.php
@@ -93,10 +93,10 @@ class log implements \phpbb\log\log_interface
/**
* Constructor
*
- * @param \phpbb\db\driver\driver $db Database object
+ * @param \phpbb\db\driver\driver_interface $db Database object
* @param \phpbb\user $user User object
* @param \phpbb\auth\auth $auth Auth object
- * @param phpbb_dispatcher $phpbb_dispatcher Event dispatcher
+ * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher
* @param string $phpbb_root_path Root path
* @param string $relative_admin_path Relative admin root path
* @param string $php_ext PHP Extension
@@ -305,10 +305,18 @@ class log implements \phpbb\log\log_interface
* @var array sql_ary Array with log data we insert into the
* database. If sql_ary[log_type] is not set,
* we won't add the entry to the database.
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
- $vars = array('mode', 'user_id', 'log_ip', 'log_operation', 'log_time', 'additional_data', 'sql_ary');
- extract($this->dispatcher->trigger_event('core.add_log', $vars));
+ $vars = array(
+ 'mode',
+ 'user_id',
+ 'log_ip',
+ 'log_operation',
+ 'log_time',
+ 'additional_data',
+ 'sql_ary',
+ );
+ extract($this->dispatcher->trigger_event('core.add_log', compact($vars)));
// We didn't find a log_type, so we don't save it in the database.
if (!isset($sql_ary['log_type']))
@@ -403,10 +411,24 @@ class log implements \phpbb\log\log_interface
* is false, no entries will be returned.
* @var string sql_additional Additional conditions for the entries,
* e.g.: 'AND l.forum_id = 1'
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
- $vars = array('mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional');
- extract($this->dispatcher->trigger_event('core.get_logs_modify_type', $vars));
+ $vars = array(
+ 'mode',
+ 'count_logs',
+ 'limit',
+ 'offset',
+ 'forum_id',
+ 'topic_id',
+ 'user_id',
+ 'log_time',
+ 'sort_by',
+ 'keywords',
+ 'profile_url',
+ 'log_type',
+ 'sql_additional',
+ );
+ extract($this->dispatcher->trigger_event('core.get_logs_modify_type', compact($vars)));
if ($log_type === false)
{
@@ -424,7 +446,7 @@ class log implements \phpbb\log\log_interface
if ($count_logs)
{
$sql = 'SELECT COUNT(l.log_id) AS total_entries
- FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u
+ FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u
WHERE l.log_type = ' . (int) $log_type . '
AND l.user_id = u.user_id
AND l.log_time >= ' . (int) $log_time . "
@@ -449,7 +471,7 @@ class log implements \phpbb\log\log_interface
}
$sql = 'SELECT l.*, u.username, u.username_clean, u.user_colour
- FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u
+ FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u
WHERE l.log_type = ' . (int) $log_type . '
AND u.user_id = l.user_id
' . (($log_time) ? 'AND l.log_time >= ' . (int) $log_time : '') . "
@@ -490,7 +512,7 @@ class log implements \phpbb\log\log_interface
'topic_id' => (int) $row['topic_id'],
'viewforum' => ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false,
- 'action' => (isset($this->user->lang[$row['log_operation']])) ? $this->user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
+ 'action' => (isset($this->user->lang[$row['log_operation']])) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
);
/**
@@ -499,10 +521,10 @@ class log implements \phpbb\log\log_interface
* @event core.get_logs_modify_entry_data
* @var array row Entry data from the database
* @var array log_entry_data Entry's data which is returned
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
$vars = array('row', 'log_entry_data');
- extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', $vars));
+ extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars)));
$log[$i] = $log_entry_data;
@@ -517,12 +539,26 @@ class log implements \phpbb\log\log_interface
// arguments, if there are we fill out the arguments
// array. It doesn't matter if we add more arguments than
// placeholders.
- if ((substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) > 0)
+ $num_args = 0;
+ if (!is_array($this->user->lang[$row['log_operation']]))
+ {
+ $num_args = substr_count($this->user->lang[$row['log_operation']], '%');
+ }
+ else
+ {
+ foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string)
+ {
+ $num_args = max($num_args, substr_count($plural_string, '%'));
+ }
+ }
+
+ if (($num_args - sizeof($log_data_ary)) > 0)
{
- $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), ''));
+ $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), ''));
}
- $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary);
+ $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary);
+ $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments);
// If within the admin panel we do not censor text out
if ($this->get_is_admin())
@@ -544,6 +580,10 @@ class log implements \phpbb\log\log_interface
$log[$i]['action'] = make_clickable($log[$i]['action']);
*/
}
+ else
+ {
+ $log[$i]['action'] = $this->user->lang($log[$i]['action']);
+ }
$i++;
}
@@ -558,10 +598,10 @@ class log implements \phpbb\log\log_interface
* get the permission data
* @var array reportee_id_list Array of additional user IDs we
* get the username strings for
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
$vars = array('log', 'topic_id_list', 'reportee_id_list');
- extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', $vars));
+ extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars)));
if (sizeof($topic_id_list))
{
@@ -625,9 +665,23 @@ class log implements \phpbb\log\log_interface
$operations = array();
foreach ($this->user->lang as $key => $value)
{
- if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value))
+ if (substr($key, 0, 4) == 'LOG_')
{
- $operations[] = $key;
+ if (is_array($value))
+ {
+ foreach ($value as $plural_value)
+ {
+ if (preg_match($keywords_pattern, $plural_value))
+ {
+ $operations[] = $key;
+ break;
+ }
+ }
+ }
+ else if (preg_match($keywords_pattern, $value))
+ {
+ $operations[] = $key;
+ }
}
}
diff --git a/phpBB/phpbb/notification/exception.php b/phpBB/phpbb/notification/exception.php
index 6bdded3fd8..1b4cc89fc9 100644
--- a/phpBB/phpbb/notification/exception.php
+++ b/phpBB/phpbb/notification/exception.php
@@ -3,7 +3,7 @@
*
* @package notifications
* @copyright (c) 2013 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php
index 2e8652771b..09d9677ccd 100644
--- a/phpBB/phpbb/notification/manager.php
+++ b/phpBB/phpbb/notification/manager.php
@@ -30,7 +30,7 @@ class manager
/** @var \phpbb\config\config */
protected $config;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\cache\service */
@@ -62,7 +62,7 @@ class manager
* @param ContainerBuilder $phpbb_container
* @param \phpbb\user_loader $user_loader
* @param \phpbb\config\config $config
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\user $user
* @param string $phpbb_root_path
* @param string $php_ext
@@ -71,7 +71,7 @@ class manager
* @param string $user_notifications_table
* @return \phpbb\notification\manager
*/
- public function __construct($notification_types, $notification_methods, $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct($notification_types, $notification_methods, $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php
index 4ce42de830..2e6507d30f 100644
--- a/phpBB/phpbb/notification/method/base.php
+++ b/phpBB/phpbb/notification/method/base.php
@@ -21,7 +21,7 @@ abstract class base implements \phpbb\notification\method\method_interface
/** @var \phpbb\user_loader */
protected $user_loader;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\cache\driver\driver_interface */
@@ -59,7 +59,7 @@ abstract class base implements \phpbb\notification\method\method_interface
* Notification Method Base Constructor
*
* @param \phpbb\user_loader $user_loader
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\driver\driver_interface $cache
* @param \phpbb\user $user
* @param \phpbb\auth\auth $auth
@@ -68,7 +68,7 @@ abstract class base implements \phpbb\notification\method\method_interface
* @param string $php_ext
* @return \phpbb\notification\method\base
*/
- public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
{
$this->user_loader = $user_loader;
$this->db = $db;
diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php
index 5f146e18ff..62ea759a98 100644
--- a/phpBB/phpbb/notification/type/admin_activate_user.php
+++ b/phpBB/phpbb/notification/type/admin_activate_user.php
@@ -81,7 +81,7 @@ class admin_activate_user extends \phpbb\notification\type\base
WHERE user_type = ' . USER_FOUNDER;
$result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($sql))
+ while ($row = $this->db->sql_fetchrow($result))
{
$users[] = (int) $row['user_id'];
}
@@ -142,7 +142,7 @@ class admin_activate_user extends \phpbb\notification\type\base
*/
public function get_url()
{
- return append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, "mode=viewprofile&u={$this->item_id}");
+ return $this->user_loader->get_username($this->item_id, 'profile');
}
/**
diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php
index 51a9a704b0..5912ad62b4 100644
--- a/phpBB/phpbb/notification/type/approve_post.php
+++ b/phpBB/phpbb/notification/type/approve_post.php
@@ -35,6 +35,13 @@ class approve_post extends \phpbb\notification\type\post
protected $language_key = 'NOTIFICATION_POST_APPROVED';
/**
+ * Inherit notification read status from post.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
@@ -131,4 +138,12 @@ class approve_post extends \phpbb\notification\type\post
{
return 'post_approved';
}
+
+ /**
+ * {inheritDoc}
+ */
+ public function get_redirect_url()
+ {
+ return $this->get_url();
+ }
}
diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php
index 6229800c68..11a240e03d 100644
--- a/phpBB/phpbb/notification/type/approve_topic.php
+++ b/phpBB/phpbb/notification/type/approve_topic.php
@@ -35,6 +35,13 @@ class approve_topic extends \phpbb\notification\type\topic
protected $language_key = 'NOTIFICATION_TOPIC_APPROVED';
/**
+ * Inherit notification read status from topic.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php
index 951585853f..7d08521d40 100644
--- a/phpBB/phpbb/notification/type/base.php
+++ b/phpBB/phpbb/notification/type/base.php
@@ -21,7 +21,7 @@ abstract class base implements \phpbb\notification\type\type_interface
/** @var \phpbb\user_loader */
protected $user_loader;
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\cache\driver\driver_interface */
@@ -89,7 +89,7 @@ abstract class base implements \phpbb\notification\type\type_interface
* Notification Type Base Constructor
*
* @param \phpbb\user_loader $user_loader
- * @param \phpbb\db\driver\driver $db
+ * @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\driver\driver_interface $cache
* @param \phpbb\user $user
* @param \phpbb\auth\auth $auth
@@ -101,7 +101,7 @@ abstract class base implements \phpbb\notification\type\type_interface
* @param string $user_notifications_table
* @return \phpbb\notification\type\base
*/
- public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->user_loader = $user_loader;
$this->db = $db;
@@ -276,21 +276,31 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
+ * {inheritDoc}
+ */
+ public function get_redirect_url()
+ {
+ return $this->get_url();
+ }
+
+ /**
* Prepare to output the notification to the template
*
* @return array Template variables
*/
public function prepare_for_display()
{
+ $mark_hash = generate_link_hash('mark_notification_read');
+
if ($this->get_url())
{
- $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id);
+ $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;hash=' . $mark_hash);
}
else
{
$redirect = (($this->user->page['page_dir']) ? $this->user->page['page_dir'] . '/' : '') . $this->user->page['page_name'] . (($this->user->page['query_string']) ? '?' . $this->user->page['query_string'] : '');
- $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;redirect=' . urlencode($redirect));
+ $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;hash=' . $mark_hash . '&amp;redirect=' . urlencode($redirect));
}
return array(
diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php
index 5e6fdd2523..c981695f74 100644
--- a/phpBB/phpbb/notification/type/bookmark.php
+++ b/phpBB/phpbb/notification/type/bookmark.php
@@ -75,7 +75,7 @@ class bookmark extends \phpbb\notification\type\post
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- $users[] = $row['user_id'];
+ $users[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
@@ -110,10 +110,14 @@ class bookmark extends \phpbb\notification\type\post
unset($notify_users[$row['user_id']]);
$notification = $this->notification_manager->get_item_type_class($this->get_type(), $row);
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
- WHERE notification_id = ' . $row['notification_id'];
- $this->db->sql_query($sql);
+ $update_responders = $notification->add_responders($post);
+ if (!empty($update_responders))
+ {
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . '
+ WHERE notification_id = ' . $row['notification_id'];
+ $this->db->sql_query($sql);
+ }
}
$this->db->sql_freeresult($result);
diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php
index 411d4195c7..70de2a3e10 100644
--- a/phpBB/phpbb/notification/type/disapprove_post.php
+++ b/phpBB/phpbb/notification/type/disapprove_post.php
@@ -35,6 +35,13 @@ class disapprove_post extends \phpbb\notification\type\approve_post
protected $language_key = 'NOTIFICATION_POST_DISAPPROVED';
/**
+ * Inherit notification read status from post.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php
index 19e9d468ce..d39201d928 100644
--- a/phpBB/phpbb/notification/type/disapprove_topic.php
+++ b/phpBB/phpbb/notification/type/disapprove_topic.php
@@ -35,6 +35,13 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
protected $language_key = 'NOTIFICATION_TOPIC_DISAPPROVED';
/**
+ * Inherit notification read status from topic.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php
index c2854c17af..93fbcbde22 100644
--- a/phpBB/phpbb/notification/type/post.php
+++ b/phpBB/phpbb/notification/type/post.php
@@ -35,6 +35,13 @@ class post extends \phpbb\notification\type\base
protected $language_key = 'NOTIFICATION_POST';
/**
+ * Inherit notification read status from post.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = true;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
@@ -96,7 +103,7 @@ class post extends \phpbb\notification\type\base
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- $users[] = $row['user_id'];
+ $users[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
@@ -108,7 +115,7 @@ class post extends \phpbb\notification\type\base
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- $users[] = $row['user_id'];
+ $users[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
@@ -145,10 +152,14 @@ class post extends \phpbb\notification\type\base
unset($notify_users[$row['user_id']]);
$notification = $this->notification_manager->get_item_type_class($this->get_type(), $row);
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
- WHERE notification_id = ' . $row['notification_id'];
- $this->db->sql_query($sql);
+ $update_responders = $notification->add_responders($post);
+ if (!empty($update_responders))
+ {
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . '
+ WHERE notification_id = ' . $row['notification_id'];
+ $this->db->sql_query($sql);
+ }
}
$this->db->sql_freeresult($result);
@@ -198,18 +209,21 @@ class post extends \phpbb\notification\type\base
$usernames[] = $this->user_loader->get_username($responder['poster_id'], 'no_profile');
}
}
- $lang_key = $this->language_key;
- if ($trimmed_responders_cnt)
+ if ($trimmed_responders_cnt > 20)
{
- $lang_key .= '_TRIMMED';
+ $usernames[] = $this->user->lang('NOTIFICATION_MANY_OTHERS');
+ }
+ else if ($trimmed_responders_cnt)
+ {
+ $usernames[] = $this->user->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt);
}
return $this->user->lang(
- $lang_key,
- implode($this->user->lang['COMMA_SEPARATOR'], $usernames),
+ $this->language_key,
+ phpbb_generate_string_list($usernames, $this->user),
censor_text($this->get_data('topic_title')),
- $trimmed_responders_cnt
+ $responders_cnt
);
}
@@ -264,6 +278,14 @@ class post extends \phpbb\notification\type\base
}
/**
+ * {inheritDoc}
+ */
+ public function get_redirect_url()
+ {
+ return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "t={$this->item_parent_id}&amp;view=unread#unread");
+ }
+
+ /**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
@@ -315,7 +337,7 @@ class post extends \phpbb\notification\type\base
*/
public function pre_create_insert_array($post, $notify_users)
{
- if (!sizeof($notify_users))
+ if (!sizeof($notify_users) || !$this->inherit_read_status)
{
return array();
}
@@ -360,7 +382,7 @@ class post extends \phpbb\notification\type\base
// Topics can be "read" before they are public (while awaiting approval).
// Make sure that if the user has read the topic, it's marked as read in the notification
- if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time)
+ if ($this->inherit_read_status && isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time)
{
$this->notification_read = true;
}
@@ -378,19 +400,27 @@ class post extends \phpbb\notification\type\base
// Do not add them as a responder if they were the original poster that created the notification
if ($this->get_data('poster_id') == $post['poster_id'])
{
- return array('notification_data' => serialize($this->get_data(false)));
+ return array();
}
$responders = $this->get_data('responders');
$responders = ($responders === null) ? array() : $responders;
+ // Do not add more than 25 responders,
+ // we trim the username list to "a, b, c and x others" anyway
+ // so there is no use to add all of them anyway.
+ if (sizeof($responders) > 25)
+ {
+ return array();
+ }
+
foreach ($responders as $responder)
{
// Do not add them as a responder multiple times
if ($responder['poster_id'] == $post['poster_id'])
{
- return array('notification_data' => serialize($this->get_data(false)));
+ return array();
}
}
@@ -401,6 +431,15 @@ class post extends \phpbb\notification\type\base
$this->set_data('responders', $responders);
- return array('notification_data' => serialize($this->get_data(false)));
+ $serialized_data = serialize($this->get_data(false));
+
+ // If the data is longer then 4000 characters, it would cause a SQL error.
+ // We don't add the username to the list if this is the case.
+ if (utf8_strlen($serialized_data) >= 4000)
+ {
+ return array();
+ }
+
+ return array('notification_data' => $serialized_data);
}
}
diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php
index db16763583..56dfcce588 100644
--- a/phpBB/phpbb/notification/type/post_in_queue.php
+++ b/phpBB/phpbb/notification/type/post_in_queue.php
@@ -119,6 +119,14 @@ class post_in_queue extends \phpbb\notification\type\post
}
/**
+ * {inheritDoc}
+ */
+ public function get_redirect_url()
+ {
+ return parent::get_url();
+ }
+
+ /**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php
index e8527261d8..f4b4d763eb 100644
--- a/phpBB/phpbb/notification/type/quote.php
+++ b/phpBB/phpbb/notification/type/quote.php
@@ -94,7 +94,7 @@ class quote extends \phpbb\notification\type\post
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- $users[] = $row['user_id'];
+ $users[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
@@ -113,29 +113,6 @@ class quote extends \phpbb\notification\type\post
$notify_users = $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], $options);
- // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
- $update_notifications = array();
- $sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
- AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . '
- AND n.notification_read = 0
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- // Do not create a new notification
- unset($notify_users[$row['user_id']]);
-
- $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row);
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
- WHERE notification_id = ' . $row['notification_id'];
- $this->db->sql_query($sql);
- }
- $this->db->sql_freeresult($result);
-
return $notify_users;
}
@@ -191,6 +168,14 @@ class quote extends \phpbb\notification\type\post
}
/**
+ * {inheritDoc}
+ */
+ public function get_redirect_url()
+ {
+ return $this->get_url();
+ }
+
+ /**
* Get email template
*
* @return string|bool
diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php
index 9d2aac329e..56485f5d37 100644
--- a/phpBB/phpbb/notification/type/report_pm_closed.php
+++ b/phpBB/phpbb/notification/type/report_pm_closed.php
@@ -114,7 +114,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
*/
public function get_avatar()
{
- return $this->get_user_avatar($this->get_data('closer_id'));
+ return $this->user_loader->get_avatar($this->get_data('closer_id'));
}
/**
diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php
index 89b497efa6..9bf035b91e 100644
--- a/phpBB/phpbb/notification/type/report_post.php
+++ b/phpBB/phpbb/notification/type/report_post.php
@@ -35,6 +35,13 @@ class report_post extends \phpbb\notification\type\post_in_queue
protected $language_key = 'NOTIFICATION_REPORT_POST';
/**
+ * Inherit notification read status from post.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
+ /**
* Permission to check for (in find_users_for_notification)
*
* @var string Permission name
diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php
index 5874d48e31..fff45612b3 100644
--- a/phpBB/phpbb/notification/type/report_post_closed.php
+++ b/phpBB/phpbb/notification/type/report_post_closed.php
@@ -41,6 +41,13 @@ class report_post_closed extends \phpbb\notification\type\post
*/
protected $language_key = 'NOTIFICATION_REPORT_CLOSED';
+ /**
+ * Inherit notification read status from post.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = false;
+
public function is_available()
{
return false;
diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php
index 6198881d8d..635d05bccd 100644
--- a/phpBB/phpbb/notification/type/topic.php
+++ b/phpBB/phpbb/notification/type/topic.php
@@ -35,6 +35,13 @@ class topic extends \phpbb\notification\type\base
protected $language_key = 'NOTIFICATION_TOPIC';
/**
+ * Inherit notification read status from topic.
+ *
+ * @var bool
+ */
+ protected $inherit_read_status = true;
+
+ /**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
@@ -96,7 +103,7 @@ class topic extends \phpbb\notification\type\base
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- $users[] = $row['user_id'];
+ $users[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
@@ -220,7 +227,7 @@ class topic extends \phpbb\notification\type\base
*/
public function pre_create_insert_array($post, $notify_users)
{
- if (!sizeof($notify_users))
+ if (!sizeof($notify_users) || !$this->inherit_read_status)
{
return array();
}
@@ -261,7 +268,7 @@ class topic extends \phpbb\notification\type\base
// Topics can be "read" before they are public (while awaiting approval).
// Make sure that if the user has read the topic, it's marked as read in the notification
- if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time)
+ if ($this->inherit_read_status && isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->notification_time)
{
$this->notification_read = true;
}
diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php
index e3e6898172..2f465aae2b 100644
--- a/phpBB/phpbb/notification/type/type_interface.php
+++ b/phpBB/phpbb/notification/type/type_interface.php
@@ -99,6 +99,13 @@ interface type_interface
public function get_url();
/**
+ * Get the url to redirect after the item has been marked as read
+ *
+ * @return string URL
+ */
+ public function get_redirect_url();
+
+ /**
* URL to unsubscribe to this notification
*
* @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item
diff --git a/phpBB/phpbb/pagination.php b/phpBB/phpbb/pagination.php
index 467dc2157f..6a7631c89d 100644
--- a/phpBB/phpbb/pagination.php
+++ b/phpBB/phpbb/pagination.php
@@ -22,11 +22,13 @@ class pagination
*
* @param \phpbb\template\template $template
* @param \phpbb\user $user
+ * @param \phpbb\controller\helper $helper
*/
- public function __construct(\phpbb\template\template $template, \phpbb\user $user)
+ public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\controller\helper $helper)
{
$this->template = $template;
$this->user = $user;
+ $this->helper = $helper;
}
/**
@@ -44,9 +46,26 @@ class pagination
*/
protected function generate_page_link($base_url, $on_page, $start_name, $per_page)
{
- if (strpos($start_name, '%d') !== false)
+ if (!is_string($base_url))
{
- return ($on_page > 1) ? sprintf($base_url, (int) $on_page) : str_replace($start_name, '', $base_url);
+ if (is_array($base_url['routes']))
+ {
+ $route = ($on_page > 1) ? $base_url['routes'][1] : $base_url['routes'][0];
+ }
+ else
+ {
+ $route = $base_url['routes'];
+ }
+ $params = (isset($base_url['params'])) ? $base_url['params'] : array();
+ $is_amp = (isset($base_url['is_amp'])) ? $base_url['is_amp'] : true;
+ $session_id = (isset($base_url['session_id'])) ? $base_url['session_id'] : false;
+
+ if ($on_page > 1 || !is_array($base_url['routes']))
+ {
+ $params[$start_name] = (int) $on_page;
+ }
+
+ return $this->helper->route($route, $params, $is_amp, $session_id);
}
else
{
@@ -76,107 +95,104 @@ class pagination
public function generate_template_pagination($base_url, $block_var_name, $start_name, $num_items, $per_page, $start = 1, $reverse_count = false, $ignore_on_page = false)
{
$total_pages = ceil($num_items / $per_page);
-
- if ($total_pages == 1 || !$num_items)
- {
- return;
- }
-
$on_page = $this->get_on_page($per_page, $start);
-
- if ($reverse_count)
- {
- $start_page = ($total_pages > 5) ? $total_pages - 4 : 1;
- $end_page = $total_pages;
- }
- else
- {
- // What we're doing here is calculating what the "start" and "end" pages should be. We
- // do this by assuming pagination is "centered" around the currently active page with
- // the three previous and three next page links displayed. Anything more than that and
- // we display the ellipsis, likewise anything less.
- //
- // $start_page is the page at which we start creating the list. When we have five or less
- // pages we start at page 1 since there will be no ellipsis displayed. Anymore than that
- // and we calculate the start based on the active page. This is the min/max calculation.
- // First (max) would we end up starting on a page less than 1? Next (min) would we end
- // up starting so close to the end that we'd not display our minimum number of pages.
- //
- // $end_page is the last page in the list to display. Like $start_page we use a min/max to
- // determine this number. Again at most five pages? Then just display them all. More than
- // five and we first (min) determine whether we'd end up listing more pages than exist.
- // We then (max) ensure we're displaying the minimum number of pages.
- $start_page = ($total_pages > 5) ? min(max(1, $on_page - 3), $total_pages - 4) : 1;
- $end_page = ($total_pages > 5) ? max(min($total_pages, $on_page + 3), 5) : $total_pages;
- }
-
$u_previous_page = $u_next_page = '';
- if ($on_page != 1)
- {
- $u_previous_page = $this->generate_page_link($base_url, $on_page - 1, $start_name, $per_page);
- $this->template->assign_block_vars($block_var_name, array(
- 'PAGE_NUMBER' => '',
- 'PAGE_URL' => $u_previous_page,
- 'S_IS_CURRENT' => false,
- 'S_IS_PREV' => true,
- 'S_IS_NEXT' => false,
- 'S_IS_ELLIPSIS' => false,
- ));
- }
-
- // This do...while exists purely to negate the need for start and end assign_block_vars, i.e.
- // to display the first and last page in the list plus any ellipsis. We use this loop to jump
- // around a little within the list depending on where we're starting (and ending).
- $at_page = 1;
- do
+ if ($total_pages > 1)
{
- // We decide whether to display the ellipsis during the loop. The ellipsis is always
- // displayed as either the second or penultimate item in the list. So are we at either
- // of those points and of course do we even need to display it, i.e. is the list starting
- // on at least page 3 and ending three pages before the final item.
- $this->template->assign_block_vars($block_var_name, array(
- 'PAGE_NUMBER' => $at_page,
- 'PAGE_URL' => $this->generate_page_link($base_url, $at_page, $start_name, $per_page),
- 'S_IS_CURRENT' => (!$ignore_on_page && $at_page == $on_page),
- 'S_IS_NEXT' => false,
- 'S_IS_PREV' => false,
- 'S_IS_ELLIPSIS' => ($at_page == 2 && $start_page > 2) || ($at_page == $total_pages - 1 && $end_page < $total_pages - 1),
- ));
-
- // We may need to jump around in the list depending on whether we have or need to display
- // the ellipsis. Are we on page 2 and are we more than one page away from the start
- // of the list? Yes? Then we jump to the start of the list. Likewise are we at the end of
- // the list and are there more than two pages left in total? Yes? Then jump to the penultimate
- // page (so we can display the ellipsis next pass). Else, increment the counter and keep
- // going
- if ($at_page == 2 && $at_page < $start_page - 1)
+ if ($reverse_count)
{
- $at_page = $start_page;
+ $start_page = ($total_pages > 5) ? $total_pages - 4 : 1;
+ $end_page = $total_pages;
}
- else if ($at_page == $end_page && $end_page < $total_pages - 1)
+ else
{
- $at_page = $total_pages - 1;
+ // What we're doing here is calculating what the "start" and "end" pages should be. We
+ // do this by assuming pagination is "centered" around the currently active page with
+ // the three previous and three next page links displayed. Anything more than that and
+ // we display the ellipsis, likewise anything less.
+ //
+ // $start_page is the page at which we start creating the list. When we have five or less
+ // pages we start at page 1 since there will be no ellipsis displayed. Anymore than that
+ // and we calculate the start based on the active page. This is the min/max calculation.
+ // First (max) would we end up starting on a page less than 1? Next (min) would we end
+ // up starting so close to the end that we'd not display our minimum number of pages.
+ //
+ // $end_page is the last page in the list to display. Like $start_page we use a min/max to
+ // determine this number. Again at most five pages? Then just display them all. More than
+ // five and we first (min) determine whether we'd end up listing more pages than exist.
+ // We then (max) ensure we're displaying the minimum number of pages.
+ $start_page = ($total_pages > 5) ? min(max(1, $on_page - 3), $total_pages - 4) : 1;
+ $end_page = ($total_pages > 5) ? max(min($total_pages, $on_page + 3), 5) : $total_pages;
}
- else
+
+ if ($on_page != 1)
{
- $at_page++;
+ $u_previous_page = $this->generate_page_link($base_url, $on_page - 1, $start_name, $per_page);
+
+ $this->template->assign_block_vars($block_var_name, array(
+ 'PAGE_NUMBER' => '',
+ 'PAGE_URL' => $u_previous_page,
+ 'S_IS_CURRENT' => false,
+ 'S_IS_PREV' => true,
+ 'S_IS_NEXT' => false,
+ 'S_IS_ELLIPSIS' => false,
+ ));
}
- }
- while ($at_page <= $total_pages);
- if ($on_page != $total_pages)
- {
- $u_next_page = $this->generate_page_link($base_url, $on_page + 1, $start_name, $per_page);
+ // This do...while exists purely to negate the need for start and end assign_block_vars, i.e.
+ // to display the first and last page in the list plus any ellipsis. We use this loop to jump
+ // around a little within the list depending on where we're starting (and ending).
+ $at_page = 1;
+ do
+ {
+ // We decide whether to display the ellipsis during the loop. The ellipsis is always
+ // displayed as either the second or penultimate item in the list. So are we at either
+ // of those points and of course do we even need to display it, i.e. is the list starting
+ // on at least page 3 and ending three pages before the final item.
+ $this->template->assign_block_vars($block_var_name, array(
+ 'PAGE_NUMBER' => $at_page,
+ 'PAGE_URL' => $this->generate_page_link($base_url, $at_page, $start_name, $per_page),
+ 'S_IS_CURRENT' => (!$ignore_on_page && $at_page == $on_page),
+ 'S_IS_NEXT' => false,
+ 'S_IS_PREV' => false,
+ 'S_IS_ELLIPSIS' => ($at_page == 2 && $start_page > 2) || ($at_page == $total_pages - 1 && $end_page < $total_pages - 1),
+ ));
- $this->template->assign_block_vars($block_var_name, array(
- 'PAGE_NUMBER' => '',
- 'PAGE_URL' => $u_next_page,
- 'S_IS_CURRENT' => false,
- 'S_IS_PREV' => false,
- 'S_IS_NEXT' => true,
- 'S_IS_ELLIPSIS' => false,
- ));
+ // We may need to jump around in the list depending on whether we have or need to display
+ // the ellipsis. Are we on page 2 and are we more than one page away from the start
+ // of the list? Yes? Then we jump to the start of the list. Likewise are we at the end of
+ // the list and are there more than two pages left in total? Yes? Then jump to the penultimate
+ // page (so we can display the ellipsis next pass). Else, increment the counter and keep
+ // going
+ if ($at_page == 2 && $at_page < $start_page - 1)
+ {
+ $at_page = $start_page;
+ }
+ else if ($at_page == $end_page && $end_page < $total_pages - 1)
+ {
+ $at_page = $total_pages - 1;
+ }
+ else
+ {
+ $at_page++;
+ }
+ }
+ while ($at_page <= $total_pages);
+
+ if ($on_page != $total_pages)
+ {
+ $u_next_page = $this->generate_page_link($base_url, $on_page + 1, $start_name, $per_page);
+
+ $this->template->assign_block_vars($block_var_name, array(
+ 'PAGE_NUMBER' => '',
+ 'PAGE_URL' => $u_next_page,
+ 'S_IS_CURRENT' => false,
+ 'S_IS_PREV' => false,
+ 'S_IS_NEXT' => true,
+ 'S_IS_ELLIPSIS' => false,
+ ));
+ }
}
// If the block_var_name is a nested block, we will use the last (most
@@ -197,12 +213,14 @@ class pagination
$tpl_prefix = ($tpl_prefix == 'PAGINATION') ? '' : $tpl_prefix . '_';
$template_array = array(
- $tpl_prefix . 'BASE_URL' => $base_url,
+ $tpl_prefix . 'BASE_URL' => is_string($base_url) ? $base_url : '',//@todo: Fix this for routes
+ $tpl_prefix . 'START_NAME' => $start_name,
$tpl_prefix . 'PER_PAGE' => $per_page,
'U_' . $tpl_prefix . 'PREVIOUS_PAGE' => ($on_page != 1) ? $u_previous_page : '',
'U_' . $tpl_prefix . 'NEXT_PAGE' => ($on_page != $total_pages) ? $u_next_page : '',
$tpl_prefix . 'TOTAL_PAGES' => $total_pages,
$tpl_prefix . 'CURRENT_PAGE' => $on_page,
+ $tpl_prefix . 'PAGE_NUMBER' => $this->on_page($num_items, $per_page, $start),
);
if ($tpl_block_name)
@@ -229,24 +247,15 @@ class pagination
/**
* Return current page
- * This function also sets certain specific template variables
*
- * @param string $base_url the base url used to call this page, used by Javascript for popup jump to page
* @param int $num_items the total number of items, posts, topics, etc.
* @param int $per_page the number of items, posts, etc. per page
* @param int $start the item which should be considered currently active, used to determine the page we're on
* @return string Descriptive pagination string (e.g. "page 1 of 10")
*/
- public function on_page($base_url, $num_items, $per_page, $start)
+ public function on_page($num_items, $per_page, $start)
{
$on_page = $this->get_on_page($per_page, $start);
-
- $this->template->assign_vars(array(
- 'PER_PAGE' => $per_page,
- 'ON_PAGE' => $on_page,
- 'BASE_URL' => $base_url,
- ));
-
return $this->user->lang('PAGE_OF', $on_page, max(ceil($num_items / $per_page), 1));
}
@@ -262,7 +271,7 @@ class pagination
{
if ($start < 0 || $start >= $num_items)
{
- return ($start < 0) ? 0 : floor(($num_items - 1) / $per_page) * $per_page;
+ return ($start < 0 || $num_items <= 0) ? 0 : floor(($num_items - 1) / $per_page) * $per_page;
}
return $start;
diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php
new file mode 100644
index 0000000000..8256fd721c
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/base.php
@@ -0,0 +1,45 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+abstract class base implements driver_interface
+{
+ /** @var phpbb\config\config */
+ protected $config;
+
+ /** @var phpbb\passwords\driver\helper */
+ protected $helper;
+
+ /** @var driver name */
+ protected $name;
+
+ /**
+ * Constructor of passwords driver object
+ *
+ * @param \phpbb\config\config $config phpBB config
+ * @param \phpbb\passwords\driver\helper $helper Password driver helper
+ */
+ public function __construct(\phpbb\config\config $config, helper $helper)
+ {
+ $this->config = $config;
+ $this->helper = $helper;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_supported()
+ {
+ return true;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php
new file mode 100644
index 0000000000..1d1b1e267d
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/bcrypt.php
@@ -0,0 +1,104 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+class bcrypt extends base
+{
+ const PREFIX = '$2a$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $salt = '')
+ {
+ // The 2x and 2y prefixes of bcrypt might not be supported
+ // Revert to 2a if this is the case
+ $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix();
+
+ // Do not support 8-bit characters with $2a$ bcrypt
+ // Also see http://www.php.net/security/crypt_blowfish.php
+ if ($prefix === self::PREFIX)
+ {
+ if (ord($password[strlen($password)-1]) & 128)
+ {
+ return false;
+ }
+ }
+
+ if ($salt == '')
+ {
+ $salt = $prefix . '10$' . $this->get_random_salt();
+ }
+
+ $hash = crypt($password, $salt);
+ if (strlen($hash) < 60)
+ {
+ return false;
+ }
+ return $hash;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash)
+ {
+ $salt = substr($hash, 0, 29);
+ if (strlen($salt) != 29)
+ {
+ return false;
+ }
+
+ if ($hash == $this->hash($password, $salt))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get a random salt value with a length of 22 characters
+ *
+ * @return string Salt for password hashing
+ */
+ protected function get_random_salt()
+ {
+ return $this->helper->hash_encode64($this->helper->get_random_salt(22), 22);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function get_settings_only($hash, $full = false)
+ {
+ if ($full)
+ {
+ $pos = stripos($hash, '$', 1) + 1;
+ $length = 22 + (strripos($hash, '$') + 1 - $pos);
+ }
+ else
+ {
+ $pos = strripos($hash, '$') + 1;
+ $length = 22;
+ }
+ return substr($hash, $pos, $length);
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php
new file mode 100644
index 0000000000..11c3617e49
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php
@@ -0,0 +1,34 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+class bcrypt_2y extends bcrypt
+{
+ const PREFIX = '$2y$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_supported()
+ {
+ return (version_compare(PHP_VERSION, '5.3.7', '<')) ? false : true;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php
new file mode 100644
index 0000000000..ebaf0626af
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/driver_interface.php
@@ -0,0 +1,60 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+interface driver_interface
+{
+ /**
+ * Check if hash type is supported
+ *
+ * @return bool True if supported, false if not
+ */
+ public function is_supported();
+
+ /**
+ * Returns the hash prefix
+ *
+ * @return string Hash prefix
+ */
+ public function get_prefix();
+
+ /**
+ * Hash the password
+ *
+ * @param string $password The password that should be hashed
+ *
+ * @return bool|string Password hash or false if something went wrong
+ * during hashing
+ */
+ public function hash($password);
+
+ /**
+ * Check the password against the supplied hash
+ *
+ * @param string $password The password to check
+ * @param string $hash The password hash to check against
+ *
+ * @return bool True if password is correct, else false
+ */
+ public function check($password, $hash);
+
+ /**
+ * Get only the settings of the specified hash
+ *
+ * @param string $hash Password hash
+ * @param bool $full Return full settings or only settings
+ * related to the salt
+ * @return string String containing the hash settings
+ */
+ public function get_settings_only($hash, $full = false);
+}
diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php
new file mode 100644
index 0000000000..4b8dc9a123
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/helper.php
@@ -0,0 +1,144 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+class helper
+{
+ /**
+ * @var phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * base64 alphabet
+ * @var string
+ */
+ public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+
+ /**
+ * Construct a driver helper object
+ *
+ * @param phpbb\config\config $config phpBB configuration
+ */
+ public function __construct(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Base64 encode hash
+ *
+ * @param string $input Input string
+ * @param int $count Input string length
+ *
+ * @return string base64 encoded string
+ */
+ public function hash_encode64($input, $count)
+ {
+ $output = '';
+ $i = 0;
+
+ do
+ {
+ $value = ord($input[$i++]);
+ $output .= $this->itoa64[$value & 0x3f];
+
+ if ($i < $count)
+ {
+ $value |= ord($input[$i]) << 8;
+ }
+
+ $output .= $this->itoa64[($value >> 6) & 0x3f];
+
+ if ($i++ >= $count)
+ {
+ break;
+ }
+
+ if ($i < $count)
+ {
+ $value |= ord($input[$i]) << 16;
+ }
+
+ $output .= $this->itoa64[($value >> 12) & 0x3f];
+
+ if ($i++ >= $count)
+ {
+ break;
+ }
+
+ $output .= $this->itoa64[($value >> 18) & 0x3f];
+ }
+ while ($i < $count);
+
+ return $output;
+ }
+
+ /**
+ * Return unique id
+ *
+ * @param string $extra Additional entropy
+ *
+ * @return string Unique id
+ */
+ public function unique_id($extra = 'c')
+ {
+ static $dss_seeded = false;
+
+ $val = $this->config['rand_seed'] . microtime();
+ $val = md5($val);
+ $this->config['rand_seed'] = md5($this->config['rand_seed'] . $val . $extra);
+
+ if ($dss_seeded !== true && ($this->config['rand_seed_last_update'] < time() - rand(1,10)))
+ {
+ $this->config->set('rand_seed_last_update', time(), true);
+ $this->config->set('rand_seed', $this->config['rand_seed'], true);
+ $dss_seeded = true;
+ }
+
+ return substr($val, 4, 16);
+ }
+
+ /**
+ * Get random salt with specified length
+ *
+ * @param int $length Salt length
+ * @param string $rand_seed Seed for random data (optional). For tests.
+ *
+ * @return string Random salt with specified length
+ */
+ public function get_random_salt($length, $rand_seed = '/dev/urandom')
+ {
+ $random = '';
+
+ if (($fh = @fopen($rand_seed, 'rb')))
+ {
+ $random = fread($fh, $length);
+ fclose($fh);
+ }
+
+ if (strlen($random) < $length)
+ {
+ $random = '';
+ $random_state = $this->unique_id();
+
+ for ($i = 0; $i < $length; $i += 16)
+ {
+ $random_state = md5($this->unique_id() . $random_state);
+ $random .= pack('H*', md5($random_state));
+ }
+ $random = substr($random, 0, $length);
+ }
+ return $random;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php
new file mode 100644
index 0000000000..80c4d7a7f0
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/phpass.php
@@ -0,0 +1,26 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+* @package passwords
+*/
+class phpass extends salted_md5
+{
+ const PREFIX = '$P$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php
new file mode 100644
index 0000000000..5c72726422
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/salted_md5.php
@@ -0,0 +1,160 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords\driver;
+
+/**
+*
+* @version Version 0.1 / slightly modified for phpBB 3.1.x (using $H$ as hash type identifier)
+*
+* Portable PHP password hashing framework.
+*
+* Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
+* the public domain.
+*
+* There's absolutely no warranty.
+*
+* The homepage URL for this framework is:
+*
+* http://www.openwall.com/phpass/
+*
+* Please be sure to update the Version line if you edit this file in any way.
+* It is suggested that you leave the main version number intact, but indicate
+* your project name (after the slash) and add your own revision information.
+*
+* Please do not change the "private" password hashing method implemented in
+* here, thereby making your hashes incompatible. However, if you must, please
+* change the hash type identifier (the "$P$") to something different.
+*
+* Obviously, since this code is in the public domain, the above are not
+* requirements (there can be none), but merely suggestions.
+*
+*/
+
+/**
+* @package passwords
+*/
+class salted_md5 extends base
+{
+ const PREFIX = '$H$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $setting = '')
+ {
+ if ($setting)
+ {
+ if (($settings = $this->get_hash_settings($setting)) === false)
+ {
+ // Return md5 of password if settings do not
+ // comply with our standards. This will only
+ // happen if pre-determined settings are
+ // directly passed to the driver. The manager
+ // will not do this. Same as the old hashing
+ // implementatio in phpBB 3.0
+ return md5($password);
+ }
+ }
+ else
+ {
+ $settings = $this->get_hash_settings($this->generate_salt());
+ }
+
+ $hash = md5($settings['salt'] . $password, true);
+ do
+ {
+ $hash = md5($hash . $password, true);
+ }
+ while (--$settings['count']);
+
+ $output = $settings['full'];
+ $output .= $this->helper->hash_encode64($hash, 16);
+
+ return $output;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash)
+ {
+ if (strlen($hash) !== 34)
+ {
+ return md5($password) === $hash;
+ }
+
+ return $hash === $this->hash($password, $hash);
+ }
+
+ /**
+ * Generate salt for hashing method
+ *
+ * @return string Salt for hashing method
+ */
+ protected function generate_salt()
+ {
+ $count = 6;
+
+ $random = $this->helper->get_random_salt($count);
+
+ $salt = $this->get_prefix();
+ $salt .= $this->helper->itoa64[min($count + 5, 30)];
+ $salt .= $this->helper->hash_encode64($random, $count);
+
+ return $salt;
+ }
+
+ /**
+ * Get hash settings
+ *
+ * @param string $hash The hash that contains the settings
+ *
+ * @return bool|array Array containing the count_log2, salt, and full
+ * hash settings string or false if supplied hash is empty
+ * or contains incorrect settings
+ */
+ public function get_hash_settings($hash)
+ {
+ if (empty($hash))
+ {
+ return false;
+ }
+
+ $count_log2 = strpos($this->helper->itoa64, $hash[3]);
+ $salt = substr($hash, 4, 8);
+
+ if ($count_log2 < 7 || $count_log2 > 30 || strlen($salt) != 8)
+ {
+ return false;
+ }
+
+ return array(
+ 'count' => 1 << $count_log2,
+ 'salt' => $salt,
+ 'full' => substr($hash, 0, 12),
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function get_settings_only($hash, $full = false)
+ {
+ return substr($hash, 3, 9);
+ }
+}
diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php
new file mode 100644
index 0000000000..95bad5805f
--- /dev/null
+++ b/phpBB/phpbb/passwords/helper.php
@@ -0,0 +1,103 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords;
+
+/**
+* @package passwords
+*/
+class helper
+{
+ /**
+ * Get hash settings from combined hash
+ *
+ * @param string $hash Password hash of combined hash
+ *
+ * @return array An array containing the hash settings for the hash
+ * types in successive order as described by the combined
+ * password hash or an empty array if hash does not
+ * properly fit the combined hash format
+ */
+ public function get_combined_hash_settings($hash)
+ {
+ $output = array();
+
+ preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match);
+ $hash_settings = substr($hash, strpos($hash, $match[1]) + strlen($match[1]) + 1);
+ $matches = explode('\\', $match[1]);
+ foreach ($matches as $cur_type)
+ {
+ $dollar_position = strpos($hash_settings, '$');
+ $output[] = substr($hash_settings, 0, ($dollar_position != false) ? $dollar_position : strlen($hash_settings));
+ $hash_settings = substr($hash_settings, $dollar_position + 1);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Combine hash prefixes, settings, and actual hash
+ *
+ * @param array $data Array containing the keys 'prefix' and 'settings'.
+ * It will hold the prefixes and settings
+ * @param string $type Data type of the supplied value
+ * @param string $value Value that should be put into the data array
+ *
+ * @return string|null Return complete combined hash if type is neither
+ * 'prefix' nor 'settings', nothing if it is
+ */
+ public function combine_hash_output(&$data, $type, $value)
+ {
+ if ($type == 'prefix')
+ {
+ $data[$type] .= ($data[$type] !== '$') ? '\\' : '';
+ $data[$type] .= str_replace('$', '', $value);
+ }
+ elseif ($type == 'settings')
+ {
+ $data[$type] .= ($data[$type] !== '$') ? '$' : '';
+ $data[$type] .= $value;
+ }
+ else
+ {
+ // Return full hash
+ return $data['prefix'] . $data['settings'] . '$' . $value;
+ }
+ }
+
+ /**
+ * Rebuild hash for hashing functions
+ *
+ * @param string $prefix Hash prefix
+ * @param string $settings Hash settings
+ *
+ * @return string Rebuilt hash for hashing functions
+ */
+ public function rebuild_hash($prefix, $settings)
+ {
+ $rebuilt_hash = $prefix;
+ if (strpos($settings, '\\') !== false)
+ {
+ $settings = str_replace('\\', '$', $settings);
+ }
+ $rebuilt_hash .= $settings;
+ return $rebuilt_hash;
+ }
+
+ /**
+ * Obtain only the actual hash after the prefixes
+ *
+ * @param string $hash The full password hash
+ * @return string Actual hash (incl. settings)
+ */
+ public function obtain_hash_only($hash)
+ {
+ return substr($hash, strripos($hash, '$') + 1);
+ }
+}
diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php
new file mode 100644
index 0000000000..0ac6b05ec4
--- /dev/null
+++ b/phpBB/phpbb/passwords/manager.php
@@ -0,0 +1,341 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\passwords;
+
+/**
+* @package passwords
+*/
+class manager
+{
+ /**
+ * Default hashing method
+ */
+ protected $type = false;
+
+ /**
+ * Hashing algorithm type map
+ * Will be used to map hash prefix to type
+ */
+ protected $type_map = false;
+
+ /**
+ * Service collection of hashing algorithms
+ * Needs to be public for passwords helper
+ */
+ public $algorithms = false;
+
+ /**
+ * Password convert flag. Signals that password should be converted
+ */
+ public $convert_flag = false;
+
+ /**
+ * Passwords helper
+ * @var phpbb\passwords\helper
+ */
+ protected $helper;
+
+ /**
+ * phpBB configuration
+ * @var phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * Construct a passwords object
+ *
+ * @param phpbb\config\config $config phpBB configuration
+ * @param array $hashing_algorithms Hashing driver
+ * service collection
+ * @param phpbb\passwords\helper $helper Passwords helper object
+ * @param string $defaults List of default driver types
+ */
+ public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults)
+ {
+ $this->config = $config;
+ $this->helper = $helper;
+
+ $this->fill_type_map($hashing_algorithms);
+ $this->register_default_type($defaults);
+ }
+
+ /**
+ * Register default type
+ * Will register the first supported type from the list of default types
+ *
+ * @param array $defaults List of default types in order from first to
+ * use to last to use
+ */
+ protected function register_default_type($defaults)
+ {
+ foreach ($defaults as $type)
+ {
+ if ($this->algorithms[$type]->is_supported())
+ {
+ $this->type = $this->algorithms[$type]->get_prefix();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Fill algorithm type map
+ *
+ * @param phpbb\di\service_collection $hashing_algorithms
+ */
+ protected function fill_type_map($hashing_algorithms)
+ {
+ foreach ($hashing_algorithms as $algorithm)
+ {
+ if (!isset($this->type_map[$algorithm->get_prefix()]))
+ {
+ $this->type_map[$algorithm->get_prefix()] = $algorithm;
+ }
+ }
+ $this->algorithms = $hashing_algorithms;
+ }
+
+ /**
+ * Get the algorithm specified by a specific prefix
+ *
+ * @param string $prefix Password hash prefix
+ *
+ * @return object|bool The hash type object or false if prefix is not
+ * supported
+ */
+ protected function get_algorithm($prefix)
+ {
+ if (isset($this->type_map[$prefix]))
+ {
+ return $this->type_map[$prefix];
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Detect the hash type of the supplied hash
+ *
+ * @param string $hash Password hash that should be checked
+ *
+ * @return object|bool The hash type object or false if the specified
+ * type is not supported
+ */
+ public function detect_algorithm($hash)
+ {
+ /*
+ * preg_match() will also show hashing algos like $2a\H$, which
+ * is a combination of bcrypt and phpass. Legacy algorithms
+ * like md5 will not be matched by this and need to be treated
+ * differently.
+ */
+ if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match))
+ {
+ return $this->get_algorithm('$H$');
+ }
+
+ // Be on the lookout for multiple hashing algorithms
+ // 2 is correct: H\2a > 2, H\P > 2
+ if (strlen($match[1]) > 2)
+ {
+ $hash_types = explode('\\', $match[1]);
+ $return_ary = array();
+ foreach ($hash_types as $type)
+ {
+ // we do not support the same hashing
+ // algorithm more than once
+ if (isset($return_ary[$type]))
+ {
+ return false;
+ }
+
+ $return_ary[$type] = $this->get_algorithm('$' . $type . '$');
+
+ if (empty($return_ary[$type]))
+ {
+ return false;
+ }
+ }
+ return $return_ary;
+ }
+
+ // get_algorithm() will automatically return false if prefix
+ // is not supported
+ return $this->get_algorithm($match[0]);
+ }
+
+ /**
+ * Hash supplied password
+ *
+ * @param string $password Password that should be hashed
+ * @param string $type Hash type. Will default to standard hash type if
+ * none is supplied
+ * @return string|bool Password hash of supplied password or false if
+ * if something went wrong during hashing
+ */
+ public function hash($password, $type = '')
+ {
+ if (strlen($password) > 4096)
+ {
+ // If the password is too huge, we will simply reject it
+ // and not let the server try to hash it.
+ return false;
+ }
+
+ // Try to retrieve algorithm by service name if type doesn't
+ // start with dollar sign
+ if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type]))
+ {
+ $type = $this->algorithms[$type]->get_prefix();
+ }
+
+ $type = ($type === '') ? $this->type : $type;
+
+ if (is_array($type))
+ {
+ return $this->combined_hash_password($password, $type);
+ }
+
+ if (isset($this->type_map[$type]))
+ {
+ $hashing_algorithm = $this->type_map[$type];
+ }
+ else
+ {
+ return false;
+ }
+
+ return $hashing_algorithm->hash($password);
+ }
+
+ /**
+ * Check supplied password against hash and set convert_flag if password
+ * needs to be converted to different format (preferrably newer one)
+ *
+ * @param string $password Password that should be checked
+ * @param string $hash Stored hash
+ * @return string|bool True if password is correct, false if not
+ */
+ public function check($password, $hash)
+ {
+ if (strlen($password) > 4096)
+ {
+ // If the password is too huge, we will simply reject it
+ // and not let the server try to hash it.
+ return false;
+ }
+
+ // First find out what kind of hash we're dealing with
+ $stored_hash_type = $this->detect_algorithm($hash);
+ if ($stored_hash_type == false)
+ {
+ return false;
+ }
+
+ // Multiple hash passes needed
+ if (is_array($stored_hash_type))
+ {
+ $correct = $this->check_combined_hash($password, $stored_hash_type, $hash);
+ $this->convert_flag = ($correct === true) ? true : false;
+ return $correct;
+ }
+
+ if ($stored_hash_type->get_prefix() !== $this->type)
+ {
+ $this->convert_flag = true;
+ }
+ else
+ {
+ $this->convert_flag = false;
+ }
+
+ return $stored_hash_type->check($password, $hash);
+ }
+
+ /**
+ * Create combined hash from already hashed password
+ *
+ * @param string $password_hash Complete current password hash
+ * @param string $type Type of the hashing algorithm the password hash
+ * should be combined with
+ * @return string|bool Combined password hash if combined hashing was
+ * successful, else false
+ */
+ public function combined_hash_password($password_hash, $type)
+ {
+ $data = array(
+ 'prefix' => '$',
+ 'settings' => '$',
+ );
+ $hash_settings = $this->helper->get_combined_hash_settings($password_hash);
+ $hash = $hash_settings[0];
+
+ // Put settings of current hash into data array
+ $stored_hash_type = $this->detect_algorithm($password_hash);
+ $this->helper->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix());
+ $this->helper->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash));
+
+ // Hash current hash with the defined types
+ foreach ($type as $cur_type)
+ {
+ if (isset($this->algorithms[$cur_type]))
+ {
+ $new_hash_type = $this->algorithms[$cur_type];
+ }
+ else
+ {
+ $new_hash_type = $this->get_algorithm($cur_type);
+ }
+
+ if (!$new_hash_type)
+ {
+ return false;
+ }
+
+ $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash));
+ $this->helper->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix());
+ $this->helper->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0));
+ $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->helper->obtain_hash_only($new_hash));
+ }
+ return $this->helper->combine_hash_output($data, 'hash', $hash);
+ }
+
+ /**
+ * Check combined password hash against the supplied password
+ *
+ * @param string $password Password entered by user
+ * @param array $stored_hash_type An array containing the hash types
+ * as described by stored password hash
+ * @param string $hash Stored password hash
+ *
+ * @return bool True if password is correct, false if not
+ */
+ public function check_combined_hash($password, $stored_hash_type, $hash)
+ {
+ $i = 0;
+ $data = array(
+ 'prefix' => '$',
+ 'settings' => '$',
+ );
+ $hash_settings = $this->helper->get_combined_hash_settings($hash);
+ foreach ($stored_hash_type as $key => $hash_type)
+ {
+ $rebuilt_hash = $this->helper->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]);
+ $this->helper->combine_hash_output($data, 'prefix', $key);
+ $this->helper->combine_hash_output($data, 'settings', $hash_settings[$i]);
+ $cur_hash = $hash_type->hash($password, $rebuilt_hash);
+ $password = str_replace($rebuilt_hash, '', $cur_hash);
+ $i++;
+ }
+ return ($hash === $this->helper->combine_hash_output($data, 'hash', $password));
+ }
+}
diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php
index 8cd8808261..f92c2b72b2 100644
--- a/phpBB/phpbb/path_helper.php
+++ b/phpBB/phpbb/path_helper.php
@@ -102,6 +102,27 @@ class path_helper
}
/**
+ * Strips away the web root path and prepends the normal root path
+ *
+ * This replaces get_web_root_path() . some_url with
+ * $phpbb_root_path . some_url
+ *
+ * @param string $path The path to be updated
+ * @return string
+ */
+ public function remove_web_root_path($path)
+ {
+ if (strpos($path, $this->get_web_root_path()) === 0)
+ {
+ $path = substr($path, strlen($this->get_web_root_path()));
+
+ return $this->phpbb_root_path . $path;
+ }
+
+ return $path;
+ }
+
+ /**
* Get a relative root path from the current URL
*
* @return string
@@ -128,6 +149,16 @@ class path_helper
$script_name = $this->symfony_request->getScriptName();
/*
+ * If the path info is empty but we're using app.php, then we
+ * might be using an empty route like app.php/ which is
+ * supported by symfony's routing
+ */
+ if ($path_info === '/' && preg_match('/app\.' . $this->php_ext . '\/$/', $request_uri))
+ {
+ return $this->web_root_path = $this->phpbb_root_path . '../';
+ }
+
+ /*
* If the path info is empty (single /), then we're not using
* a route like app.php/foo/bar
*/
@@ -162,4 +193,143 @@ class path_helper
*/
return $this->web_root_path = $this->phpbb_root_path . str_repeat('../', $corrections - 1);
}
+
+ /**
+ * Eliminates useless . and .. components from specified URL
+ *
+ * @param string $url URL to clean
+ *
+ * @return string Cleaned URL
+ */
+ public function clean_url($url)
+ {
+ $delimiter_position = strpos($url, '://');
+ // URL should contain :// but it shouldn't start with it.
+ // Do not clean URLs that do not fit these constraints.
+ if (empty($delimiter_position))
+ {
+ return $url;
+ }
+ $scheme = substr($url, 0, $delimiter_position) . '://';
+ // Add length of URL delimiter to position
+ $path = substr($url, $delimiter_position + 3);
+
+ return $scheme . $this->filesystem->clean_path($path);
+ }
+
+ /**
+ * Glue URL parameters together
+ *
+ * @param array $params URL parameters in the form of array(name => value)
+ * @return string Returns the glued string, e.g. name1=value1&amp;name2=value2
+ */
+ public function glue_url_params($params)
+ {
+ $_params = array();
+
+ foreach ($params as $key => $value)
+ {
+ $_params[] = $key . '=' . $value;
+ }
+ return implode('&amp;', $_params);
+ }
+
+ /**
+ * Get the base and parameters of a URL
+ *
+ * @param string $url URL to break apart
+ * @param bool $is_amp Is the parameter separator &amp;. Defaults to true.
+ * @return array Returns the base and parameters in the form of array('base' => string, 'params' => array(name => value))
+ */
+ public function get_url_parts($url, $is_amp = true)
+ {
+ $separator = ($is_amp) ? '&amp;' : '&';
+ $params = array();
+
+ if (strpos($url, '?') !== false)
+ {
+ $base = substr($url, 0, strpos($url, '?'));
+ $args = substr($url, strlen($base) + 1);
+ $args = ($args) ? explode($separator, $args) : array();
+
+ foreach ($args as $argument)
+ {
+ if (empty($argument))
+ {
+ continue;
+ }
+ list($key, $value) = explode('=', $argument, 2);
+
+ if ($key === '')
+ {
+ continue;
+ }
+
+ $params[$key] = $value;
+ }
+ }
+ else
+ {
+ $base = $url;
+ }
+
+ return array(
+ 'base' => $base,
+ 'params' => $params,
+ );
+ }
+
+ /**
+ * Strip parameters from an already built URL.
+ *
+ * @param string $url URL to strip parameters from
+ * @param array|string $strip Parameters to strip.
+ * @param bool $is_amp Is the parameter separator &amp;. Defaults to true.
+ * @return string Returns the new URL.
+ */
+ public function strip_url_params($url, $strip, $is_amp = true)
+ {
+ $url_parts = $this->get_url_parts($url, $is_amp);
+ $params = $url_parts['params'];
+
+ if (!is_array($strip))
+ {
+ $strip = array($strip);
+ }
+
+ if (!empty($params))
+ {
+ // Strip the parameters off
+ foreach ($strip as $param)
+ {
+ unset($params[$param]);
+ }
+ }
+
+ return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : '');
+ }
+
+ /**
+ * Append parameters to an already built URL.
+ *
+ * @param string $url URL to append parameters to
+ * @param array $new_params Parameters to add in the form of array(name => value)
+ * @param string $is_amp Is the parameter separator &amp;. Defaults to true.
+ * @return string Returns the new URL.
+ */
+ public function append_url_params($url, $new_params, $is_amp = true)
+ {
+ $url_parts = $this->get_url_parts($url, $is_amp);
+ $params = array_merge($url_parts['params'], $new_params);
+
+ // Move the sid to the end if it's set
+ if (isset($params['sid']))
+ {
+ $sid = $params['sid'];
+ unset($params['sid']);
+ $params['sid'] = $sid;
+ }
+
+ return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : '');
+ }
}
diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php
index 8319e6d123..3cf39b5126 100644
--- a/phpBB/phpbb/permissions.php
+++ b/phpBB/phpbb/permissions.php
@@ -57,7 +57,7 @@ class permissions
* 'lang' => 'ACL_U_VIEWPROFILE',
* 'cat' => 'profile',
* ),
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
$vars = array('types', 'categories', 'permissions');
extract($phpbb_dispatcher->trigger_event('core.permissions', compact($vars)));
@@ -251,6 +251,7 @@ class permissions
'f_reply' => array('lang' => 'ACL_F_REPLY', 'cat' => 'post'),
'f_edit' => array('lang' => 'ACL_F_EDIT', 'cat' => 'post'),
'f_delete' => array('lang' => 'ACL_F_DELETE', 'cat' => 'post'),
+ 'f_softdelete' => array('lang' => 'ACL_F_SOFTDELETE', 'cat' => 'post'),
'f_ignoreflood' => array('lang' => 'ACL_F_IGNOREFLOOD', 'cat' => 'post'),
'f_postcount' => array('lang' => 'ACL_F_POSTCOUNT', 'cat' => 'post'),
'f_noapprove' => array('lang' => 'ACL_F_NOAPPROVE', 'cat' => 'post'),
diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php
index 6bff2b8a7e..b988ce7ce0 100644
--- a/phpBB/phpbb/plupload/plupload.php
+++ b/phpBB/phpbb/plupload/plupload.php
@@ -146,10 +146,11 @@ class plupload
* @param \phpbb\template\template $template
* @param string $s_action The URL to submit the POST data to
* @param int $forum_id The ID of the forum
+ * @param int $max_files Maximum number of files allowed. 0 for unlimited.
*
* @return null
*/
- public function configure(\phpbb\cache\service $cache, \phpbb\template\template $template, $s_action, $forum_id)
+ public function configure(\phpbb\cache\service $cache, \phpbb\template\template $template, $s_action, $forum_id, $max_files)
{
$filters = $this->generate_filter_string($cache, $forum_id);
$chunk_size = $this->get_chunk_size();
@@ -161,6 +162,9 @@ class plupload
'FILTERS' => $filters,
'CHUNK_SIZE' => $chunk_size,
'S_PLUPLOAD_URL' => htmlspecialchars_decode($s_action),
+ 'MAX_ATTACHMENTS' => $max_files,
+ 'ATTACH_ORDER' => ($this->config['display_order']) ? 'asc' : 'desc',
+ 'L_TOO_MANY_ATTACHMENTS' => $this->user->lang('TOO_MANY_ATTACHMENTS', $max_files),
));
$this->user->add_lang('plupload');
diff --git a/phpBB/phpbb/profilefields/lang_helper.php b/phpBB/phpbb/profilefields/lang_helper.php
new file mode 100644
index 0000000000..7ad4722230
--- /dev/null
+++ b/phpBB/phpbb/profilefields/lang_helper.php
@@ -0,0 +1,130 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields;
+
+/**
+* Custom Profile Fields
+* @package phpBB3
+*/
+class lang_helper
+{
+ /**
+ * Array with the language option, grouped by field and language
+ * @var array
+ */
+ protected $options_lang = array();
+
+ /**
+ * Database object
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * Table where the language strings are stored
+ * @var string
+ */
+ protected $language_table;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct($db, $language_table)
+ {
+ $this->db = $db;
+ $this->language_table = $language_table;
+ }
+
+ /**
+ * Get language entries for options and store them here for later use
+ */
+ public function get_option_lang($field_id, $lang_id, $field_type, $preview_options)
+ {
+ if ($preview_options !== false)
+ {
+ $lang_options = (!is_array($preview_options)) ? explode("\n", $preview_options) : $preview_options;
+
+ foreach ($lang_options as $num => $var)
+ {
+ if (!isset($this->options_lang[$field_id]))
+ {
+ $this->options_lang[$field_id] = array();
+ }
+ if (!isset($this->options_lang[$field_id][$lang_id]))
+ {
+ $this->options_lang[$field_id][$lang_id] = array();
+ }
+ $this->options_lang[$field_id][$lang_id][($num + 1)] = $var;
+ }
+ }
+ else
+ {
+ $sql = 'SELECT option_id, lang_value
+ FROM ' . $this->language_table . '
+ WHERE field_id = ' . (int) $field_id . '
+ AND lang_id = ' . (int) $lang_id . "
+ AND field_type = '" . $this->db->sql_escape($field_type) . "'
+ ORDER BY option_id";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['lang_value'];
+ }
+ $this->db->sql_freeresult($result);
+ }
+ }
+
+ /**
+ * Are language options set for this field?
+ *
+ * @param int $field_id Database ID of the field
+ * @param int $lang_id ID of the language
+ * @param int $field_value Selected value of the field
+ * @return boolean
+ */
+ public function is_set($field_id, $lang_id = null, $field_value = null)
+ {
+ $is_set = isset($this->options_lang[$field_id]);
+
+ if ($is_set && (!is_null($lang_id) || !is_null($field_value)))
+ {
+ $is_set = isset($this->options_lang[$field_id][$lang_id]);
+ }
+
+ if ($is_set && !is_null($field_value))
+ {
+ $is_set = isset($this->options_lang[$field_id][$lang_id][$field_value]);
+ }
+
+ return $is_set;
+ }
+
+ /**
+ * Get the selected language string
+ *
+ * @param int $field_id Database ID of the field
+ * @param int $lang_id ID of the language
+ * @param int $field_value Selected value of the field
+ * @return string
+ */
+ public function get($field_id, $lang_id, $field_value = null)
+ {
+ if (is_null($field_value))
+ {
+ return $this->options_lang[$field_id][$lang_id];
+ }
+
+ return $this->options_lang[$field_id][$lang_id][$field_value];
+ }
+}
diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php
new file mode 100644
index 0000000000..37449c67c4
--- /dev/null
+++ b/phpBB/phpbb/profilefields/manager.php
@@ -0,0 +1,437 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields;
+
+/**
+* Custom Profile Fields
+* @package phpBB3
+*/
+class manager
+{
+ /**
+ * Auth object
+ * @var \phpbb\auth\auth
+ */
+ protected $auth;
+
+ /**
+ * Database object
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * Service Collection object
+ * @var \phpbb\di\service_collection
+ */
+ protected $type_collection;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ protected $fields_table;
+
+ protected $fields_language_table;
+
+ protected $fields_data_table;
+
+ protected $profile_cache = array();
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\auth\auth $auth Auth object
+ * @param \phpbb\db\driver\driver_interface $db Database object
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\di\service_collection $type_collection
+ * @param \phpbb\user $user User object
+ * @param string $fields_table
+ * @param string $fields_language_table
+ * @param string $fields_data_table
+ */
+ public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table)
+ {
+ $this->auth = $auth;
+ $this->db = $db;
+ $this->request = $request;
+ $this->template = $template;
+ $this->type_collection = $type_collection;
+ $this->user = $user;
+
+ $this->fields_table = $fields_table;
+ $this->fields_language_table = $fields_language_table;
+ $this->fields_data_table = $fields_data_table;
+ }
+
+ /**
+ * Assign editable fields to template, mode can be profile (for profile change) or register (for registration)
+ * Called by ucp_profile and ucp_register
+ */
+ public function generate_profile_fields($mode, $lang_id)
+ {
+ $sql_where = '';
+ switch ($mode)
+ {
+ case 'register':
+ // If the field is required we show it on the registration page
+ $sql_where .= ' AND f.field_show_on_reg = 1';
+ break;
+
+ case 'profile':
+ // Show hidden fields to moderators/admins
+ if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_'))
+ {
+ $sql_where .= ' AND f.field_show_profile = 1';
+ }
+ break;
+
+ default:
+ trigger_error('Wrong profile mode specified', E_USER_ERROR);
+ break;
+ }
+
+ $sql = 'SELECT l.*, f.*
+ FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . " f
+ WHERE f.field_active = 1
+ $sql_where
+ AND l.lang_id = " . (int) $lang_id . '
+ AND l.field_id = f.field_id
+ ORDER BY f.field_order';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Return templated field
+ $profile_field = $this->type_collection[$row['field_type']];
+ $tpl_snippet = $profile_field->process_field_row('change', $row);
+
+ $this->template->assign_block_vars('profile_fields', array(
+ 'LANG_NAME' => $this->user->lang($row['lang_name']),
+ 'LANG_EXPLAIN' => $this->user->lang($row['lang_explain']),
+ 'FIELD' => $tpl_snippet,
+ 'FIELD_ID' => $profile_field->get_field_ident($row),
+ 'S_REQUIRED' => ($row['field_required']) ? true : false,
+ ));
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Build profile cache, used for display
+ */
+ protected function build_cache()
+ {
+ $this->profile_cache = array();
+
+ // Display hidden/no_view fields for admin/moderator
+ $sql = 'SELECT l.*, f.*
+ FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f
+ WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . '
+ AND f.field_active = 1 ' .
+ ((!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_')) ? ' AND f.field_hide = 0 ' : '') . '
+ AND f.field_no_view = 0
+ AND l.field_id = f.field_id
+ ORDER BY f.field_order';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->profile_cache[$row['field_ident']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Submit profile field for validation
+ */
+ public function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error)
+ {
+ $sql_where = '';
+ switch ($mode)
+ {
+ case 'register':
+ // If the field is required we show it on the registration page
+ $sql_where .= ' AND f.field_show_on_reg = 1';
+ break;
+
+ case 'profile':
+ // Show hidden fields to moderators/admins
+ if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_'))
+ {
+ $sql_where .= ' AND f.field_show_profile = 1';
+ }
+ break;
+
+ default:
+ trigger_error('Wrong profile mode specified', E_USER_ERROR);
+ break;
+ }
+
+ $sql = 'SELECT l.*, f.*
+ FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f
+ WHERE l.lang_id = ' . (int) $lang_id . "
+ AND f.field_active = 1
+ $sql_where
+ AND l.field_id = f.field_id
+ ORDER BY f.field_order";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $profile_field = $this->type_collection[$row['field_type']];
+ $cp_data['pf_' . $row['field_ident']] = $profile_field->get_profile_field($row);
+ $check_value = $cp_data['pf_' . $row['field_ident']];
+
+ if (($cp_result = $profile_field->validate_profile_field($check_value, $row)) !== false)
+ {
+ // If the result is not false, it's an error message
+ $cp_error[] = $cp_result;
+ }
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Update profile field data directly
+ */
+ public function update_profile_field_data($user_id, $cp_data)
+ {
+ if (!sizeof($cp_data))
+ {
+ return;
+ }
+
+ $sql = 'UPDATE ' . $this->fields_data_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . '
+ WHERE user_id = ' . (int) $user_id;
+ $this->db->sql_query($sql);
+
+ if (!$this->db->sql_affectedrows())
+ {
+ $cp_data = $this->build_insert_sql_array($cp_data);
+ $cp_data['user_id'] = (int) $user_id;
+
+ $this->db->sql_return_on_error(true);
+
+ $sql = 'INSERT INTO ' . $this->fields_data_table . ' ' . $this->db->sql_build_array('INSERT', $cp_data);
+ $this->db->sql_query($sql);
+
+ $this->db->sql_return_on_error(false);
+ }
+ }
+
+ /**
+ * Generate the template arrays in order to display the column names
+ *
+ * @param string $restrict_option Restrict the published fields to a certain profile field option
+ * @return array Returns an array with the template variables type, name and explain for the fields to display
+ */
+ public function generate_profile_fields_template_headlines($restrict_option = '')
+ {
+ if (!sizeof($this->profile_cache))
+ {
+ $this->build_cache();
+ }
+
+ $tpl_fields = array();
+
+ // Go through the fields in correct order
+ foreach ($this->profile_cache as $field_ident => $field_data)
+ {
+ if ($restrict_option && !$field_data[$restrict_option])
+ {
+ continue;
+ }
+
+ $profile_field = $this->type_collection[$field_data['field_type']];
+
+ $tpl_fields[] = array(
+ 'PROFILE_FIELD_TYPE' => $field_data['field_type'],
+ 'PROFILE_FIELD_NAME' => $profile_field->get_field_name($field_data['lang_name']),
+ 'PROFILE_FIELD_EXPLAIN' => $this->user->lang($field_data['lang_explain']),
+ );
+ }
+
+ return $tpl_fields;
+ }
+
+ /**
+ * Grab the user specific profile fields data
+ *
+ * @param int|array $user_ids Single user id or an array of ids
+ * @return array Users profile fields data
+ */
+ public function grab_profile_fields_data($user_ids = 0)
+ {
+ if (!is_array($user_ids))
+ {
+ $user_ids = array($user_ids);
+ }
+
+ if (!sizeof($this->profile_cache))
+ {
+ $this->build_cache();
+ }
+
+ if (!sizeof($user_ids))
+ {
+ return array();
+ }
+
+ $sql = 'SELECT *
+ FROM ' . $this->fields_data_table . '
+ WHERE ' . $this->db->sql_in_set('user_id', array_map('intval', $user_ids));
+ $result = $this->db->sql_query($sql);
+
+ $field_data = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $field_data[$row['user_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ $user_fields = array();
+
+ // Go through the fields in correct order
+ foreach (array_keys($this->profile_cache) as $used_ident)
+ {
+ foreach ($field_data as $user_id => $row)
+ {
+ $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident];
+ $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident];
+ }
+
+ foreach ($user_ids as $user_id)
+ {
+ if (!isset($user_fields[$user_id][$used_ident]) && $this->profile_cache[$used_ident]['field_show_novalue'])
+ {
+ $user_fields[$user_id][$used_ident]['value'] = '';
+ $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident];
+ }
+ }
+ }
+
+ return $user_fields;
+ }
+
+ /**
+ * Assign the user's profile fields data to the template
+ *
+ * @param array $profile_row Array with users profile field data
+ * @param bool $use_contact_fields Should we display contact fields as such?
+ * This requires special treatments (links should not be parsed in the values, and more)
+ * @return array
+ */
+ public function generate_profile_fields_template_data($profile_row, $use_contact_fields = true)
+ {
+ // $profile_row == $user_fields[$row['user_id']];
+ $tpl_fields = array();
+ $tpl_fields['row'] = $tpl_fields['blockrow'] = array();
+
+ foreach ($profile_row as $ident => $ident_ary)
+ {
+ $profile_field = $this->type_collection[$ident_ary['data']['field_type']];
+ $value = $profile_field->get_profile_value($ident_ary['value'], $ident_ary['data']);
+
+ if ($value === null)
+ {
+ continue;
+ }
+
+ $field_desc = $contact_url = '';
+ if ($use_contact_fields)
+ {
+ $value = $profile_field->get_profile_contact_value($ident_ary['value'], $ident_ary['data']);
+ $field_desc = $this->user->lang($ident_ary['data']['field_contact_desc']);
+ if (strpos($field_desc, '%s') !== false)
+ {
+ $field_desc = sprintf($field_desc, $value);
+ }
+ $contact_url = '';
+ if (strpos($ident_ary['data']['field_contact_url'], '%s') !== false)
+ {
+ $contact_url = sprintf($ident_ary['data']['field_contact_url'], $value);
+ }
+ }
+
+ $tpl_fields['row'] += array(
+ 'PROFILE_' . strtoupper($ident) . '_IDENT' => $ident,
+ 'PROFILE_' . strtoupper($ident) . '_VALUE' => $value,
+ 'PROFILE_' . strtoupper($ident) . '_CONTACT'=> $contact_url,
+ 'PROFILE_' . strtoupper($ident) . '_DESC' => $field_desc,
+ 'PROFILE_' . strtoupper($ident) . '_TYPE' => $ident_ary['data']['field_type'],
+ 'PROFILE_' . strtoupper($ident) . '_NAME' => $this->user->lang($ident_ary['data']['lang_name']),
+ 'PROFILE_' . strtoupper($ident) . '_EXPLAIN'=> $this->user->lang($ident_ary['data']['lang_explain']),
+
+ 'S_PROFILE_' . strtoupper($ident) . '_CONTACT' => $ident_ary['data']['field_is_contact'],
+ 'S_PROFILE_' . strtoupper($ident) => true,
+ );
+
+ $tpl_fields['blockrow'][] = array(
+ 'PROFILE_FIELD_IDENT' => $ident,
+ 'PROFILE_FIELD_VALUE' => $value,
+ 'PROFILE_FIELD_CONTACT' => $contact_url,
+ 'PROFILE_FIELD_DESC' => $field_desc,
+ 'PROFILE_FIELD_TYPE' => $ident_ary['data']['field_type'],
+ 'PROFILE_FIELD_NAME' => $this->user->lang($ident_ary['data']['lang_name']),
+ 'PROFILE_FIELD_EXPLAIN' => $this->user->lang($ident_ary['data']['lang_explain']),
+
+ 'S_PROFILE_CONTACT' => $ident_ary['data']['field_is_contact'],
+ 'S_PROFILE_' . strtoupper($ident) => true,
+ );
+ }
+
+ return $tpl_fields;
+ }
+
+ /**
+ * Build Array for user insertion into custom profile fields table
+ */
+ public function build_insert_sql_array($cp_data)
+ {
+ $sql_not_in = array();
+ foreach ($cp_data as $key => $null)
+ {
+ $sql_not_in[] = (strncmp($key, 'pf_', 3) === 0) ? substr($key, 3) : $key;
+ }
+
+ $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value
+ FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f
+ WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . '
+ ' . ((sizeof($sql_not_in)) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . '
+ AND l.field_id = f.field_id';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $profile_field = $this->type_collection[$row['field_type']];
+ $cp_data['pf_' . $row['field_ident']] = $profile_field->get_default_field_value($row);
+ }
+ $this->db->sql_freeresult($result);
+
+ return $cp_data;
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_base.php b/phpBB/phpbb/profilefields/type/type_base.php
new file mode 100644
index 0000000000..a96196674d
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_base.php
@@ -0,0 +1,191 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+abstract class type_base implements type_interface
+{
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name()
+ {
+ return $this->user->lang('FIELD_' . strtoupper($this->get_name_short()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_service_name()
+ {
+ return 'profilefields.type.' . $this->get_name_short();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_template_filename()
+ {
+ return 'profilefields/' . $this->get_name_short() . '.html';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_field_ident($field_data)
+ {
+ return 'pf_' . $field_data['field_ident'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_field_name($field_name)
+ {
+ return isset($this->user->lang[$field_name]) ? $this->user->lang[$field_name] : $field_name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_contact_value($field_value, $field_data)
+ {
+ return $this->get_profile_value($field_value, $field_data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options_input($field_data)
+ {
+ $field_data['l_lang_name'] = $this->request->variable('l_lang_name', array(0 => ''), true);
+ $field_data['l_lang_explain'] = $this->request->variable('l_lang_explain', array(0 => ''), true);
+ $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => ''), true);
+ $field_data['l_lang_options'] = $this->request->variable('l_lang_options', array(0 => ''), true);
+
+ return $field_data;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_options_form(&$exclude_options, &$visibility_options)
+ {
+ return $this->request->variable('lang_options', '', true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_options_on_submit($error, $field_data)
+ {
+ return $error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 3 && ($field_data[$key] || $action != 'edit') && $key == 'l_lang_options' && is_array($field_data[$key]))
+ {
+ foreach ($field_data[$key] as $lang_id => $options)
+ {
+ $field_data[$key][$lang_id] = explode("\n", $options);
+ }
+
+ return $current_value;
+ }
+
+ return $current_value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_hidden_fields($step, $key, $action, &$field_data)
+ {
+ if (!$this->request->is_set($key))
+ {
+ // Do not set this variable, we will use the default value
+ return null;
+ }
+ else if ($key == 'field_ident' && isset($field_data[$key]))
+ {
+ return $field_data[$key];
+ }
+ else
+ {
+ return $this->request->variable($key, '', true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function display_options(&$template_vars, &$field_data)
+ {
+ return;
+ }
+
+ /**
+ * Return templated value/field. Possible values for $mode are:
+ * change == user is able to set/enter profile values; preview == just show the value
+ */
+ public function process_field_row($mode, $profile_row)
+ {
+ $preview_options = ($mode == 'preview') ? $profile_row['lang_options'] : false;
+
+ // set template filename
+ $this->template->set_filenames(array(
+ 'cp_body' => $this->get_template_filename(),
+ ));
+
+ // empty previously filled blockvars
+ $this->template->destroy_block_vars($this->get_name_short());
+
+ // Assign template variables
+ $this->generate_field($profile_row, $preview_options);
+
+ return $this->template->assign_display('cp_body');
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php
new file mode 100644
index 0000000000..fa9c0a8714
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_bool.php
@@ -0,0 +1,387 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_bool extends type_base
+{
+ /**
+ * Profile fields language helper
+ * @var \phpbb\profilefields\lang_helper
+ */
+ protected $lang_helper;
+
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\profilefields\lang_helper $lang_helper Profile fields language helper
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\profilefields\lang_helper $lang_helper, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->lang_helper = $lang_helper;
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'bool';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $profile_row = array(
+ 'var_name' => 'field_default_value',
+ 'field_id' => 1,
+ 'lang_name' => $field_data['lang_name'],
+ 'lang_explain' => $field_data['lang_explain'],
+ 'lang_id' => $default_lang_id,
+ 'field_default_value' => $field_data['field_default_value'],
+ 'field_ident' => 'field_default_value',
+ 'field_type' => $this->get_service_name(),
+ 'field_length' => $field_data['field_length'],
+ 'lang_options' => $field_data['lang_options'],
+ );
+
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['FIELD_TYPE'], 'EXPLAIN' => $this->user->lang['BOOL_TYPE_EXPLAIN'], 'FIELD' => '<label><input type="radio" class="radio" name="field_length" value="1"' . (($field_data['field_length'] == 1) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['RADIO_BUTTONS'] . '</label><label><input type="radio" class="radio" name="field_length" value="2"' . (($field_data['field_length'] == 2) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['CHECKBOX'] . '</label>'),
+ 1 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 1,
+ 'field_minlen' => 0,
+ 'field_maxlen' => 0,
+ 'field_validation' => '',
+ 'field_novalue' => 0,
+ 'field_default_value' => 0,
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_field_value($field_data)
+ {
+ return $field_data['field_default_value'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+
+ // Checkbox
+ if ($profile_row['field_length'] == 2)
+ {
+ return ($this->request->is_set($var_name)) ? 1 : 0;
+ }
+ else
+ {
+ return $this->request->variable($var_name, (int) $profile_row['field_default_value']);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ $field_value = (bool) $field_value;
+
+ if (!$field_value && $field_data['field_required'])
+ {
+ return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name']));
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_value($field_value, $field_data)
+ {
+ $field_id = $field_data['field_id'];
+ $lang_id = $field_data['lang_id'];
+
+ if (!$this->lang_helper->is_set($field_id, $lang_id))
+ {
+ $this->lang_helper->get_option_lang($field_id, $lang_id, FIELD_BOOL, false);
+ }
+
+ if (!$field_value && $field_data['field_show_novalue'])
+ {
+ $field_value = $field_data['field_default_value'];
+ }
+
+ if ($field_data['field_length'] == 1)
+ {
+ return ($this->lang_helper->is_set($field_id, $lang_id, (int) $field_value)) ? $this->lang_helper->get($field_id, $lang_id, (int) $field_value) : null;
+ }
+ else if (!$field_value)
+ {
+ return null;
+ }
+ else
+ {
+ return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+ $default_value = $profile_row['field_default_value'];
+
+ // checkbox - set the value to "true" if it has been set to 1
+ if ($profile_row['field_length'] == 2)
+ {
+ $value = ($this->request->is_set($field_ident) && $this->request->variable($field_ident, $default_value) == 1) ? true : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]);
+ }
+ else
+ {
+ $value = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]);
+ }
+
+ $profile_row['field_value'] = (int) $value;
+ $this->template->assign_block_vars('bool', array_change_key_case($profile_row, CASE_UPPER));
+
+ if ($profile_row['field_length'] == 1)
+ {
+ if (!$this->lang_helper->is_set($profile_row['field_id'], $profile_row['lang_id'], 1))
+ {
+ $this->lang_helper->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], $this->get_service_name(), $preview_options);
+ }
+
+ $options = $this->lang_helper->get($profile_row['field_id'], $profile_row['lang_id']);
+ foreach ($options as $option_id => $option_value)
+ {
+ $this->template->assign_block_vars('bool.options', array(
+ 'OPTION_ID' => $option_id,
+ 'CHECKED' => ($value == $option_id) ? ' checked="checked"' : '',
+ 'VALUE' => $option_value,
+ ));
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_field_ident($field_data)
+ {
+ return ($field_data['field_length'] == '1') ? '' : 'pf_' . $field_data['field_ident'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'TINT:2';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ 'lang_options' => 'two_options',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options_input($field_data)
+ {
+ $field_data['l_lang_name'] = $this->request->variable('l_lang_name', array(0 => ''), true);
+ $field_data['l_lang_explain'] = $this->request->variable('l_lang_explain', array(0 => ''), true);
+ $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => ''), true);
+
+ /**
+ * @todo check if this line is correct...
+ $field_data['l_lang_default_value'] = $this->request->variable('l_lang_default_value', array(0 => array('')), true);
+ */
+ $field_data['l_lang_options'] = $this->request->variable('l_lang_options', array(0 => array('')), true);
+
+ return $field_data;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_options_form(&$exclude_options, &$visibility_options)
+ {
+ $exclude_options[1][] = 'lang_options';
+
+ return $this->request->variable('lang_options', array(''), true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_options_on_submit($error, $field_data)
+ {
+ if (empty($field_data['lang_options'][0]) || empty($field_data['lang_options'][1]))
+ {
+ $error[] = $this->user->lang['NO_FIELD_ENTRIES'];
+ }
+
+ return $error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 2 && $key == 'field_default_value')
+ {
+ // 'field_length' == 1 defines radio buttons. Possible values are 1 or 2 only.
+ // 'field_length' == 2 defines checkbox. Possible values are 0 or 1 only.
+ // If we switch the type on step 2, we have to adjust field value.
+ // 1 is a common value for the checkbox and radio buttons.
+
+ // Adjust unchecked checkbox value.
+ // If we return or save settings from 2nd/3rd page
+ // and the checkbox is unchecked, set the value to 0.
+ if ($this->request->is_set('step') && !$this->request->is_set($key))
+ {
+ return 0;
+ }
+
+ // If we switch to the checkbox type but former radio buttons value was 2,
+ // which is not the case for the checkbox, set it to 0 (unchecked).
+ if ($field_data['field_length'] == 2 && $current_value == 2)
+ {
+ return 0;
+ }
+ // If we switch to the radio buttons but the former checkbox value was 0,
+ // which is not the case for the radio buttons, set it to 0.
+ else if ($field_data['field_length'] == 1 && $current_value == 0)
+ {
+ return 2;
+ }
+ }
+
+ if ($step == 3 && ($field_data[$key] || $action != 'edit') && $key == 'l_lang_options')
+ {
+ $field_data[$key] = $this->request->variable($key, array(0 => array('')), true);
+
+ return $current_value;
+ }
+
+ return parent::get_excluded_options($key, $action, $current_value, $field_data, $step);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_hidden_fields($step, $key, $action, &$field_data)
+ {
+ if ($key == 'l_lang_options' && $this->request->is_set('l_lang_options'))
+ {
+ return $this->request->variable($key, array(array('')), true);
+ }
+ else if ($key == 'field_default_value')
+ {
+ return $this->request->variable($key, $field_data[$key]);
+ }
+ else
+ {
+ if (!$this->request->is_set($key))
+ {
+ return false;
+ }
+ else if ($key == 'field_ident' && isset($field_data[$key]))
+ {
+ return $field_data[$key];
+ }
+ else
+ {
+ return ($key == 'lang_options') ? $this->request->variable($key, array(''), true) : $this->request->variable($key, '', true);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function display_options(&$template_vars, &$field_data)
+ {
+ // Initialize these array elements if we are creating a new field
+ if (!sizeof($field_data['lang_options']))
+ {
+ // No options have been defined for a boolean field.
+ $field_data['lang_options'][0] = '';
+ $field_data['lang_options'][1] = '';
+ }
+
+ $template_vars = array_merge($template_vars, array(
+ 'S_BOOL' => true,
+ 'L_LANG_OPTIONS_EXPLAIN' => $this->user->lang['BOOL_ENTRIES_EXPLAIN'],
+ 'FIRST_LANG_OPTION' => $field_data['lang_options'][0],
+ 'SECOND_LANG_OPTION' => $field_data['lang_options'][1],
+ ));
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php
new file mode 100644
index 0000000000..af3d65c9b6
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_date.php
@@ -0,0 +1,358 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_date extends type_base
+{
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'date';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $profile_row = array(
+ 'var_name' => 'field_default_value',
+ 'lang_name' => $field_data['lang_name'],
+ 'lang_explain' => $field_data['lang_explain'],
+ 'lang_id' => $default_lang_id,
+ 'field_default_value' => $field_data['field_default_value'],
+ 'field_ident' => 'field_default_value',
+ 'field_type' => $this->get_service_name(),
+ 'field_length' => $field_data['field_length'],
+ 'lang_options' => $field_data['lang_options'],
+ );
+
+ $always_now = request_var('always_now', -1);
+ if ($always_now == -1)
+ {
+ $s_checked = ($field_data['field_default_value'] == 'now') ? true : false;
+ }
+ else
+ {
+ $s_checked = ($always_now) ? true : false;
+ }
+
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)),
+ 1 => array('TITLE' => $this->user->lang['ALWAYS_TODAY'], 'FIELD' => '<label><input type="radio" class="radio" name="always_now" value="1"' . (($s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['YES'] . '</label><label><input type="radio" class="radio" name="always_now" value="0"' . ((!$s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . $this->user->lang['NO'] . '</label>'),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 10,
+ 'field_minlen' => 10,
+ 'field_maxlen' => 10,
+ 'field_validation' => '',
+ 'field_novalue' => ' 0- 0- 0',
+ 'field_default_value' => ' 0- 0- 0',
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_field_value($field_data)
+ {
+ if ($field_data['field_default_value'] == 'now')
+ {
+ $now = getdate();
+ $field_data['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
+ }
+
+ return $field_data['field_default_value'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+
+ if (!$this->request->is_set($var_name . '_day'))
+ {
+ if ($profile_row['field_default_value'] == 'now')
+ {
+ $now = getdate();
+ $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
+ }
+ list($day, $month, $year) = explode('-', $profile_row['field_default_value']);
+ }
+ else
+ {
+ $day = $this->request->variable($var_name . '_day', 0);
+ $month = $this->request->variable($var_name . '_month', 0);
+ $year = $this->request->variable($var_name . '_year', 0);
+ }
+
+ return sprintf('%2d-%2d-%4d', $day, $month, $year);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ $field_validate = explode('-', $field_value);
+
+ $day = (isset($field_validate[0])) ? (int) $field_validate[0] : 0;
+ $month = (isset($field_validate[1])) ? (int) $field_validate[1] : 0;
+ $year = (isset($field_validate[2])) ? (int) $field_validate[2] : 0;
+
+ if ((!$day || !$month || !$year) && !$field_data['field_required'])
+ {
+ return false;
+ }
+
+ if ((!$day || !$month || !$year) && $field_data['field_required'])
+ {
+ return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name']));
+ }
+
+ if ($day < 0 || $day > 31 || $month < 0 || $month > 12 || ($year < 1901 && $year > 0) || $year > gmdate('Y', time()) + 50)
+ {
+ return $this->user->lang('FIELD_INVALID_DATE', $this->get_field_name($field_data['lang_name']));
+ }
+
+ if (checkdate($month, $day, $year) === false)
+ {
+ return $this->user->lang('FIELD_INVALID_DATE', $this->get_field_name($field_data['lang_name']));
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_value($field_value, $field_data)
+ {
+ $date = explode('-', $field_value);
+ $day = (isset($date[0])) ? (int) $date[0] : 0;
+ $month = (isset($date[1])) ? (int) $date[1] : 0;
+ $year = (isset($date[2])) ? (int) $date[2] : 0;
+
+ if (!$day && !$month && !$year && !$field_data['field_show_novalue'])
+ {
+ return null;
+ }
+ else if ($day && $month && $year)
+ {
+ // Date should display as the same date for every user regardless of timezone
+ return $this->user->create_datetime()
+ ->setDate($year, $month, $day)
+ ->setTime(0, 0, 0)
+ ->format($this->user->lang['DATE_FORMAT'], true);
+ }
+
+ return $field_value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+
+ $now = getdate();
+
+ if (!$this->request->is_set($profile_row['field_ident'] . '_day'))
+ {
+ if ($profile_row['field_default_value'] == 'now')
+ {
+ $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
+ }
+ list($day, $month, $year) = explode('-', ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $profile_row['field_default_value'] : $this->user->profile_fields[$field_ident]));
+ }
+ else
+ {
+ if ($preview_options !== false && $profile_row['field_default_value'] == 'now')
+ {
+ $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
+ list($day, $month, $year) = explode('-', ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $profile_row['field_default_value'] : $this->user->profile_fields[$field_ident]));
+ }
+ else
+ {
+ $day = $this->request->variable($profile_row['field_ident'] . '_day', 0);
+ $month = $this->request->variable($profile_row['field_ident'] . '_month', 0);
+ $year = $this->request->variable($profile_row['field_ident'] . '_year', 0);
+ }
+ }
+
+ $profile_row['s_day_options'] = '<option value="0"' . ((!$day) ? ' selected="selected"' : '') . '>--</option>';
+ for ($i = 1; $i < 32; $i++)
+ {
+ $profile_row['s_day_options'] .= '<option value="' . $i . '"' . (($i == $day) ? ' selected="selected"' : '') . ">$i</option>";
+ }
+
+ $profile_row['s_month_options'] = '<option value="0"' . ((!$month) ? ' selected="selected"' : '') . '>--</option>';
+ for ($i = 1; $i < 13; $i++)
+ {
+ $profile_row['s_month_options'] .= '<option value="' . $i . '"' . (($i == $month) ? ' selected="selected"' : '') . ">$i</option>";
+ }
+
+ $profile_row['s_year_options'] = '<option value="0"' . ((!$year) ? ' selected="selected"' : '') . '>--</option>';
+ for ($i = $now['year'] - 100; $i <= $now['year'] + 100; $i++)
+ {
+ $profile_row['s_year_options'] .= '<option value="' . $i . '"' . (($i == $year) ? ' selected="selected"' : '') . ">$i</option>";
+ }
+
+ $profile_row['field_value'] = 0;
+ $this->template->assign_block_vars('date', array_change_key_case($profile_row, CASE_UPPER));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_field_ident($field_data)
+ {
+ return '';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'VCHAR:10';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 2 && $key == 'field_default_value')
+ {
+ $always_now = $this->request->variable('always_now', -1);
+
+ if ($always_now == 1 || ($always_now === -1 && $current_value == 'now'))
+ {
+ $now = getdate();
+
+ $field_data['field_default_value_day'] = $now['mday'];
+ $field_data['field_default_value_month'] = $now['mon'];
+ $field_data['field_default_value_year'] = $now['year'];
+ $current_value = 'now';
+ $this->request->overwrite('field_default_value', $current_value, \phpbb\request\request_interface::POST);
+ }
+ else
+ {
+ if ($this->request->is_set('field_default_value_day'))
+ {
+ $field_data['field_default_value_day'] = $this->request->variable('field_default_value_day', 0);
+ $field_data['field_default_value_month'] = $this->request->variable('field_default_value_month', 0);
+ $field_data['field_default_value_year'] = $this->request->variable('field_default_value_year', 0);
+ $current_value = sprintf('%2d-%2d-%4d', $field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']);
+ $this->request->overwrite('field_default_value', $current_value, \phpbb\request\request_interface::POST);
+ }
+ else
+ {
+ list($field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']) = explode('-', $current_value);
+ }
+ }
+
+ return $current_value;
+ }
+
+ return parent::get_excluded_options($key, $action, $current_value, $field_data, $step);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_hidden_fields($step, $key, $action, &$field_data)
+ {
+ if ($key == 'field_default_value')
+ {
+ $always_now = $this->request->variable('always_now', 0);
+
+ if ($always_now)
+ {
+ return 'now';
+ }
+ else if ($this->request->is_set('field_default_value_day'))
+ {
+ $field_data['field_default_value_day'] = $this->request->variable('field_default_value_day', 0);
+ $field_data['field_default_value_month'] = $this->request->variable('field_default_value_month', 0);
+ $field_data['field_default_value_year'] = $this->request->variable('field_default_value_year', 0);
+ return sprintf('%2d-%2d-%4d', $field_data['field_default_value_day'], $field_data['field_default_value_month'], $field_data['field_default_value_year']);
+ }
+ }
+
+ return parent::prepare_hidden_fields($step, $key, $action, $field_data);
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_dropdown.php b/phpBB/phpbb/profilefields/type/type_dropdown.php
new file mode 100644
index 0000000000..bcf0ba05f9
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_dropdown.php
@@ -0,0 +1,297 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_dropdown extends type_base
+{
+ /**
+ * Profile fields language helper
+ * @var \phpbb\profilefields\lang_helper
+ */
+ protected $lang_helper;
+
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\profilefields\lang_helper $lang_helper Profile fields language helper
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\profilefields\lang_helper $lang_helper, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->lang_helper = $lang_helper;
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'dropdown';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $profile_row[0] = array(
+ 'var_name' => 'field_default_value',
+ 'field_id' => 1,
+ 'lang_name' => $field_data['lang_name'],
+ 'lang_explain' => $field_data['lang_explain'],
+ 'lang_id' => $default_lang_id,
+ 'field_default_value' => $field_data['field_default_value'],
+ 'field_ident' => 'field_default_value',
+ 'field_type' => $this->get_service_name(),
+ 'lang_options' => $field_data['lang_options'],
+ );
+
+ $profile_row[1] = $profile_row[0];
+ $profile_row[1]['var_name'] = 'field_novalue';
+ $profile_row[1]['field_ident'] = 'field_novalue';
+ $profile_row[1]['field_default_value'] = $field_data['field_novalue'];
+
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row[0])),
+ 1 => array('TITLE' => $this->user->lang['NO_VALUE_OPTION'], 'EXPLAIN' => $this->user->lang['NO_VALUE_OPTION_EXPLAIN'], 'FIELD' => $this->process_field_row('preview', $profile_row[1])),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 0,
+ 'field_minlen' => 0,
+ 'field_maxlen' => 5,
+ 'field_validation' => '',
+ 'field_novalue' => 0,
+ 'field_default_value' => 0,
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_field_value($field_data)
+ {
+ return $field_data['field_default_value'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+ return $this->request->variable($var_name, (int) $profile_row['field_default_value']);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ $field_value = (int) $field_value;
+
+ // retrieve option lang data if necessary
+ if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], 1))
+ {
+ $this->lang_helper->get_option_lang($field_data['field_id'], $field_data['lang_id'], $this->get_service_name(), false);
+ }
+
+ if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], $field_value))
+ {
+ return $this->user->lang('FIELD_INVALID_VALUE', $this->get_field_name($field_data['lang_name']));
+ }
+
+ if ($field_value == $field_data['field_novalue'] && $field_data['field_required'])
+ {
+ return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name']));
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_value($field_value, $field_data)
+ {
+ $field_id = $field_data['field_id'];
+ $lang_id = $field_data['lang_id'];
+ if (!$this->lang_helper->is_set($field_id, $lang_id))
+ {
+ $this->lang_helper->get_option_lang($field_id, $lang_id, $this->get_service_name(), false);
+ }
+
+ if ($field_value == $field_data['field_novalue'] && !$field_data['field_show_novalue'])
+ {
+ return null;
+ }
+
+ $field_value = (int) $field_value;
+
+ // User not having a value assigned
+ if (!$this->lang_helper->is_set($field_id, $lang_id, $field_value))
+ {
+ if ($field_data['field_show_novalue'])
+ {
+ $field_value = $field_data['field_novalue'];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ return $this->lang_helper->get($field_id, $lang_id, $field_value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+ $default_value = $profile_row['field_default_value'];
+
+ $value = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]);
+
+ if (!$this->lang_helper->is_set($profile_row['field_id'], $profile_row['lang_id'], 1))
+ {
+ $this->lang_helper->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], $this->get_service_name(), $preview_options);
+ }
+
+ $profile_row['field_value'] = (int) $value;
+ $this->template->assign_block_vars('dropdown', array_change_key_case($profile_row, CASE_UPPER));
+
+ $options = $this->lang_helper->get($profile_row['field_id'], $profile_row['lang_id']);
+ foreach ($options as $option_id => $option_value)
+ {
+ $this->template->assign_block_vars('dropdown.options', array(
+ 'OPTION_ID' => $option_id,
+ 'SELECTED' => ($value == $option_id) ? ' selected="selected"' : '',
+ 'VALUE' => $option_value,
+ ));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'UINT';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ 'lang_options' => 'optionfield',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_options_form(&$exclude_options, &$visibility_options)
+ {
+ $exclude_options[1][] = 'lang_options';
+
+ return $this->request->variable('lang_options', '', true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_options_on_submit($error, $field_data)
+ {
+ if (!sizeof($field_data['lang_options']))
+ {
+ $error[] = $this->user->lang['NO_FIELD_ENTRIES'];
+ }
+
+ return $error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 2 && $key == 'field_maxlen')
+ {
+ // Get the number of options if this key is 'field_maxlen'
+ return sizeof(explode("\n", $this->request->variable('lang_options', '', true)));
+ }
+
+ return parent::get_excluded_options($key, $action, $current_value, $field_data, $step);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function display_options(&$template_vars, &$field_data)
+ {
+ // Initialize these array elements if we are creating a new field
+ if (!sizeof($field_data['lang_options']))
+ {
+ // No options have been defined for the dropdown menu
+ $field_data['lang_options'] = array();
+ }
+
+ $template_vars = array_merge($template_vars, array(
+ 'S_DROPDOWN' => true,
+ 'L_LANG_OPTIONS_EXPLAIN' => $this->user->lang['DROPDOWN_ENTRIES_EXPLAIN'],
+ 'LANG_OPTIONS' => implode("\n", $field_data['lang_options']),
+ ));
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_int.php b/phpBB/phpbb/profilefields/type/type_int.php
new file mode 100644
index 0000000000..c98c863e13
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_int.php
@@ -0,0 +1,234 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_int extends type_base
+{
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'int';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'),
+ 1 => array('TITLE' => $this->user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $this->user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'),
+ 3 => array('TITLE' => $this->user->lang['DEFAULT_VALUE'], 'FIELD' => '<input type="number" name="field_default_value" value="' . $field_data['field_default_value'] . '" />'),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 5,
+ 'field_minlen' => 0,
+ 'field_maxlen' => 100,
+ 'field_validation' => '',
+ 'field_novalue' => 0,
+ 'field_default_value' => 0,
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_field_value($field_data)
+ {
+ if ($field_data['field_default_value'] === '')
+ {
+ // We cannot insert an empty string into an integer column.
+ return null;
+ }
+
+ return $field_data['field_default_value'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+ if ($this->request->is_set($var_name) && $this->request->variable($var_name, '') === '')
+ {
+ return null;
+ }
+ else
+ {
+ return $this->request->variable($var_name, (int) $profile_row['field_default_value']);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ if (trim($field_value) === '' && !$field_data['field_required'])
+ {
+ return false;
+ }
+
+ $field_value = (int) $field_value;
+
+ if ($field_value < $field_data['field_minlen'])
+ {
+ return $this->user->lang('FIELD_TOO_SMALL', (int) $field_data['field_minlen'], $this->get_field_name($field_data['lang_name']));
+ }
+ else if ($field_value > $field_data['field_maxlen'])
+ {
+ return $this->user->lang('FIELD_TOO_LARGE', (int) $field_data['field_maxlen'], $this->get_field_name($field_data['lang_name']));
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_value($field_value, $field_data)
+ {
+ if (($field_value === '' || $field_value === null) && !$field_data['field_show_novalue'])
+ {
+ return null;
+ }
+ return (int) $field_value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+ $default_value = $profile_row['field_default_value'];
+
+ if ($this->request->is_set($field_ident))
+ {
+ $value = ($this->request->variable($field_ident, '') === '') ? null : $this->request->variable($field_ident, $default_value);
+ }
+ else
+ {
+ if ($preview_options === false && array_key_exists($field_ident, $this->user->profile_fields) && is_null($this->user->profile_fields[$field_ident]))
+ {
+ $value = null;
+ }
+ else if (!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false)
+ {
+ $value = $default_value;
+ }
+ else
+ {
+ $value = $this->user->profile_fields[$field_ident];
+ }
+ }
+
+ $profile_row['field_value'] = (is_null($value) || $value === '') ? '' : (int) $value;
+
+ $this->template->assign_block_vars('int', array_change_key_case($profile_row, CASE_UPPER));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_field_ident($field_data)
+ {
+ return 'pf_' . $field_data['field_ident'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'BINT';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 2 && $key == 'field_default_value')
+ {
+ // Permit an empty string
+ if ($action == 'create' && $this->request->variable('field_default_value', '') === '')
+ {
+ return '';
+ }
+ }
+
+ return parent::get_excluded_options($key, $action, $current_value, $field_data, $step);
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_interface.php b/phpBB/phpbb/profilefields/type/type_interface.php
new file mode 100644
index 0000000000..a1c3d879c8
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_interface.php
@@ -0,0 +1,205 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+interface type_interface
+{
+ /**
+ * Get the translated name of the type
+ *
+ * @return string Translated name of the field type
+ */
+ public function get_name();
+
+ /**
+ * Get the short name of the type, used for error messages and template loops
+ *
+ * @return string lowercase version of the fields type
+ */
+ public function get_name_short();
+
+ /**
+ * Get the name of service representing the type
+ *
+ * @return string lowercase version of the fields type
+ */
+ public function get_service_name();
+
+ /**
+ * Get the name of template file for this type
+ *
+ * @return string Returns the name of the template file
+ */
+ public function get_template_filename();
+
+ /**
+ * Get dropdown options for second step in ACP
+ *
+ * @param string $default_lang_id ID of the default language
+ * @param array $field_data Array with data for this field
+ * @return array with the acp options
+ */
+ public function get_options($default_lang_id, $field_data);
+
+ /**
+ * Get default values for the options of this type
+ *
+ * @return array with values like default field size and more
+ */
+ public function get_default_option_values();
+
+ /**
+ * Get default value for this type
+ *
+ * @param array $field_data Array with data for this field
+ * @return mixed default value for new users when no value is given
+ */
+ public function get_default_field_value($field_data);
+
+ /**
+ * Get profile field value on submit
+ *
+ * @param array $profile_row Array with data for this field
+ * @return mixed Submitted value of the profile field
+ */
+ public function get_profile_field($profile_row);
+
+ /**
+ * Validate entered profile field data
+ *
+ * @param mixed $field_value Field value to validate
+ * @param array $field_data Array with requirements of the field
+ * @return mixed String with the error message
+ */
+ public function validate_profile_field(&$field_value, $field_data);
+
+ /**
+ * Get Profile Value for display
+ *
+ * @param mixed $field_value Field value as stored in the database
+ * @param array $field_data Array with requirements of the field
+ * @return mixed Field value to display
+ */
+ public function get_profile_value($field_value, $field_data);
+
+ /**
+ * Get Profile Value for display
+ *
+ * When displaying a contact field, we don't want to have links already parsed and more
+ *
+ * @param mixed $field_value Field value as stored in the database
+ * @param array $field_data Array with requirements of the field
+ * @return mixed Field value to display
+ */
+ public function get_profile_contact_value($field_value, $field_data);
+
+ /**
+ * Generate the input field for display
+ *
+ * @param array $profile_row Array with data for this field
+ * @param mixed $preview_options When previewing we use different data
+ * @return null
+ */
+ public function generate_field($profile_row, $preview_options = false);
+
+ /**
+ * Get the ident of the field
+ *
+ * Some types are multivalue, we can't give them a field_id
+ * as we would not know which to pick.
+ *
+ * @param array $field_data Array with data for this field
+ * @return string ident of the field
+ */
+ public function get_field_ident($field_data);
+
+ /**
+ * Get the column type for the database
+ *
+ * @return string Returns the database column type
+ */
+ public function get_database_column_type();
+
+ /**
+ * Get the options we need to display for the language input fields in the ACP
+ *
+ * @param array $field_data Array with data for this field
+ * @return array Returns the language options we need to generate
+ */
+ public function get_language_options($field_data);
+
+ /**
+ * Get the input for the supplied language options
+ *
+ * @param array $field_data Array with data for this field
+ * @return array Returns the language options we need to generate
+ */
+ public function get_language_options_input($field_data);
+
+ /**
+ * Allows exclusion of options in single steps of the creation process
+ *
+ * @param array $exclude_options Array with options that should be excluded in the steps
+ * @param array $visibility_options Array with options responsible for the fields visibility
+ * @return mixed Returns the provided language options
+ */
+ public function prepare_options_form(&$exclude_options, &$visibility_options);
+
+ /**
+ * Allows exclusion of options in single steps of the creation process
+ *
+ * @param array $error Array with error messages
+ * @param array $field_data Array with data for this field
+ * @return array Array with error messages
+ */
+ public function validate_options_on_submit($error, $field_data);
+
+ /**
+ * Allows manipulating the intended variables if needed
+ *
+ * @param string $key Name of the option
+ * @param string $action Currently performed action (create|edit)
+ * @param mixed $current_value Currently value of the option
+ * @param array $field_data Array with data for this field
+ * @param int $step Step on which the option is excluded
+ * @return mixed Final value of the option
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step);
+
+ /**
+ * Allows manipulating the intended variables if needed
+ *
+ * @param string $key Name of the option
+ * @param int $step Step on which the option is hidden
+ * @param string $action Currently performed action (create|edit)
+ * @param array $field_data Array with data for this field
+ * @return mixed Final value of the option
+ */
+ public function prepare_hidden_fields($step, $key, $action, &$field_data);
+
+ /**
+ * Allows assigning of additional template variables
+ *
+ * @param array $template_vars Template variables we are going to assign
+ * @param array $field_data Array with data for this field
+ * @return null
+ */
+ public function display_options(&$template_vars, &$field_data);
+
+ /**
+ * Return templated value/field. Possible values for $mode are:
+ * change == user is able to set/enter profile values; preview == just show the value
+ *
+ * @param string $mode Mode for displaying the field (preview|change)
+ * @param array $profile_row Array with data for this field
+ * @return null
+ */
+ public function process_field_row($mode, $profile_row);
+}
diff --git a/phpBB/phpbb/profilefields/type/type_string.php b/phpBB/phpbb/profilefields/type/type_string.php
new file mode 100644
index 0000000000..9dada592eb
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_string.php
@@ -0,0 +1,156 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_string extends type_string_common
+{
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'string';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'),
+ 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'),
+ 3 => array('TITLE' => $this->user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options($field_data) . '</select>'),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 10,
+ 'field_minlen' => 0,
+ 'field_maxlen' => 20,
+ 'field_validation' => '.*',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+ return $this->request->variable($var_name, (string) $profile_row['field_default_value'], true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ return $this->validate_string_profile_field('string', $field_value, $field_data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+ $default_value = $profile_row['lang_default_value'];
+ $profile_row['field_value'] = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value, true) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]);
+
+ $this->template->assign_block_vars($this->get_name_short(), array_change_key_case($profile_row, CASE_UPPER));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'VCHAR';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ if (strlen($field_data['lang_default_value']))
+ {
+ $options['lang_default_value'] = 'string';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function display_options(&$template_vars, &$field_data)
+ {
+ $template_vars = array_merge($template_vars, array(
+ 'S_STRING' => true,
+ 'L_DEFAULT_VALUE_EXPLAIN' => $this->user->lang['STRING_DEFAULT_VALUE_EXPLAIN'],
+ 'LANG_DEFAULT_VALUE' => $field_data['lang_default_value'],
+ ));
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_string_common.php b/phpBB/phpbb/profilefields/type/type_string_common.php
new file mode 100644
index 0000000000..78e219a61f
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_string_common.php
@@ -0,0 +1,128 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+abstract class type_string_common extends type_base
+{
+ protected $validation_options = array(
+ 'CHARS_ANY' => '.*',
+ 'NUMBERS_ONLY' => '[0-9]+',
+ 'ALPHA_ONLY' => '[\w]+',
+ 'ALPHA_UNDERSCORE' => '[\w_]+',
+ 'ALPHA_SPACERS' => '[\w_\+\. \-\[\]]+',
+ );
+
+ /**
+ * Return possible validation options
+ */
+ public function validate_options($field_data)
+ {
+ $validate_options = '';
+ foreach ($this->validation_options as $lang => $value)
+ {
+ $selected = ($field_data['field_validation'] == $value) ? ' selected="selected"' : '';
+ $validate_options .= '<option value="' . $value . '"' . $selected . '>' . $this->user->lang[$lang] . '</option>';
+ }
+
+ return $validate_options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_field_value($field_data)
+ {
+ return $field_data['lang_default_value'];
+ }
+
+ /**
+ * Validate entered profile field data
+ *
+ * @param string $field_type Field type (string or text)
+ * @param mixed $field_value Field value to validate
+ * @param array $field_data Array with requirements of the field
+ * @return mixed String with key of the error language string, false otherwise
+ */
+ public function validate_string_profile_field($field_type, &$field_value, $field_data)
+ {
+ if (trim($field_value) === '' && !$field_data['field_required'])
+ {
+ return false;
+ }
+ else if (trim($field_value) === '' && $field_data['field_required'])
+ {
+ return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name']));
+ }
+
+ if ($field_data['field_minlen'] && utf8_strlen($field_value) < $field_data['field_minlen'])
+ {
+ return $this->user->lang('FIELD_TOO_SHORT', (int) $field_data['field_minlen'], $this->get_field_name($field_data['lang_name']));
+ }
+ else if ($field_data['field_maxlen'] && utf8_strlen(html_entity_decode($field_value)) > $field_data['field_maxlen'])
+ {
+ return $this->user->lang('FIELD_TOO_LONG', (int) $field_data['field_maxlen'], $this->get_field_name($field_data['lang_name']));
+ }
+
+ if (!empty($field_data['field_validation']) && $field_data['field_validation'] != '.*')
+ {
+ $field_validate = ($field_type != 'text') ? $field_value : bbcode_nl2br($field_value);
+ if (!preg_match('#^' . str_replace('\\\\', '\\', $field_data['field_validation']) . '$#i', $field_validate))
+ {
+ $validation = array_search($field_data['field_validation'], $this->validation_options);
+ if ($validation)
+ {
+ return $this->user->lang('FIELD_INVALID_CHARS_' . $validation, $this->get_field_name($field_data['lang_name']));
+ }
+ return $this->user->lang('FIELD_INVALID_CHARS_INVALID', $this->get_field_name($field_data['lang_name']));
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_value($field_value, $field_data)
+ {
+ if (!$field_value && !$field_data['field_show_novalue'])
+ {
+ return null;
+ }
+
+ $field_value = make_clickable($field_value);
+ $field_value = censor_text($field_value);
+ $field_value = bbcode_nl2br($field_value);
+ return $field_value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_contact_value($field_value, $field_data)
+ {
+ if (!$field_value && !$field_data['field_show_novalue'])
+ {
+ return null;
+ }
+
+ return $field_value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_options_form(&$exclude_options, &$visibility_options)
+ {
+ $exclude_options[1][] = 'lang_default_value';
+
+ return $this->request->variable('lang_options', '', true);
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_text.php b/phpBB/phpbb/profilefields/type/type_text.php
new file mode 100644
index 0000000000..660bb20ef8
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_text.php
@@ -0,0 +1,201 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_text extends type_string_common
+{
+ /**
+ * Request object
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * Template object
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * User object
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\request\request $request Request object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param string $language_table Table where the language strings are stored
+ */
+ public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'text';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="rows" size="5" value="' . $field_data['rows'] . '" /> ' . $this->user->lang['ROWS'] . '</dd><dd><input type="number" min="0" max="99999" name="columns" size="5" value="' . $field_data['columns'] . '" /> ' . $this->user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $field_data['field_length'] . '" />'),
+ 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_minlen" size="10" value="' . $field_data['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_maxlen" size="10" value="' . $field_data['field_maxlen'] . '" />'),
+ 3 => array('TITLE' => $this->user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options($field_data) . '</select>'),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => '5|80',
+ 'field_minlen' => 0,
+ 'field_maxlen' => 1000,
+ 'field_validation' => '.*',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_profile_field($profile_row)
+ {
+ $var_name = 'pf_' . $profile_row['field_ident'];
+ return $this->request->variable($var_name, (string) $profile_row['field_default_value'], true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ return $this->validate_string_profile_field('text', $field_value, $field_data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate_field($profile_row, $preview_options = false)
+ {
+ $field_length = explode('|', $profile_row['field_length']);
+ $profile_row['field_rows'] = $field_length[0];
+ $profile_row['field_cols'] = $field_length[1];
+ $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
+ $field_ident = $profile_row['field_ident'];
+ $default_value = $profile_row['lang_default_value'];
+
+ $profile_row['field_value'] = ($this->request->is_set($field_ident)) ? $this->request->variable($field_ident, $default_value, true) : ((!isset($this->user->profile_fields[$field_ident]) || $preview_options !== false) ? $default_value : $this->user->profile_fields[$field_ident]);
+
+ $this->template->assign_block_vars('text', array_change_key_case($profile_row, CASE_UPPER));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_database_column_type()
+ {
+ return 'MTEXT';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_language_options($field_data)
+ {
+ $options = array(
+ 'lang_name' => 'string',
+ );
+
+ if ($field_data['lang_explain'])
+ {
+ $options['lang_explain'] = 'text';
+ }
+
+ if (strlen($field_data['lang_default_value']))
+ {
+ $options['lang_default_value'] = 'text';
+ }
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_excluded_options($key, $action, $current_value, &$field_data, $step)
+ {
+ if ($step == 2 && $key == 'field_length')
+ {
+ if ($this->request->is_set('rows'))
+ {
+ $field_data['rows'] = $this->request->variable('rows', 0);
+ $field_data['columns'] = $this->request->variable('columns', 0);
+ $current_value = $field_data['rows'] . '|' . $field_data['columns'];
+ }
+ else
+ {
+ $row_col = explode('|', $current_value);
+ $field_data['rows'] = $row_col[0];
+ $field_data['columns'] = $row_col[1];
+ }
+
+ return $current_value;
+ }
+
+ return parent::get_excluded_options($key, $action, $current_value, $field_data, $step);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_hidden_fields($step, $key, $action, &$field_data)
+ {
+ if ($key == 'field_length' && $this->request->is_set('rows'))
+ {
+ $field_data['rows'] = $this->request->variable('rows', 0);
+ $field_data['columns'] = $this->request->variable('columns', 0);
+ return $field_data['rows'] . '|' . $field_data['columns'];
+ }
+
+ return parent::prepare_hidden_fields($step, $key, $action, $field_data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function display_options(&$template_vars, &$field_data)
+ {
+ $template_vars = array_merge($template_vars, array(
+ 'S_TEXT' => true,
+ 'L_DEFAULT_VALUE_EXPLAIN' => $this->user->lang['TEXT_DEFAULT_VALUE_EXPLAIN'],
+ 'LANG_DEFAULT_VALUE' => $field_data['lang_default_value'],
+ ));
+ }
+}
diff --git a/phpBB/phpbb/profilefields/type/type_url.php b/phpBB/phpbb/profilefields/type/type_url.php
new file mode 100644
index 0000000000..b1523b9355
--- /dev/null
+++ b/phpBB/phpbb/profilefields/type/type_url.php
@@ -0,0 +1,70 @@
+<?php
+/**
+*
+* @package phpBB
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\profilefields\type;
+
+class type_url extends type_string
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function get_name_short()
+ {
+ return 'url';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_options($default_lang_id, $field_data)
+ {
+ $options = array(
+ 0 => array('TITLE' => $this->user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" name="field_length" size="5" value="' . $field_data['field_length'] . '" />'),
+ 1 => array('TITLE' => $this->user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_minlen" size="5" value="' . $field_data['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $this->user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_maxlen" size="5" value="' . $field_data['field_maxlen'] . '" />'),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_default_option_values()
+ {
+ return array(
+ 'field_length' => 40,
+ 'field_minlen' => 0,
+ 'field_maxlen' => 200,
+ 'field_validation' => '',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate_profile_field(&$field_value, $field_data)
+ {
+ $field_value = trim($field_value);
+
+ if ($field_value === '' && !$field_data['field_required'])
+ {
+ return false;
+ }
+
+ if (!preg_match('#^' . get_preg_expression('url') . '$#i', $field_value))
+ {
+ return $this->user->lang('FIELD_INVALID_URL', $this->get_field_name($field_data['lang_name']));
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php b/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php
new file mode 100644
index 0000000000..6ef63ec906
--- /dev/null
+++ b/phpBB/phpbb/recursive_dot_prefix_filter_iterator.php
@@ -0,0 +1,28 @@
+<?php
+/**
+*
+* @package extension
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb;
+
+/**
+* Class recursive_dot_prefix_filter_iterator
+*
+* This filter ignores directories starting with a dot.
+* When searching for php classes and template files of extensions
+* we don't need to look inside these directories.
+*
+* @package phpbb
+*/
+class recursive_dot_prefix_filter_iterator extends \RecursiveFilterIterator
+{
+ public function accept()
+ {
+ $filename = $this->current()->getFilename();
+ return !$this->current()->isDir() || $filename[0] !== '.';
+ }
+}
diff --git a/phpBB/phpbb/request/deactivated_super_global.php b/phpBB/phpbb/request/deactivated_super_global.php
index b03624593e..b6940cf51f 100644
--- a/phpBB/phpbb/request/deactivated_super_global.php
+++ b/phpBB/phpbb/request/deactivated_super_global.php
@@ -112,4 +112,3 @@ class deactivated_super_global implements \ArrayAccess, \Countable, \IteratorAgg
$this->error();
}
}
-
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index cdd2da222f..e5b0c89cb6 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -36,7 +36,7 @@ class fulltext_mysql extends \phpbb\search\base
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -216,7 +216,7 @@ class fulltext_mysql extends \phpbb\search\base
// We limit the number of allowed keywords to minimize load on the database
if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords'])
{
- trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], sizeof($this->split_words)));
+ trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], sizeof($this->split_words)));
}
// to allow phrase search, we need to concatenate quoted words
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index 1b314a24d3..7d51d164c7 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -80,7 +80,7 @@ class fulltext_native extends \phpbb\search\base
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -277,7 +277,7 @@ class fulltext_native extends \phpbb\search\base
// We limit the number of allowed keywords to minimize load on the database
if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords'])
{
- trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], $num_keywords));
+ trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], $num_keywords));
}
// $keywords input format: each word separated by a space, words in a bracket are not separated
@@ -325,7 +325,12 @@ class fulltext_native extends \phpbb\search\base
}
$this->db->sql_freeresult($result);
}
- unset($exact_words);
+
+ // Handle +, - without preceeding whitespace character
+ $match = array('#(\S)\+#', '#(\S)-#');
+ $replace = array('$1 +', '$1 +');
+
+ $keywords = preg_replace($match, $replace, $keywords);
// now analyse the search query, first split it using the spaces
$query = explode(' ', $keywords);
@@ -451,39 +456,21 @@ class fulltext_native extends \phpbb\search\base
$this->{$mode . '_ids'}[] = $words[$word];
}
}
- // throw an error if we shall not ignore unexistant words
- else if (!$ignore_no_id)
+ else
{
if (!isset($common_ids[$word]))
{
$len = utf8_strlen($word);
- if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
- {
- trigger_error(sprintf($this->user->lang['WORD_IN_NO_POST'], $word));
- }
- else
+ if ($len < $this->word_length['min'] || $len > $this->word_length['max'])
{
$this->common_words[] = $word;
}
}
}
- else
- {
- $len = utf8_strlen($word);
- if ($len < $this->word_length['min'] || $len > $this->word_length['max'])
- {
- $this->common_words[] = $word;
- }
- }
- }
-
- // we can't search for negatives only
- if (!sizeof($this->must_contain_ids))
- {
- return false;
}
- if (!empty($this->search_query))
+ // Return true if all words are not common words
+ if (sizeof($exact_words) - sizeof($this->common_words) > 0)
{
return true;
}
@@ -518,6 +505,12 @@ class fulltext_native extends \phpbb\search\base
return false;
}
+ // we can't search for negatives only
+ if (empty($this->must_contain_ids))
+ {
+ return false;
+ }
+
$must_contain_ids = $this->must_contain_ids;
$must_not_contain_ids = $this->must_not_contain_ids;
$must_exclude_one_ids = $this->must_exclude_one_ids;
diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php
index 063bf52a19..864a53e642 100644
--- a/phpBB/phpbb/search/fulltext_postgres.php
+++ b/phpBB/phpbb/search/fulltext_postgres.php
@@ -61,7 +61,7 @@ class fulltext_postgres extends \phpbb\search\base
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -457,15 +457,13 @@ class fulltext_postgres extends \phpbb\search\base
$sql_where_options .= $sql_match_where;
$tmp_sql_match = array();
- foreach (explode(',', $sql_match) as $sql_match_column)
- {
- $tmp_sql_match[] = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')";
- }
+ $sql_match = str_replace(',', " || ' ' ||", $sql_match);
+ $tmp_sql_match = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')";
$this->db->sql_transaction('begin');
$sql_from = "FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p";
- $sql_where = "WHERE (" . implode(' OR ', $tmp_sql_match) . ")
+ $sql_where = "WHERE (" . $tmp_sql_match . ")
$sql_where_options";
$sql = "SELECT $sql_select
$sql_from
@@ -793,9 +791,9 @@ class fulltext_postgres extends \phpbb\search\base
$this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))");
}
- if (!isset($this->stats['post_text']))
+ if (!isset($this->stats['post_content']))
{
- $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_text ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text))");
+ $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))");
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
@@ -826,9 +824,9 @@ class fulltext_postgres extends \phpbb\search\base
$this->db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']);
}
- if (isset($this->stats['post_text']))
+ if (isset($this->stats['post_content']))
{
- $this->db->sql_query('DROP INDEX ' . $this->stats['post_text']['relname']);
+ $this->db->sql_query('DROP INDEX ' . $this->stats['post_content']['relname']);
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
@@ -846,7 +844,7 @@ class fulltext_postgres extends \phpbb\search\base
$this->get_stats();
}
- return (isset($this->stats['post_text']) && isset($this->stats['post_subject'])) ? true : false;
+ return (isset($this->stats['post_subject']) && isset($this->stats['post_content'])) ? true : false;
}
/**
@@ -888,13 +886,13 @@ class fulltext_postgres extends \phpbb\search\base
// deal with older PostgreSQL versions which didn't use Index_type
if (strpos($row['indexdef'], 'to_tsvector') !== false)
{
- if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_text' || $row['relname'] == POSTS_TABLE . '_post_text')
+ if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject')
{
- $this->stats['post_text'] = $row;
+ $this->stats['post_subject'] = $row;
}
- else if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject')
+ else if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_content' || $row['relname'] == POSTS_TABLE . '_post_content')
{
- $this->stats['post_subject'] = $row;
+ $this->stats['post_content'] = $row;
}
}
}
diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php
index acbfad9474..1501dcdc31 100644
--- a/phpBB/phpbb/search/fulltext_sphinx.php
+++ b/phpBB/phpbb/search/fulltext_sphinx.php
@@ -77,7 +77,7 @@ class fulltext_sphinx
/**
* Database connection
- * @var \phpbb\db\driver\driver
+ * @var \phpbb\db\driver\driver_interface
*/
protected $db;
@@ -282,9 +282,9 @@ class fulltext_sphinx
array('sql_attr_uint', 'post_visibility'),
array('sql_attr_bool', 'topic_first_post'),
array('sql_attr_bool', 'deleted'),
- array('sql_attr_timestamp' , 'post_time'),
- array('sql_attr_timestamp' , 'topic_last_post_time'),
- array('sql_attr_str2ordinal', 'post_subject'),
+ array('sql_attr_timestamp', 'post_time'),
+ array('sql_attr_timestamp', 'topic_last_post_time'),
+ array('sql_attr_string', 'post_subject'),
),
'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array(
array('sql_query_pre', ''),
diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php
index 6044effa1f..5bce79fd85 100644
--- a/phpBB/phpbb/template/base.php
+++ b/phpBB/phpbb/template/base.php
@@ -113,6 +113,16 @@ abstract class base implements template
/**
* {@inheritdoc}
*/
+ public function assign_block_vars_array($blockname, array $block_vars_array)
+ {
+ $this->context->assign_block_vars_array($blockname, $block_vars_array);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert')
{
return $this->context->alter_block_array($blockname, $vararray, $key, $mode);
diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php
index 65c7d094a0..a222fbb69e 100644
--- a/phpBB/phpbb/template/context.php
+++ b/phpBB/phpbb/template/context.php
@@ -155,11 +155,12 @@ 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'] = sizeof($str[$blocks[$blockcount]]);
+ $mod_block['S_NUM_ROWS'] = $s_num_rows;
}
}
else
@@ -186,11 +187,12 @@ 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'] = sizeof($this->tpldata[$blockname]);
+ $mod_block['S_NUM_ROWS'] = $s_num_rows;
}
}
@@ -198,6 +200,22 @@ class context
}
/**
+ * Assign key variable pairs from an array to a whole specified block loop
+ *
+ * @param string $blockname Name of block to assign $block_vars_array to
+ * @param array $block_vars_array An array of hashes of variable name => value pairs
+ */
+ public function assign_block_vars_array($blockname, array $block_vars_array)
+ {
+ foreach ($block_vars_array as $vararray)
+ {
+ $this->assign_block_vars($blockname, $vararray);
+ }
+
+ return true;
+ }
+
+ /**
* Change already assigned key variable pair (one-dimensional - single loop entry)
*
* An example of how to use this function:
diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php
index d95b0a822c..87ae7a9766 100644
--- a/phpBB/phpbb/template/template.php
+++ b/phpBB/phpbb/template/template.php
@@ -132,6 +132,14 @@ interface template
public function assign_block_vars($blockname, array $vararray);
/**
+ * Assign key variable pairs from an array to a whole specified block loop
+ * @param string $blockname Name of block to assign $block_vars_array to
+ * @param array $block_vars_array An array of hashes of variable name => value pairs
+ * @return \phpbb\template\template $this
+ */
+ public function assign_block_vars_array($blockname, array $block_vars_array);
+
+ /**
* Change already assigned key variable pair (one-dimensional - single loop entry)
*
* An example of how to use this function:
diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php
index 24bd55b3c5..aa55f1e011 100644
--- a/phpBB/phpbb/template/twig/environment.php
+++ b/phpBB/phpbb/template/twig/environment.php
@@ -11,15 +11,15 @@ namespace phpbb\template\twig;
class environment extends \Twig_Environment
{
- /** @var array */
- protected $phpbb_extensions;
-
/** @var \phpbb\config\config */
protected $phpbb_config;
/** @var \phpbb\path_helper */
protected $phpbb_path_helper;
+ /** @var \phpbb\extension\manager */
+ protected $extension_manager;
+
/** @var string */
protected $phpbb_root_path;
@@ -33,18 +33,19 @@ class environment extends \Twig_Environment
* Constructor
*
* @param \phpbb\config\config $phpbb_config
- * @param array $phpbb_extensions Array of enabled extensions (name => path)
* @param \phpbb\path_helper
+ * @param \phpbb\extension\manager
* @param string $phpbb_root_path
* @param Twig_LoaderInterface $loader
* @param array $options Array of options to pass to Twig
*/
- public function __construct($phpbb_config, $phpbb_extensions, \phpbb\path_helper $path_helper, \Twig_LoaderInterface $loader = null, $options = array())
+ public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array())
{
$this->phpbb_config = $phpbb_config;
- $this->phpbb_extensions = $phpbb_extensions;
$this->phpbb_path_helper = $path_helper;
+ $this->extension_manager = $extension_manager;
+
$this->phpbb_root_path = $this->phpbb_path_helper->get_phpbb_root_path();
$this->web_root_path = $this->phpbb_path_helper->get_web_root_path();
@@ -60,7 +61,7 @@ class environment extends \Twig_Environment
*/
public function get_phpbb_extensions()
{
- return $this->phpbb_extensions;
+ return ($this->extension_manager) ? $this->extension_manager->all_enabled() : array();
}
/**
diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php
index ddadcfd89a..83630f5992 100644
--- a/phpBB/phpbb/template/twig/twig.php
+++ b/phpBB/phpbb/template/twig/twig.php
@@ -94,8 +94,8 @@ class twig extends \phpbb\template\base
$this->twig = new \phpbb\template\twig\environment(
$this->config,
- ($this->extension_manager) ? $this->extension_manager->all_enabled() : array(),
$this->path_helper,
+ $this->extension_manager,
$loader,
array(
'cache' => (defined('IN_INSTALL')) ? false : $this->cachepath,
diff --git a/phpBB/phpbb/tree/nestedset.php b/phpBB/phpbb/tree/nestedset.php
index 13184cf41c..9aaee9e468 100644
--- a/phpBB/phpbb/tree/nestedset.php
+++ b/phpBB/phpbb/tree/nestedset.php
@@ -11,7 +11,7 @@ namespace phpbb\tree;
abstract class nestedset implements \phpbb\tree\tree_interface
{
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\lock\db */
@@ -52,7 +52,7 @@ abstract class nestedset implements \phpbb\tree\tree_interface
/**
* Construct
*
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param \phpbb\lock\db $lock Lock class used to lock the table when moving forums around
* @param string $table_name Table name
* @param string $message_prefix Prefix for the messages thrown by exceptions
@@ -60,7 +60,7 @@ abstract class nestedset implements \phpbb\tree\tree_interface
* @param array $item_basic_data Array with basic item data that is stored in item_parents
* @param array $columns Array with column names to overwrite
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\lock\db $lock, $table_name, $message_prefix = '', $sql_where = '', $item_basic_data = array(), $columns = array())
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\lock\db $lock, $table_name, $message_prefix = '', $sql_where = '', $item_basic_data = array(), $columns = array())
{
$this->db = $db;
$this->lock = $lock;
@@ -664,6 +664,32 @@ abstract class nestedset implements \phpbb\tree\tree_interface
}
/**
+ * Get all items from the tree
+ *
+ * @param bool $order_asc Order the items ascending by their left_id
+ * @return array Array of items (containing all columns from the item table)
+ * ID => Item data
+ */
+ public function get_all_tree_data($order_asc = true)
+ {
+ $rows = array();
+
+ $sql = 'SELECT *
+ FROM ' . $this->table_name . ' ' .
+ $this->get_sql_where('WHERE') . '
+ ORDER BY ' . $this->column_left_id . ' ' . ($order_asc ? 'ASC' : 'DESC');
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $rows[(int) $row[$this->column_item_id]] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ /**
* Remove a subset from the nested set
*
* @param array $subset_items Subset of items to remove
diff --git a/phpBB/phpbb/tree/nestedset_forum.php b/phpBB/phpbb/tree/nestedset_forum.php
index ef6023546b..5973b0b6d9 100644
--- a/phpBB/phpbb/tree/nestedset_forum.php
+++ b/phpBB/phpbb/tree/nestedset_forum.php
@@ -14,11 +14,11 @@ class nestedset_forum extends \phpbb\tree\nestedset
/**
* Construct
*
- * @param \phpbb\db\driver\driver $db Database connection
+ * @param \phpbb\db\driver\driver_interface $db Database connection
* @param \phpbb\lock\db $lock Lock class used to lock the table when moving forums around
* @param string $table_name Table name
*/
- public function __construct(\phpbb\db\driver\driver $db, \phpbb\lock\db $lock, $table_name)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\lock\db $lock, $table_name)
{
parent::__construct(
$db,
diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php
index b2ab187a70..18b7a3d096 100644
--- a/phpBB/phpbb/user.php
+++ b/phpBB/phpbb/user.php
@@ -143,9 +143,17 @@ class user extends \phpbb\session
* that are absolutely needed globally using this
* event. Use local events otherwise.
* @var mixed style_id Style we are going to display
- * @since 3.1-A1
+ * @since 3.1.0-a1
*/
- $vars = array('user_data', 'user_lang_name', 'user_date_format', 'user_timezone', 'lang_set', 'lang_set_ext', 'style_id');
+ $vars = array(
+ 'user_data',
+ 'user_lang_name',
+ 'user_date_format',
+ 'user_timezone',
+ 'lang_set',
+ 'lang_set_ext',
+ 'style_id',
+ );
extract($phpbb_dispatcher->trigger_event('core.user_setup', compact($vars)));
$this->data = $user_data;
@@ -183,7 +191,7 @@ class user extends \phpbb\session
unset($lang_set_ext);
$style_request = request_var('style', 0);
- if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START'))
+ if ($style_request && (!$config['override_user_style'] || $auth->acl_get('a_styles')) && !defined('ADMIN_START'))
{
global $SID, $_EXTRA_URL;
@@ -204,6 +212,19 @@ class user extends \phpbb\session
$this->style = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+ // Fallback to user's standard style
+ if (!$this->style && $style_id != $this->data['user_style'])
+ {
+ $style_id = $this->data['user_style'];
+
+ $sql = 'SELECT *
+ FROM ' . STYLES_TABLE . " s
+ WHERE s.style_id = $style_id";
+ $result = $db->sql_query($sql, 3600);
+ $this->style = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+ }
+
// User has wrong style
if (!$this->style && $style_id == $this->data['user_style'])
{
@@ -618,18 +639,20 @@ class user extends \phpbb\session
else if ($this->lang_name == basename($config['default_lang']))
{
// Fall back to the English Language
+ $reset_lang_name = $this->lang_name;
$this->lang_name = 'en';
$this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
+ $this->lang_name = $reset_lang_name;
}
else if ($this->lang_name == $this->data['user_lang'])
{
// Fall back to the board default language
+ $reset_lang_name = $this->lang_name;
$this->lang_name = basename($config['default_lang']);
$this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
+ $this->lang_name = $reset_lang_name;
}
- // Reset the lang name
- $this->lang_name = (file_exists($lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
return;
}
diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php
index c1d69802f8..9179572277 100644
--- a/phpBB/phpbb/user_loader.php
+++ b/phpBB/phpbb/user_loader.php
@@ -19,7 +19,7 @@ namespace phpbb;
*/
class user_loader
{
- /** @var \phpbb\db\driver\driver */
+ /** @var \phpbb\db\driver\driver_interface */
protected $db = null;
/** @var string */
@@ -41,12 +41,12 @@ class user_loader
/**
* User loader constructor
*
- * @param \phpbb\db\driver\driver $db A database connection
+ * @param \phpbb\db\driver\driver_interface $db A database connection
* @param string $phpbb_root_path Path to the phpbb includes directory.
* @param string $php_ext php file extension
* @param string $users_table The name of the database table (phpbb_users)
*/
- public function __construct(\phpbb\db\driver\driver $db, $phpbb_root_path, $php_ext, $users_table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $users_table)
{
$this->db = $db;
diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php
new file mode 100644
index 0000000000..e2fdf6ce63
--- /dev/null
+++ b/phpBB/phpbb/version_helper.php
@@ -0,0 +1,271 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb;
+
+/**
+ * Class to handle version checking and comparison
+ */
+class version_helper
+{
+ /**
+ * @var string Host
+ */
+ protected $host = 'version.phpbb.com';
+
+ /**
+ * @var string Path to file
+ */
+ protected $path = '/phpbb';
+
+ /**
+ * @var string File name
+ */
+ protected $file = 'versions.json';
+
+ /**
+ * @var string Current version installed
+ */
+ protected $current_version;
+
+ /**
+ * @var null|string Null to not force stability, 'unstable' or 'stable' to
+ * force the corresponding stability
+ */
+ protected $force_stability;
+
+ /** @var \phpbb\cache\service */
+ protected $cache;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\cache\service $cache
+ * @param \phpbb\config\config $config
+ * @param \phpbb\user $user
+ */
+ public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\user $user)
+ {
+ $this->cache = $cache;
+ $this->config = $config;
+ $this->user = $user;
+
+ if (defined('PHPBB_QA'))
+ {
+ $this->force_stability = 'unstable';
+ }
+
+ $this->current_version = $this->config['version'];
+ }
+
+ /**
+ * Set location to the file
+ *
+ * @param string $host Host (e.g. version.phpbb.com)
+ * @param string $path Path to file (e.g. /phpbb)
+ * @param string $file File name (Default: versions.json)
+ * @return version_helper
+ */
+ public function set_file_location($host, $path, $file = 'versions.json')
+ {
+ $this->host = $host;
+ $this->path = $path;
+ $this->file = $file;
+
+ return $this;
+ }
+
+ /**
+ * Set current version
+ *
+ * @param string $version The current version
+ * @return version_helper
+ */
+ public function set_current_version($version)
+ {
+ $this->current_version = $version;
+
+ return $this;
+ }
+
+ /**
+ * Over-ride the stability to force check to include unstable versions
+ *
+ * @param null|string Null to not force stability, 'unstable' or 'stable' to
+ * force the corresponding stability
+ * @return version_helper
+ */
+ public function force_stability($stability)
+ {
+ $this->force_stability = $stability;
+
+ return $this;
+ }
+
+ /**
+ * Wrapper for version_compare() that allows using uppercase A and B
+ * for alpha and beta releases.
+ *
+ * See http://www.php.net/manual/en/function.version-compare.php
+ *
+ * @param string $version1 First version number
+ * @param string $version2 Second version number
+ * @param string $operator Comparison operator (optional)
+ *
+ * @return mixed Boolean (true, false) if comparison operator is specified.
+ * Integer (-1, 0, 1) otherwise.
+ */
+ public function compare($version1, $version2, $operator = null)
+ {
+ return phpbb_version_compare($version1, $version2, $operator);
+ }
+
+ /**
+ * Check whether or not a version is "stable"
+ *
+ * Stable means only numbers OR a pl release
+ *
+ * @param string $version
+ * @return bool Bool true or false
+ */
+ public function is_stable($version)
+ {
+ $matches = false;
+ preg_match('/^[\d\.]+/', $version, $matches);
+
+ if (empty($matches[0]))
+ {
+ return false;
+ }
+
+ return $this->compare($version, $matches[0], '>=');
+ }
+
+ /**
+ * Gets the latest version for the current branch the user is on
+ *
+ * @param bool $force_update Ignores cached data. Defaults to false.
+ * @return string
+ * @throws \RuntimeException
+ */
+ public function get_latest_on_current_branch($force_update = false)
+ {
+ $versions = $this->get_versions_matching_stability($force_update);
+
+ $self = $this;
+ $current_version = $this->current_version;
+
+ // Filter out any versions less than to the current version
+ $versions = array_filter($versions, function($data) use ($self, $current_version) {
+ return $self->compare($data['current'], $current_version, '>=');
+ });
+
+ // Get the lowest version from the previous list.
+ return array_reduce($versions, function($value, $data) use ($self) {
+ if ($value === null || $self->compare($data['current'], $value, '<'))
+ {
+ return $data['current'];
+ }
+
+ return $value;
+ });
+ }
+
+ /**
+ * Obtains the latest version information
+ *
+ * @param bool $force_update Ignores cached data. Defaults to false.
+ * @return string
+ * @throws \RuntimeException
+ */
+ public function get_suggested_updates($force_update = false)
+ {
+ $versions = $this->get_versions_matching_stability($force_update);
+
+ $self = $this;
+ $current_version = $this->current_version;
+
+ // Filter out any versions less than or equal to the current version
+ return array_filter($versions, function($data) use ($self, $current_version) {
+ return $self->compare($data['current'], $current_version, '>');
+ });
+ }
+
+ /**
+ * Obtains the latest version information matching the stability of the current install
+ *
+ * @param bool $force_update Ignores cached data. Defaults to false.
+ * @return string Version info
+ * @throws \RuntimeException
+ */
+ public function get_versions_matching_stability($force_update = false)
+ {
+ $info = $this->get_versions($force_update);
+
+ if ($this->force_stability !== null)
+ {
+ return ($this->force_stability === 'unstable') ? $info['unstable'] : $info['stable'];
+ }
+
+ return ($this->is_stable($this->current_version)) ? $info['stable'] : $info['unstable'];
+ }
+
+ /**
+ * Obtains the latest version information
+ *
+ * @param bool $force_update Ignores cached data. Defaults to false.
+ * @return string Version info, includes stable and unstable data
+ * @throws \RuntimeException
+ */
+ public function get_versions($force_update = false)
+ {
+ $cache_file = 'versioncheck_' . $this->host . $this->path . $this->file;
+
+ $info = $this->cache->get($cache_file);
+
+ if ($info === false || $force_update)
+ {
+ $errstr = $errno = '';
+ $info = get_remote_file($this->host, $this->path, $this->file, $errstr, $errno);
+
+ if (!empty($errstr))
+ {
+ throw new \RuntimeException($errstr);
+ }
+
+ $info = json_decode($info, true);
+
+ if (empty($info['stable']) || empty($info['unstable']))
+ {
+ $this->user->add_lang('acp/common');
+
+ throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL'));
+ }
+
+ // Replace & with &amp; on announcement links
+ foreach ($info as $stability => $branches)
+ {
+ foreach ($branches as $branch => $branch_data)
+ {
+ $info[$stability][$branch]['announcement'] = str_replace('&', '&amp;', $branch_data['announcement']);
+ }
+ }
+
+ $this->cache->put($cache_file, $info, 86400); // 24 hours
+ }
+
+ return $info;
+ }
+}