Merge branch 'develop' of https://github.com/phpbb/phpbb3 into feature/avatars

Conflicts:
	phpBB/install/database_update.php
This commit is contained in:
Marc Alexander 2013-03-04 00:22:15 +01:00
commit d26ad8ed26
183 changed files with 12185 additions and 3635 deletions

View file

@ -7,7 +7,13 @@
<p>{L_EXTENSIONS_EXPLAIN}</p> <p>{L_EXTENSIONS_EXPLAIN}</p>
<p>{L_ENABLE_EXPLAIN}</p> <p>{L_ENABLE_EXPLAIN}</p>
<!-- IF PRE --> <!-- IF MIGRATOR_ERROR -->
<div class="errorbox">
<p><strong>{L_MIGRATION_EXCEPTION_ERROR}</strong></p>
<p>{MIGRATOR_ERROR}</p>
<p><a href="{U_RETURN}">{L_RETURN}</a></p>
</div>
<!-- ELSEIF PRE -->
<div class="errorbox"> <div class="errorbox">
<p>{L_ENABLE_CONFIRM}</p> <p>{L_ENABLE_CONFIRM}</p>
</div> </div>

View file

@ -7,7 +7,13 @@
<p>{L_EXTENSIONS_EXPLAIN}</p> <p>{L_EXTENSIONS_EXPLAIN}</p>
<p>{L_PURGE_EXPLAIN}</p> <p>{L_PURGE_EXPLAIN}</p>
<!-- IF PRE --> <!-- IF MIGRATOR_ERROR -->
<div class="errorbox">
<p><strong>{L_MIGRATION_EXCEPTION_ERROR}</strong></p>
<p>{MIGRATOR_ERROR}</p>
<p><a href="{U_RETURN}">{L_RETURN}</a></p>
</div>
<!-- ELSEIF PRE -->
<div class="errorbox"> <div class="errorbox">
<p>{L_PURGE_CONFIRM}</p> <p>{L_PURGE_CONFIRM}</p>
</div> </div>

View file

@ -492,6 +492,19 @@ phpbb.timezonePreselectSelect = function(forceSelector) {
} }
}; };
// Toggle notification list
$('#notification_list_button').click(function(e) {
$('#notification_list').toggle();
e.preventDefault();
});
$('#phpbb').click(function(e) {
var target = $(e.target);
if (!target.is('#notification_list') && !target.is('#notification_list_button') && !target.parents().is('#notification_list')) {
$('#notification_list').hide();
}
});
phpbb.ajaxCallbacks = {}; phpbb.ajaxCallbacks = {};
/** /**

View file

@ -10,6 +10,8 @@ services:
- %core.php_ext% - %core.php_ext%
- %core.table_prefix% - %core.table_prefix%
- @migrator.tool_collection - @migrator.tool_collection
calls:
- [set_extension_manager, [@ext.manager]]
migrator.tool_collection: migrator.tool_collection:
class: phpbb_di_service_collection class: phpbb_di_service_collection

View file

@ -0,0 +1,314 @@
services:
notification.type_collection:
class: phpbb_di_service_collection
arguments:
- @service_container
tags:
- { name: service_collection, tag: notification.type }
notification.method_collection:
class: phpbb_di_service_collection
arguments:
- @service_container
tags:
- { name: service_collection, tag: notification.method }
notification.type.approve_post:
class: phpbb_notification_type_approve_post
scope: prototype # scope MUST be prototype for this to work! # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.approve_topic:
class: phpbb_notification_type_approve_topic
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.bookmark:
class: phpbb_notification_type_bookmark
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.disapprove_post:
class: phpbb_notification_type_disapprove_post
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.disapprove_topic:
class: phpbb_notification_type_disapprove_topic
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.pm:
class: phpbb_notification_type_pm
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.post:
class: phpbb_notification_type_post
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.post_in_queue:
class: phpbb_notification_type_post_in_queue
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.quote:
class: phpbb_notification_type_quote
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.report_pm:
class: phpbb_notification_type_report_pm
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.report_pm_closed:
class: phpbb_notification_type_report_pm_closed
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.report_post:
class: phpbb_notification_type_report_post
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.report_post_closed:
class: phpbb_notification_type_report_post
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.topic:
class: phpbb_notification_type_topic
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.type.topic_in_queue:
class: phpbb_notification_type_topic_in_queue
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
tags:
- { name: notification.type }
notification.method.email:
class: phpbb_notification_method_email
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
tags:
- { name: notification.method }
notification.method.jabber:
class: phpbb_notification_method_jabber
scope: prototype # scope MUST be prototype for this to work!
arguments:
- @user_loader
- @dbal.conn
- @cache.driver
- @user
- @auth
- @config
- %core.root_path%
- %core.php_ext%
tags:
- { name: notification.method }

View file

@ -1,6 +1,7 @@
imports: imports:
- { resource: tables.yml } - { resource: tables.yml }
- { resource: cron_tasks.yml } - { resource: cron_tasks.yml }
- { resource: notifications.yml }
- { resource: migrator.yml } - { resource: migrator.yml }
- { resource: avatars.yml } - { resource: avatars.yml }
@ -120,12 +121,15 @@ services:
ext.manager: ext.manager:
class: phpbb_extension_manager class: phpbb_extension_manager
arguments: arguments:
- @service_container
- @dbal.conn - @dbal.conn
- @config - @config
- %tables.ext% - %tables.ext%
- %core.root_path% - %core.root_path%
- .%core.php_ext% - .%core.php_ext%
- @cache.driver - @cache.driver
calls:
- [set_migrator, [@migrator]]
ext.finder: ext.finder:
class: phpbb_extension_finder class: phpbb_extension_finder
@ -171,6 +175,21 @@ services:
tags: tags:
- { name: kernel.event_subscriber } - { name: kernel.event_subscriber }
notification_manager:
class: phpbb_notification_manager
arguments:
- @notification.type_collection
- @notification.method_collection
- @service_container
- @user_loader
- @dbal.conn
- @user
- %core.root_path%
- %core.php_ext%
- %tables.notification_types%
- %tables.notifications%
- %tables.user_notifications%
request: request:
class: phpbb_request class: phpbb_request
@ -213,3 +232,11 @@ services:
user: user:
class: phpbb_user class: phpbb_user
user_loader:
class: phpbb_user_loader
arguments:
- @dbal.conn
- %core.root_path%
- %core.php_ext%
- %tables.users%

View file

@ -1,5 +1,9 @@
parameters: parameters:
tables.config: %core.table_prefix%config tables.config: %core.table_prefix%config
tables.ext: %core.table_prefix%ext tables.ext: %core.table_prefix%ext
tables.notification_types: %core.table_prefix%notification_types
tables.notifications: %core.table_prefix%notifications
tables.user_notifications: %core.table_prefix%user_notifications
tables.users: %core.table_prefix%users
tables.migrations: %core.table_prefix%migrations tables.migrations: %core.table_prefix%migrations
tables.modules: %core.table_prefix%modules tables.modules: %core.table_prefix%modules

View file

@ -1308,6 +1308,32 @@ function get_schema_struct()
), ),
); );
$schema_data['phpbb_notification_types'] = array(
'COLUMNS' => array(
'notification_type' => array('VCHAR:255', ''),
'notification_type_enabled' => array('BOOL', 1),
),
'PRIMARY_KEY' => array('notification_type', 'notification_type_enabled'),
);
$schema_data['phpbb_notifications'] = array(
'COLUMNS' => array(
'notification_id' => array('UINT', NULL, 'auto_increment'),
'item_type' => array('VCHAR:255', ''),
'item_id' => array('UINT', 0),
'item_parent_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'notification_read' => array('BOOL', 0),
'notification_time' => array('TIMESTAMP', 1),
'notification_data' => array('TEXT_UNI', ''),
),
'PRIMARY_KEY' => 'notification_id',
'KEYS' => array(
'item_ident' => array('INDEX', array('item_type', 'item_id')),
'user' => array('INDEX', array('user_id', 'notification_read')),
),
);
$schema_data['phpbb_poll_options'] = array( $schema_data['phpbb_poll_options'] = array(
'COLUMNS' => array( 'COLUMNS' => array(
'poll_option_id' => array('TINT:4', 0), 'poll_option_id' => array('TINT:4', 0),
@ -1769,6 +1795,16 @@ function get_schema_struct()
), ),
); );
$schema_data['phpbb_user_notifications'] = array(
'COLUMNS' => array(
'item_type' => array('VCHAR:255', ''),
'item_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'method' => array('VCHAR:255', ''),
'notify' => array('BOOL', 1),
),
);
$schema_data['phpbb_user_group'] = array( $schema_data['phpbb_user_group'] = array(
'COLUMNS' => array( 'COLUMNS' => array(
'group_id' => array('UINT', 0), 'group_id' => array('UINT', 0),

View file

@ -23,11 +23,11 @@ involved in phpBB.
phpBB Lead Developer: naderman (Nils Adermann) phpBB Lead Developer: naderman (Nils Adermann)
phpBB Developers: bantu (Andreas Fischer) phpBB Developers: bantu (Andreas Fischer)
EXreaction (Nathan Guse)
igorw (Igor Wiedler) igorw (Igor Wiedler)
imkingdavid (David King) imkingdavid (David King)
nickvergessen (Joas Schilling) nickvergessen (Joas Schilling)
Oleg (Oleg Pudeyev) Oleg (Oleg Pudeyev)
rxu (Ruslan Uzdenov)
Contributions by: leviatan21 (Gabriel Vazquez) Contributions by: leviatan21 (Gabriel Vazquez)
Raimon (Raimon Meuldijk) Raimon (Raimon Meuldijk)
@ -53,6 +53,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010]
dhn (Dominik Dröscher) [05/2007 - 01/2011] dhn (Dominik Dröscher) [05/2007 - 01/2011]
GrahamJE (Graham Eames) [09/2005 - 11/2006] GrahamJE (Graham Eames) [09/2005 - 11/2006]
kellanved (Henry Sudhof) [04/2007 - 03/2011] kellanved (Henry Sudhof) [04/2007 - 03/2011]
rxu (Ruslan Uzdenov) [04/2010 - 12/2012]
TerraFrost (Jim Wigginton) [04/2009 - 01/2011] TerraFrost (Jim Wigginton) [04/2009 - 01/2011]
ToonArmy (Chris Smith) [06/2008 - 11/2011] ToonArmy (Chris Smith) [06/2008 - 11/2011]
Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009] Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009]

View file

@ -329,6 +329,7 @@ class acp_board
'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'legend2' => 'GENERAL_OPTIONS', 'legend2' => 'GENERAL_OPTIONS',
'load_notifications' => array('lang' => 'LOAD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@ -428,8 +429,8 @@ class acp_board
'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true),
'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true),
'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true),
'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),

View file

@ -37,7 +37,7 @@ class acp_extensions
$this->template = $template; $this->template = $template;
$this->user = $user; $this->user = $user;
$user->add_lang(array('install', 'acp/extensions')); $user->add_lang(array('install', 'acp/extensions', 'migrator'));
$this->page_title = 'ACP_EXTENSIONS'; $this->page_title = 'ACP_EXTENSIONS';
@ -103,11 +103,18 @@ class acp_extensions
trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action)); trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action));
} }
if ($phpbb_extension_manager->enable_step($ext_name)) try
{ {
$template->assign_var('S_NEXT_STEP', true); if ($phpbb_extension_manager->enable_step($ext_name))
{
$template->assign_var('S_NEXT_STEP', true);
meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name)); meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name));
}
}
catch (phpbb_db_migration_exception $e)
{
$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user));
} }
$this->tpl_name = 'acp_ext_enable'; $this->tpl_name = 'acp_ext_enable';
@ -156,11 +163,18 @@ class acp_extensions
break; break;
case 'purge': case 'purge':
if ($phpbb_extension_manager->purge_step($ext_name)) try
{ {
$template->assign_var('S_NEXT_STEP', true); if ($phpbb_extension_manager->purge_step($ext_name))
{
$template->assign_var('S_NEXT_STEP', true);
meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name)); meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name));
}
}
catch (phpbb_db_migration_exception $e)
{
$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user));
} }
$this->tpl_name = 'acp_ext_purge'; $this->tpl_name = 'acp_ext_purge';

View file

@ -125,13 +125,34 @@ class acp_groups
{ {
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
} }
else if (empty($mark_ary))
{
trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
if (confirm_box(true)) if (confirm_box(true))
{ {
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
if (!sizeof($mark_ary)) break;
case 'set_default_on_all':
if (confirm_box(true))
{ {
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
$start = 0; $start = 0;
do do
@ -162,28 +183,25 @@ class acp_groups
$db->sql_freeresult($result); $db->sql_freeresult($result);
} }
while ($start); while ($start);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
} }
else else
{ {
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
} }
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
break; break;
case 'deleteusers': case 'deleteusers':
if (empty($mark_ary))
{
trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
case 'delete': case 'delete':
if (!$group_id) if (!$group_id)
{ {
@ -683,7 +701,7 @@ class acp_groups
'U_ACTION' => $this->u_action . "&amp;g=$group_id", 'U_ACTION' => $this->u_action . "&amp;g=$group_id",
'U_BACK' => $this->u_action, 'U_BACK' => $this->u_action,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'), 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'),
'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=default&amp;g=$group_id", 'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=set_default_on_all&amp;g=$group_id",
)); ));
// Grab the members // Grab the members

View file

@ -535,8 +535,14 @@ class acp_modules
/** /**
* Get available module information from module files * Get available module information from module files
*
* @param string $module
* @param bool|string $module_class
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @return array
*/ */
function get_module_infos($module = '', $module_class = false) function get_module_infos($module = '', $module_class = false, $use_all_available = false)
{ {
global $phpbb_root_path, $phpEx; global $phpbb_root_path, $phpEx;
@ -556,7 +562,7 @@ class acp_modules
->extension_directory("/$module_class") ->extension_directory("/$module_class")
->core_path("includes/$module_class/info/") ->core_path("includes/$module_class/info/")
->core_prefix($module_class . '_') ->core_prefix($module_class . '_')
->get_classes(); ->get_classes(true, $use_all_available);
foreach ($modules as $module) foreach ($modules as $module)
{ {

View file

@ -16,10 +16,10 @@ class acp_extensions_info
{ {
return array( return array(
'filename' => 'acp_extensions', 'filename' => 'acp_extensions',
'title' => 'ACP_EXTENSIONS_MANAGEMENT', 'title' => 'ACP_EXTENSION_MANAGEMENT',
'version' => '1.0.0', 'version' => '1.0.0',
'modes' => array( 'modes' => array(
'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSIONS_MANAGEMENT')), 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')),
), ),
); );
} }

View file

@ -240,6 +240,8 @@ define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts');
define('MIGRATIONS_TABLE', $table_prefix . 'migrations'); define('MIGRATIONS_TABLE', $table_prefix . 'migrations');
define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache'); define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache');
define('MODULES_TABLE', $table_prefix . 'modules'); define('MODULES_TABLE', $table_prefix . 'modules');
define('NOTIFICATION_TYPES_TABLE', $table_prefix . 'notification_types');
define('NOTIFICATIONS_TABLE', $table_prefix . 'notifications');
define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options'); define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options');
define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes'); define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes');
define('POSTS_TABLE', $table_prefix . 'posts'); define('POSTS_TABLE', $table_prefix . 'posts');
@ -273,6 +275,7 @@ define('TOPICS_POSTED_TABLE', $table_prefix . 'topics_posted');
define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track'); define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track');
define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch'); define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch');
define('USER_GROUP_TABLE', $table_prefix . 'user_group'); define('USER_GROUP_TABLE', $table_prefix . 'user_group');
define('USER_NOTIFICATIONS_TABLE', $table_prefix . 'user_notifications');
define('USERS_TABLE', $table_prefix . 'users'); define('USERS_TABLE', $table_prefix . 'users');
define('WARNINGS_TABLE', $table_prefix . 'warnings'); define('WARNINGS_TABLE', $table_prefix . 'warnings');
define('WORDS_TABLE', $table_prefix . 'words'); define('WORDS_TABLE', $table_prefix . 'words');

View file

@ -143,7 +143,7 @@ class phpbb_datetime extends DateTime
'is_short' => strpos($format, self::RELATIVE_WRAPPER) !== false, 'is_short' => strpos($format, self::RELATIVE_WRAPPER) !== false,
'format_short' => substr($format, 0, strpos($format, self::RELATIVE_WRAPPER)) . self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER . substr(strrchr($format, self::RELATIVE_WRAPPER), 1), 'format_short' => substr($format, 0, strpos($format, self::RELATIVE_WRAPPER)) . self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER . substr(strrchr($format, self::RELATIVE_WRAPPER), 1),
'format_long' => str_replace(self::RELATIVE_WRAPPER, '', $format), 'format_long' => str_replace(self::RELATIVE_WRAPPER, '', $format),
'lang' => $user->lang['datetime'], 'lang' => array_filter($user->lang['datetime'], 'is_string'),
); );
// Short representation of month in format? Some languages use different terms for the long and short format of May // Short representation of month in format? Some languages use different terms for the long and short format of May

View file

@ -303,7 +303,7 @@ class phpbb_db_tools
* @param phpbb_db_driver $db Database connection * @param phpbb_db_driver $db Database connection
* @param bool $return_statements True if only statements should be returned and no SQL being executed * @param bool $return_statements True if only statements should be returned and no SQL being executed
*/ */
function phpbb_db_tools(&$db, $return_statements = false) function phpbb_db_tools(phpbb_db_driver $db, $return_statements = false)
{ {
$this->db = $db; $this->db = $db;
$this->return_statements = $return_statements; $this->return_statements = $return_statements;

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_1_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.1')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_10 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.10', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_10_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10')),
);
}
}

View file

@ -0,0 +1,30 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_10_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.10-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_9');
}
public function update_data()
{
return array(
array('config.add', array('email_max_chunk_size', 50)),
array('config.update', array('version', '3.0.10-rc1')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_10_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.10-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_10_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10-rc2')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_10_rc3 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.10-rc3', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_10_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10-rc3')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_11 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.11', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.11')),
);
}
}

View file

@ -0,0 +1,95 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_11_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.11-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_10');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'cleanup_deactivated_styles'))),
array('custom', array(array(&$this, 'delete_orphan_private_messages'))),
array('config.update', array('version', '3.0.11-rc1')),
);
}
public function cleanup_deactivated_styles()
{
// Updates users having current style a deactivated one
$sql = 'SELECT style_id
FROM ' . STYLES_TABLE . '
WHERE style_active = 0';
$result = $this->sql_query($sql);
$deactivated_style_ids = array();
while ($style_id = $this->db->sql_fetchfield('style_id', false, $result))
{
$deactivated_style_ids[] = (int) $style_id;
}
$this->db->sql_freeresult($result);
if (!empty($deactivated_style_ids))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_style = ' . (int) $this->config['default_style'] .'
WHERE ' . $this->db->sql_in_set('user_style', $deactivated_style_ids);
$this->sql_query($sql);
}
}
public function delete_orphan_private_messages()
{
// Delete orphan private messages
$batch_size = 500;
$sql_array = array(
'SELECT' => 'p.msg_id',
'FROM' => array(
PRIVMSGS_TABLE => 'p',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(PRIVMSGS_TO_TABLE => 't'),
'ON' => 'p.msg_id = t.msg_id',
),
),
'WHERE' => 't.user_id IS NULL',
);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $batch_size);
$delete_pms = array();
while ($row = $this->db->sql_fetchrow($result))
{
$delete_pms[] = (int) $row['msg_id'];
}
$this->db->sql_freeresult($result);
if (!empty($delete_pms))
{
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $this->db->sql_in_set('msg_id', $delete_pms);
$this->sql_query($sql);
// Return false to have the Migrator call this function again
return false;
}
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_11_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.11-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11_rc1');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_novalue' => array('BOOL', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_novalue',
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.11-rc2')),
);
}
}

View file

@ -0,0 +1,123 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.12-RC1 **/
class phpbb_db_migration_data_30x_3_0_12_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.12-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_module_auth'))),
array('custom', array(array(&$this, 'update_bots'))),
array('custom', array(array(&$this, 'disable_bots_from_receiving_pms'))),
array('config.update', array('version', '3.0.12-rc1')),
);
}
public function disable_bots_from_receiving_pms()
{
// Disable receiving pms for bots
$sql = 'SELECT user_id
FROM ' . BOTS_TABLE;
$result = $this->db->sql_query($sql);
$bot_user_ids = array();
while ($row = $this->db->sql_fetchrow($result))
{
$bot_user_ids[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
if (!empty($bot_user_ids))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_allow_pm = 0
WHERE ' . $this->db->sql_in_set('user_id', $bot_user_ids);
$this->sql_query($sql);
}
}
public function update_module_auth()
{
$sql = 'UPDATE ' . MODULES_TABLE . '
SET module_auth = \'acl_u_sig\'
WHERE module_class = \'ucp\'
AND module_basename = \'profile\'
AND module_mode = \'signature\'';
$this->sql_query($sql);
}
public function update_bots()
{
// Update bots
if (!function_exists('user_delete'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$bots_updates = array(
// Bot Deletions
'NG-Search [Bot]' => false,
'Nutch/CVS [Bot]' => false,
'OmniExplorer [Bot]' => false,
'Seekport [Bot]' => false,
'Synoo [Bot]' => false,
'WiseNut [Bot]' => false,
// Bot Updates
// Bot name to bot user agent map
'Baidu [Spider]' => 'Baiduspider',
'Exabot [Bot]' => 'Exabot',
'Voyager [Bot]' => 'voyager/',
'W3C [Validator]' => 'W3C_Validator',
);
foreach ($bots_updates as $bot_name => $bot_agent)
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE user_type = ' . USER_IGNORE . "
AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($bot_name)) . "'";
$result = $this->db->sql_query($sql);
$bot_user_id = (int) $this->db->sql_fetchfield('user_id');
$this->db->sql_freeresult($result);
if ($bot_user_id)
{
if ($bot_agent === false)
{
$sql = 'DELETE FROM ' . BOTS_TABLE . "
WHERE user_id = $bot_user_id";
$this->sql_query($sql);
user_delete('remove', $bot_user_id);
}
else
{
$sql = 'UPDATE ' . BOTS_TABLE . "
SET bot_agent = '" . $this->db->sql_escape($bot_agent) . "'
WHERE user_id = $bot_user_id";
$this->sql_query($sql);
}
}
}
}
}

View file

@ -0,0 +1,108 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_1_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.1-rc1', '>=');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'forums' => array(
'display_subforum_list' => array('BOOL', 1),
),
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array('UINT', 0),
),
),
'drop_keys' => array(
$this->table_prefix . 'groups' => array(
'group_legend',
),
),
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array('session_forum_id'),
),
$this->table_prefix . 'groups' => array(
'group_legend_name' => array('group_legend', 'group_name'),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'forums' => array(
'display_subforum_list',
),
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
),
'add_index' => array(
$this->table_prefix . 'groups' => array(
'group_legend' => array('group_legend'),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
$this->table_prefix . 'groups' => array(
'group_legend_name',
),
),
);
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'fix_unset_last_view_time'))),
array('custom', array(array(&$this, 'reset_smiley_size'))),
array('config.update', array('version', '3.0.1-rc1')),
);
}
public function fix_unset_last_view_time()
{
$sql = 'UPDATE ' . $this->table_prefix . "topics
SET topic_last_view_time = topic_last_post_time
WHERE topic_last_view_time = 0";
$this->sql_query($sql);
}
public function reset_smiley_size()
{
// Update smiley sizes
$smileys = array('icon_e_surprised.gif', 'icon_eek.gif', 'icon_cool.gif', 'icon_lol.gif', 'icon_mad.gif', 'icon_razz.gif', 'icon_redface.gif', 'icon_cry.gif', 'icon_evil.gif', 'icon_twisted.gif', 'icon_rolleyes.gif', 'icon_exclaim.gif', 'icon_question.gif', 'icon_idea.gif', 'icon_arrow.gif', 'icon_neutral.gif', 'icon_mrgreen.gif', 'icon_e_ugeek.gif');
foreach ($smileys as $smiley)
{
if (file_exists($this->phpbb_root_path . 'images/smilies/' . $smiley))
{
list($width, $height) = getimagesize($this->phpbb_root_path . 'images/smilies/' . $smiley);
$sql = 'UPDATE ' . SMILIES_TABLE . '
SET smiley_width = ' . $width . ', smiley_height = ' . $height . "
WHERE smiley_url = '" . $this->db->sql_escape($smiley) . "'";
$this->sql_query($sql);
}
}
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_2_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.2')),
);
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_2_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.2-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_1');
}
public function update_data()
{
return array(
array('config.add', array('referer_validation', '1')),
array('config.add', array('check_attachment_content', '1')),
array('config.add', array('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title')),
array('config.update', array('version', '3.0.2-rc1')),
);
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_2_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.2-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_2_rc1');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'drafts' => array(
'draft_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'forums' => array(
'forum_last_post_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'posts' => array(
'post_subject' => array('STEXT_UNI', '', 'true_sort'),
),
$this->table_prefix . 'privmsgs' => array(
'message_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'topics' => array(
'topic_title' => array('STEXT_UNI', '', 'true_sort'),
'topic_last_post_subject' => array('STEXT_UNI', ''),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
),
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_fid' => array('session_forum_id'),
),
),
);
}
public function revert_schema()
{
return array(
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array(
'session_forum_id',
),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_fid',
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.2-rc2')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_3 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.3', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_3_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.3')),
);
}
}

View file

@ -0,0 +1,83 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_3_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.3-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_2');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'styles_template' => array(
'template_inherits_id' => array('UINT:4', 0),
'template_inherit_path' => array('VCHAR', ''),
),
$this->table_prefix . 'groups' => array(
'group_max_recipients' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'styles_template' => array(
'template_inherits_id',
'template_inherit_path',
),
$this->table_prefix . 'groups' => array(
'group_max_recipients',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('enable_queue_trigger', '0')),
array('config.add', array('queue_trigger_posts', '3')),
array('config.add', array('pm_max_recipients', '0')),
array('custom', array(array(&$this, 'set_group_default_max_recipients'))),
array('config.add', array('dbms_version', $this->db->sql_server_info(true))),
array('permission.add', array('u_masspm_group', true, 'u_masspm')),
array('custom', array(array(&$this, 'correct_acp_email_permissions'))),
array('config.update', array('version', '3.0.3-rc1')),
);
}
public function correct_acp_email_permissions()
{
$sql = 'UPDATE ' . $this->table_prefix . 'modules
SET module_auth = \'acl_a_email && cfg_email_enable\'
WHERE module_class = \'acp\'
AND module_basename = \'email\'';
$this->sql_query($sql);
}
public function set_group_default_max_recipients()
{
// Set maximum number of recipients for the registered users, bots, guests group
$sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5
WHERE ' . $this->db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS'));
$this->sql_query($sql);
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_4 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.4', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_4_rc1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'rename_log_delete_topic'))),
array('config.update', array('version', '3.0.4')),
);
}
public function rename_log_delete_topic()
{
if ($this->db->sql_layer == 'oracle')
{
// log_operation is CLOB - but we can change this later
$sql = 'UPDATE ' . $this->table_prefix . "log
SET log_operation = 'LOG_DELETE_TOPIC'
WHERE log_operation LIKE 'LOG_TOPIC_DELETED'";
$this->sql_query($sql);
}
else
{
$sql = 'UPDATE ' . $this->table_prefix . "log
SET log_operation = 'LOG_DELETE_TOPIC'
WHERE log_operation = 'LOG_TOPIC_DELETED'";
$this->sql_query($sql);
}
}
}

View file

@ -0,0 +1,123 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_4_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.4-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_3');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_profile' => array('BOOL', 0),
),
),
'change_columns' => array(
$this->table_prefix . 'styles' => array(
'style_id' => array('UINT', NULL, 'auto_increment'),
'template_id' => array('UINT', 0),
'theme_id' => array('UINT', 0),
'imageset_id' => array('UINT', 0),
),
$this->table_prefix . 'styles_imageset' => array(
'imageset_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_imageset_data' => array(
'image_id' => array('UINT', NULL, 'auto_increment'),
'imageset_id' => array('UINT', 0),
),
$this->table_prefix . 'styles_theme' => array(
'theme_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_template' => array(
'template_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_template_data' => array(
'template_id' => array('UINT', 0),
),
$this->table_prefix . 'forums' => array(
'forum_style' => array('UINT', 0),
),
$this->table_prefix . 'users' => array(
'user_style' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_profile',
),
),
);
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_custom_profile_fields'))),
array('config.update', array('version', '3.0.4-rc1')),
);
}
public function update_custom_profile_fields()
{
// Update the Custom Profile Fields based on previous settings to the new format
$sql = 'SELECT field_id, field_required, field_show_on_reg, field_hide
FROM ' . PROFILE_FIELDS_TABLE;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql_ary = array(
'field_required' => 0,
'field_show_on_reg' => 0,
'field_hide' => 0,
'field_show_profile'=> 0,
);
if ($row['field_required'])
{
$sql_ary['field_required'] = $sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1;
}
else if ($row['field_show_on_reg'])
{
$sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1;
}
else if ($row['field_hide'])
{
// Only administrators and moderators can see this CPF, if the view is enabled, they can see it, otherwise just admins in the acp_users module
$sql_ary['field_hide'] = 1;
}
else
{
// equivelant to "none", which is the "Display in user control panel" option
$sql_ary['field_show_profile'] = 1;
}
$this->sql_query('UPDATE ' . $this->table_prefix . 'profile_fields SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE field_id = ' . $row['field_id'], $errored, $error_ary);
}
$this->db->sql_freeresult($result);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_5 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.5', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_5_rc1part2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.5')),
);
}
}

View file

@ -0,0 +1,124 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_5_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.5-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_4');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'forums' => array(
'forum_style' => array('UINT', 0),
),
),
);
}
public function update_data()
{
$search_indexing_state = $this->config['search_indexing_state'];
return array(
array('config.add', array('captcha_gd_wave', 0)),
array('config.add', array('captcha_gd_3d_noise', 1)),
array('config.add', array('captcha_gd_fonts', 1)),
array('config.add', array('confirm_refresh', 1)),
array('config.add', array('max_num_search_keywords', 10)),
array('config.remove', array('search_indexing_state')),
array('config.add', array('search_indexing_state', $search_indexing_state, true)),
array('custom', array(array(&$this, 'hash_old_passwords'))),
array('custom', array(array(&$this, 'update_ichiro_bot'))),
);
}
public function hash_old_passwords()
{
$sql = 'SELECT user_id, user_password
FROM ' . $this->table_prefix . 'users
WHERE user_pass_convert = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (strlen($row['user_password']) == 32)
{
$sql_ary = array(
'user_password' => phpbb_hash($row['user_password']),
);
$this->sql_query('UPDATE ' . $this->table_prefix . 'users SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $row['user_id']);
}
}
$this->db->sql_freeresult($result);
}
public function update_ichiro_bot()
{
// Adjust bot entry
$sql = 'UPDATE ' . $this->table_prefix . "bots
SET bot_agent = 'ichiro/'
WHERE bot_agent = 'ichiro/2'";
$this->sql_query($sql);
}
public function remove_duplicate_auth_options()
{
// Before we are able to add a unique key to auth_option, we need to remove duplicate entries
$sql = 'SELECT auth_option
FROM ' . $this->table_prefix . 'acl_options
GROUP BY auth_option
HAVING COUNT(*) >= 2';
$result = $this->db->sql_query($sql);
$auth_options = array();
while ($row = $this->db->sql_fetchrow($result))
{
$auth_options[] = $row['auth_option'];
}
$this->db->sql_freeresult($result);
// Remove specific auth options
if (!empty($auth_options))
{
foreach ($auth_options as $option)
{
// Select auth_option_ids... the largest id will be preserved
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option = '" . $db->sql_escape($option) . "'
ORDER BY auth_option_id DESC";
// sql_query_limit not possible here, due to bug in postgresql layer
$result = $this->db->sql_query($sql);
// Skip first row, this is our original auth option we want to preserve
$row = $this->db->sql_fetchrow($result);
while ($row = $this->db->sql_fetchrow($result))
{
// Ok, remove this auth option...
$this->sql_query('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
}
$this->db->sql_freeresult($result);
}
}
}
}

View file

@ -0,0 +1,42 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_5_rc1part2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.5-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_5_rc1');
}
public function update_schema()
{
return array(
'drop_keys' => array(
$this->table_prefix . 'acl_options' => array('auth_option'),
),
'add_unique_index' => array(
$this->table_prefix . 'acl_options' => array(
'auth_option' => array('auth_option'),
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.5-rc1')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_6 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.6', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_6_rc4');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6')),
);
}
}

View file

@ -0,0 +1,324 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_6_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.6-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_5');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'confirm' => array(
'attempts' => array('UINT', 0),
),
$this->table_prefix . 'users' => array(
'user_new' => array('BOOL', 1),
'user_reminded' => array('TINT:4', 0),
'user_reminded_time' => array('TIMESTAMP', 0),
),
$this->table_prefix . 'groups' => array(
'group_skip_auth' => array('BOOL', 0, 'after' => 'group_founder_manage'),
),
$this->table_prefix . 'privmsgs' => array(
'message_reported' => array('BOOL', 0),
),
$this->table_prefix . 'reports' => array(
'pm_id' => array('UINT', 0),
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_vt' => array('BOOL', 0),
),
$this->table_prefix . 'forums' => array(
'forum_options' => array('UINT:20', 0),
),
),
'change_columns' => array(
$this->table_prefix . 'users' => array(
'user_options' => array('UINT:11', 230271),
),
),
'add_index' => array(
$this->table_prefix . 'reports' => array(
'post_id' => array('post_id'),
'pm_id' => array('pm_id'),
),
$this->table_prefix . 'posts' => array(
'post_username' => array('post_username:255'),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'confirm' => array(
'attempts',
),
$this->table_prefix . 'users' => array(
'user_new',
'user_reminded',
'user_reminded_time',
),
$this->table_prefix . 'groups' => array(
'group_skip_auth',
),
$this->table_prefix . 'privmsgs' => array(
'message_reported',
),
$this->table_prefix . 'reports' => array(
'pm_id',
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_vt',
),
$this->table_prefix . 'forums' => array(
'forum_options',
),
),
'drop_keys' => array(
$this->table_prefix . 'reports' => array(
'post_id',
'pm_id',
),
$this->table_prefix . 'posts' => array(
'post_username',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('captcha_plugin', 'phpbb_captcha_nogd')),
array('if', array(
($this->config['captcha_gd']),
array('config.update', array('captcha_plugin', 'phpbb_captcha_gd')),
)),
array('config.add', array('feed_enable', 0)),
array('config.add', array('feed_limit', 10)),
array('config.add', array('feed_overall_forums', 1)),
array('config.add', array('feed_overall_forums_limit', 15)),
array('config.add', array('feed_overall_topics', 0)),
array('config.add', array('feed_overall_topics_limit', 15)),
array('config.add', array('feed_forum', 1)),
array('config.add', array('feed_topic', 1)),
array('config.add', array('feed_item_statistics', 1)),
array('config.add', array('smilies_per_page', 50)),
array('config.add', array('allow_pm_report', 1)),
array('config.add', array('min_post_chars', 1)),
array('config.add', array('allow_quick_reply', 1)),
array('config.add', array('new_member_post_limit', 0)),
array('config.add', array('new_member_group_default', 0)),
array('config.add', array('delete_time', $this->config['edit_time'])),
array('config.add', array('allow_avatar', 0)),
array('if', array(
($this->config['allow_avatar_upload'] || $this->config['allow_avatar_local'] || $this->config['allow_avatar_remote']),
array('config.update', array('allow_avatar', 1)),
)),
array('config.add', array('allow_avatar_remote_upload', 0)),
array('if', array(
($this->config['allow_avatar_remote'] && $this->config['allow_avatar_upload']),
array('config.update', array('allow_avatar_remote_upload', 1)),
)),
array('module.add', array(
'acp',
'ACP_BOARD_CONFIGURATION',
array(
'module_basename' => 'acp_board',
'modes' => array('feed'),
),
)),
array('module.add', array(
'acp',
'ACP_CAT_USERS',
array(
'module_basename' => 'acp_users',
'modes' => array('warnings'),
),
)),
array('module.add', array(
'acp',
'ACP_SERVER_CONFIGURATION',
array(
'module_basename' => 'acp_send_statistics',
'modes' => array('send_statistics'),
),
)),
array('module.add', array(
'acp',
'ACP_FORUM_BASED_PERMISSIONS',
array(
'module_basename' => 'acp_permissions',
'modes' => array('setting_forum_copy'),
),
)),
array('module.add', array(
'mcp',
'MCP_REPORTS',
array(
'module_basename' => 'mcp_pm_reports',
'modes' => array('pm_reports','pm_reports_closed','pm_report_details'),
),
)),
array('custom', array(array(&$this, 'add_newly_registered_group'))),
array('custom', array(array(&$this, 'set_user_options_default'))),
array('config.update', array('version', '3.0.6-rc1')),
);
}
public function set_user_options_default()
{
// 229376 is the added value to enable all three signature options
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_options = user_options + 229376';
$this->sql_query($sql);
}
public function add_newly_registered_group()
{
// Add newly_registered group... but check if it already exists (we always supported running the updater on any schema)
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'NEWLY_REGISTERED'";
$result = $this->db->sql_query($sql);
$group_id = (int) $this->db->sql_fetchfield('group_id');
$this->db->sql_freeresult($result);
if (!$group_id)
{
$sql = 'INSERT INTO ' . GROUPS_TABLE . " (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5)";
$this->sql_query($sql);
$group_id = $this->db->sql_nextid();
}
// Insert new user role... at the end of the chain
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = 'ROLE_USER_NEW_MEMBER'
AND role_type = 'u_'";
$result = $this->db->sql_query($sql);
$u_role = (int) $this->db->sql_fetchfield('role_id');
$this->db->sql_freeresult($result);
if (!$u_role)
{
$sql = 'SELECT MAX(role_order) as max_order_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = 'u_'";
$result = $this->db->sql_query($sql);
$next_order_id = (int) $this->db->sql_fetchfield('max_order_id');
$this->db->sql_freeresult($result);
$next_order_id++;
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', $next_order_id)";
$this->sql_query($sql);
$u_role = $this->db->sql_nextid();
// Now add the correct data to the roles...
// The standard role says that new users are not able to send a PM, Mass PM, are not able to PM groups
$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $u_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group')";
$this->sql_query($sql);
// Add user role to group
$sql = 'INSERT INTO ' . ACL_GROUPS_TABLE . " (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES ($group_id, 0, 0, $u_role, 0)";
$this->sql_query($sql);
}
// Insert new forum role
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = 'ROLE_FORUM_NEW_MEMBER'
AND role_type = 'f_'";
$result = $this->db->sql_query($sql);
$f_role = (int) $this->db->sql_fetchfield('role_id');
$this->db->sql_freeresult($result);
if (!$f_role)
{
$sql = 'SELECT MAX(role_order) as max_order_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = 'f_'";
$result = $this->db->sql_query($sql);
$next_order_id = (int) $this->db->sql_fetchfield('max_order_id');
$this->db->sql_freeresult($result);
$next_order_id++;
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', $next_order_id)";
$this->sql_query($sql);
$f_role = $this->db->sql_nextid();
$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $f_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove')";
$this->sql_query($sql);
}
// Set every members user_new column to 0 (old users) only if there is no one yet (this makes sure we do not execute this more than once)
$sql = 'SELECT 1
FROM ' . USERS_TABLE . '
WHERE user_new = 0';
$result = $this->db->sql_query_limit($sql, 1);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$row)
{
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_new = 0';
$this->sql_query($sql);
}
// To mimick the old "feature" we will assign the forum role to every forum, regardless of the setting (this makes sure there are no "this does not work!!!! YUO!!!" posts...
// Check if the role is already assigned...
$sql = 'SELECT forum_id
FROM ' . ACL_GROUPS_TABLE . '
WHERE group_id = ' . $group_id . '
AND auth_role_id = ' . $f_role;
$result = $this->db->sql_query($sql);
$is_options = (int) $this->db->sql_fetchfield('forum_id');
$this->db->sql_freeresult($result);
// Not assigned at all... :/
if (!$is_options)
{
// Get postable forums
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . '
WHERE forum_type != ' . FORUM_LINK;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$this->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (' . $group_id . ', ' . (int) $row['forum_id'] . ', 0, ' . $f_role . ', 0)');
}
$this->db->sql_freeresult($result);
}
// Clear permissions...
include_once($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
$auth_admin = new auth_admin();
$auth_admin->acl_clear_prefetch();
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_6_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.6-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_6_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6-rc2')),
);
}
}

View file

@ -0,0 +1,40 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_6_rc3 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.6-rc3', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_6_rc2');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_cp_fields'))),
array('config.update', array('version', '3.0.6-rc3')),
);
}
public function update_cp_fields()
{
// Update the Custom Profile Fields based on previous settings to the new format
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . '
SET field_show_on_vt = 1
WHERE field_hide = 0
AND (field_required = 1 OR field_show_on_reg = 1 OR field_show_profile = 1)';
$this->sql_query($sql);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_6_rc4 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.6-rc4', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_6_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6-rc4')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_7 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.7', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_7_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.7')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_7_pl1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.7-pl1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_7');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.7-pl1')),
);
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_7_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.7-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_6');
}
public function update_schema()
{
return array(
'drop_keys' => array(
$this->table_prefix . 'log' => array(
'log_time',
),
),
'add_index' => array(
$this->table_prefix . 'topics_track' => array(
'topic_id' => array('topic_id'),
),
),
);
}
public function revert_schema()
{
return array(
'add_index' => array(
$this->table_prefix . 'log' => array(
'log_time' => array('log_time'),
),
),
'drop_keys' => array(
$this->table_prefix . 'topics_track' => array(
'topic_id',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('feed_overall', 1)),
array('config.add', array('feed_http_auth', 0)),
array('config.add', array('feed_limit_post', $this->config['feed_limit'])),
array('config.add', array('feed_limit_topic', $this->config['feed_overall_topics_limit'])),
array('config.add', array('feed_topics_new', $this->config['feed_overall_topics'])),
array('config.add', array('feed_topics_active', $this->config['feed_overall_topics'])),
array('custom', array(array(&$this, 'delete_text_templates'))),
array('config.update', array('version', '3.0.7-rc1')),
);
}
public function delete_text_templates()
{
// Delete all text-templates from the template_data
$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . '
WHERE template_filename ' . $this->db->sql_like_expression($this->db->any_char . '.txt');
$this->sql_query($sql);
}
}

View file

@ -0,0 +1,73 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_7_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.7-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_7_rc1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_email_hash'))),
array('config.update', array('version', '3.0.7-rc2')),
);
}
public function update_email_hash($start = 0)
{
$limit = 1000;
$sql = 'SELECT user_id, user_email, user_email_hash
FROM ' . USERS_TABLE . '
WHERE user_type <> ' . USER_IGNORE . "
AND user_email <> ''";
$result = $this->db->sql_query_limit($sql, $limit, $start);
$i = 0;
while ($row = $this->db->sql_fetchrow($result))
{
$i++;
// Snapshot of the phpbb_email_hash() function
// We cannot call it directly because the auto updater updates the DB first. :/
$user_email_hash = sprintf('%u', crc32(strtolower($row['user_email']))) . strlen($row['user_email']);
if ($user_email_hash != $row['user_email_hash'])
{
$sql_ary = array(
'user_email_hash' => $user_email_hash,
);
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE user_id = ' . (int) $row['user_id'];
$this->sql_query($sql);
}
}
$this->db->sql_freeresult($result);
if ($i < $limit)
{
// Completed
return;
}
// Return the next start, will be sent to $start when this function is called again
return $start + $limit;
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_8 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.8', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_8_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.8')),
);
}
}

View file

@ -0,0 +1,221 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_8_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.8-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_7_pl1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_file_extension_group_names'))),
array('custom', array(array(&$this, 'update_module_auth'))),
array('custom', array(array(&$this, 'update_bots'))),
array('custom', array(array(&$this, 'delete_orphan_shadow_topics'))),
array('module.add', array(
'acp',
'ACP_MESSAGES',
array(
'module_basename' => 'acp_board',
'modes' => array('post'),
),
)),
array('config.add', array('load_unreads_search', 1)),
array('config.update_if_equals', array(600, 'queue_interval', 60)),
array('config.update_if_equals', array(50, 'email_package_size', 20)),
array('config.update', array('version', '3.0.8-rc1')),
);
}
public function update_file_extension_group_names()
{
// Update file extension group names to use language strings.
$sql = 'SELECT lang_dir
FROM ' . LANG_TABLE;
$result = $this->db->sql_query($sql);
$extension_groups_updated = array();
while ($lang_dir = $this->db->sql_fetchfield('lang_dir'))
{
$lang_dir = basename($lang_dir);
// The language strings we need are either in language/.../acp/attachments.php
// in the update package if we're updating to 3.0.8-RC1 or later,
// or they are in language/.../install.php when we're updating from 3.0.7-PL1 or earlier.
// On an already updated board, they can also already be in language/.../acp/attachments.php
// in the board root.
$lang_files = array(
"{$this->phpbb_root_path}install/update/new/language/$lang_dir/acp/attachments.{$this->php_ext}",
"{$this->phpbb_root_path}language/$lang_dir/install.{$this->php_ext}",
"{$this->phpbb_root_path}language/$lang_dir/acp/attachments.{$this->php_ext}",
);
foreach ($lang_files as $lang_file)
{
if (!file_exists($lang_file))
{
continue;
}
$lang = array();
include($lang_file);
foreach($lang as $lang_key => $lang_val)
{
if (isset($extension_groups_updated[$lang_key]) || strpos($lang_key, 'EXT_GROUP_') !== 0)
{
continue;
}
$sql_ary = array(
'group_name' => substr($lang_key, 10), // Strip off 'EXT_GROUP_'
);
$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . "
WHERE group_name = '" . $this->db->sql_escape($lang_val) . "'";
$this->sql_query($sql);
$extension_groups_updated[$lang_key] = true;
}
}
}
$this->db->sql_freeresult($result);
}
public function update_module_auth()
{
$sql = 'UPDATE ' . MODULES_TABLE . '
SET module_auth = \'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)\'
WHERE module_class = \'ucp\'
AND module_basename = \'profile\'
AND module_mode = \'avatar\'';
$this->sql_query($sql);
}
public function update_bots()
{
$bot_name = 'Bing [Bot]';
$bot_name_clean = utf8_clean_string($bot_name);
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . "
WHERE username_clean = '" . $this->db->sql_escape($bot_name_clean) . "'";
$result = $this->db->sql_query($sql);
$bing_already_added = (bool) $this->db->sql_fetchfield('user_id');
$this->db->sql_freeresult($result);
if (!$bing_already_added)
{
$bot_agent = 'bingbot/';
$bot_ip = '';
$sql = 'SELECT group_id, group_colour
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'BOTS'";
$result = $this->db->sql_query($sql);
$group_row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$group_row)
{
// default fallback, should never get here
$group_row['group_id'] = 6;
$group_row['group_colour'] = '9E8DA7';
}
if (!function_exists('user_add'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$user_row = array(
'user_type' => USER_IGNORE,
'group_id' => $group_row['group_id'],
'username' => $bot_name,
'user_regdate' => time(),
'user_password' => '',
'user_colour' => $group_row['group_colour'],
'user_email' => '',
'user_lang' => $this->config['default_lang'],
'user_style' => $this->config['default_style'],
'user_timezone' => 0,
'user_dateformat' => $this->config['default_dateformat'],
'user_allow_massemail' => 0,
);
$user_id = user_add($user_row);
$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array(
'bot_active' => 1,
'bot_name' => (string) $bot_name,
'user_id' => (int) $user_id,
'bot_agent' => (string) $bot_agent,
'bot_ip' => (string) $bot_ip,
));
$this->sql_query($sql);
}
}
public function delete_orphan_shadow_topics()
{
// Delete shadow topics pointing to not existing topics
$batch_size = 500;
// Set of affected forums we have to resync
$sync_forum_ids = array();
$sql_array = array(
'SELECT' => 't1.topic_id, t1.forum_id',
'FROM' => array(
TOPICS_TABLE => 't1',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(TOPICS_TABLE => 't2'),
'ON' => 't1.topic_moved_id = t2.topic_id',
),
),
'WHERE' => 't1.topic_moved_id <> 0
AND t2.topic_id IS NULL',
);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $batch_size);
$topic_ids = array();
while ($row = $this->db->sql_fetchrow($result))
{
$topic_ids[] = (int) $row['topic_id'];
$sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id'];
}
$this->db->sql_freeresult($result);
if (!empty($topic_ids))
{
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
WHERE ' . $this->db->sql_in_set('topic_id', $topic_ids);
$this->db->sql_query($sql);
// Sync the forums we have deleted shadow topics from.
sync('forum', 'forum_id', $sync_forum_ids, true, true);
return false;
}
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_9 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.9', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_9_rc4');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9')),
);
}
}

View file

@ -0,0 +1,124 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_9_rc1 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.9-rc1', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_8');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'login_attempts' => array(
'COLUMNS' => array(
// this column was removed from the database updater
// after 3.0.9-RC3 was released. It might still exist
// in 3.0.9-RCX installations and has to be dropped in
// 3.0.12 after the db_tools class is capable of properly
// removing a primary key.
// 'attempt_id' => array('UINT', NULL, 'auto_increment'),
'attempt_ip' => array('VCHAR:40', ''),
'attempt_browser' => array('VCHAR:150', ''),
'attempt_forwarded_for' => array('VCHAR:255', ''),
'attempt_time' => array('TIMESTAMP', 0),
'user_id' => array('UINT', 0),
'username' => array('VCHAR_UNI:255', 0),
'username_clean' => array('VCHAR_CI', 0),
),
//'PRIMARY_KEY' => 'attempt_id',
'KEYS' => array(
'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')),
'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')),
'att_time' => array('INDEX', array('attempt_time')),
'user_id' => array('INDEX', 'user_id'),
),
),
),
'change_columns' => array(
$this->table_prefix . 'bbcodes' => array(
'bbcode_id' => array('USINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'login_attempts',
),
);
}
public function update_data()
{
return array(
array('config.add', array('ip_login_limit_max', 50)),
array('config.add', array('ip_login_limit_time', 21600)),
array('config.add', array('ip_login_limit_use_forwarded', 0)),
array('custom', array(array(&$this, 'update_file_extension_group_names'))),
array('custom', array(array(&$this, 'fix_firebird_qa_captcha'))),
array('config.update', array('version', '3.0.9-rc1')),
);
}
public function update_file_extension_group_names()
{
// Update file extension group names to use language strings, again.
$sql = 'SELECT group_id, group_name
FROM ' . EXTENSION_GROUPS_TABLE . '
WHERE group_name ' . $this->db->sql_like_expression('EXT_GROUP_' . $this->db->any_char);
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql_ary = array(
'group_name' => substr($row['group_name'], 10), // Strip off 'EXT_GROUP_'
);
$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE group_id = ' . $row['group_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
public function fix_firebird_qa_captcha()
{
// Recover from potentially broken Q&A CAPTCHA table on firebird
// Q&A CAPTCHA was uninstallable, so it's safe to remove these
// without data loss
if ($this->db_tools->sql_layer == 'firebird')
{
$tables = array(
$this->table_prefix . 'captcha_questions',
$this->table_prefix . 'captcha_answers',
$this->table_prefix . 'qa_confirm',
);
foreach ($tables as $table)
{
if ($this->db_tools->sql_table_exists($table))
{
$this->db_tools->sql_table_drop($table);
}
}
}
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_9_rc2 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.9-rc2', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_9_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-rc2')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_9_rc3 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.9-rc3', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_9_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-rc3')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_30x_3_0_9_rc4 extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.0.9-rc4', '>=');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_9_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-rc4')),
);
}
}

View file

@ -0,0 +1,405 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_dev extends phpbb_db_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.1.0-dev', '>=');
}
static public function depends_on()
{
return array(
'phpbb_db_migration_data_310_extensions',
'phpbb_db_migration_data_310_style_update_p2',
'phpbb_db_migration_data_310_timezone_p2',
'phpbb_db_migration_data_310_reported_posts_display',
);
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'groups' => array(
'group_teampage' => array('UINT', 0, 'after' => 'group_legend'),
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_pm' => array('BOOL', 0),
),
$this->table_prefix . 'styles' => array(
'style_path' => array('VCHAR:100', ''),
'bbcode_bitfield' => array('VCHAR:255', 'kNg='),
'style_parent_id' => array('UINT:4', 0),
'style_parent_tree' => array('TEXT', ''),
),
$this->table_prefix . 'reports' => array(
'reported_post_text' => array('MTEXT_UNI', ''),
'reported_post_uid' => array('VCHAR:8', ''),
'reported_post_bitfield' => array('VCHAR:255', ''),
),
),
'change_columns' => array(
$this->table_prefix . 'groups' => array(
'group_legend' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'groups' => array(
'group_teampage',
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_pm',
),
$this->table_prefix . 'styles' => array(
'style_path',
'bbcode_bitfield',
'style_parent_id',
'style_parent_tree',
),
$this->table_prefix . 'reports' => array(
'reported_post_text',
'reported_post_uid',
'reported_post_bitfield',
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('search_type', 'phpbb_search_' . $this->config['search_type'])),
array('config.add', array('fulltext_postgres_ts_name', 'simple')),
array('config.add', array('fulltext_postgres_min_word_len', 4)),
array('config.add', array('fulltext_postgres_max_word_len', 254)),
array('config.add', array('fulltext_sphinx_stopwords', 0)),
array('config.add', array('fulltext_sphinx_indexer_mem_limit', 512)),
array('config.add', array('load_jquery_cdn', 0)),
array('config.add', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js')),
array('config.add', array('use_system_cron', 0)),
array('config.add', array('legend_sort_groupname', 0)),
array('config.add', array('teampage_forums', 1)),
array('config.add', array('teampage_memberships', 1)),
array('config.add', array('load_cpf_pm', 0)),
array('config.add', array('display_last_subject', 1)),
array('config.add', array('assets_version', 1)),
array('config.add', array('site_home_url', '')),
array('config.add', array('site_home_text', '')),
array('permission.add', array('u_chgprofileinfo', true, 'u_sig')),
array('module.add', array(
'acp',
'ACP_GROUPS',
array(
'module_basename' => 'acp_groups',
'modes' => array('position'),
),
)),
array('module.add', array(
'acp',
'ACP_ATTACHMENTS',
array(
'module_basename' => 'acp_attachments',
'modes' => array('manage'),
),
)),
array('module.add', array(
'acp',
'ACP_STYLE_MANAGEMENT',
array(
'module_basename' => 'acp_styles',
'modes' => array('install', 'cache'),
),
)),
array('module.add', array(
'ucp',
'UCP_PROFILE',
array(
'module_basename' => 'ucp_profile',
'modes' => array('autologin_keys'),
),
)),
// Module will be renamed later
array('module.add', array(
'acp',
'ACP_CAT_STYLES',
'ACP_LANGUAGE'
)),
array('module.remove', array(
'acp',
false,
'ACP_TEMPLATES',
)),
array('module.remove', array(
'acp',
false,
'ACP_THEMES',
)),
array('module.remove', array(
'acp',
false,
'ACP_IMAGESETS',
)),
array('custom', array(array($this, 'rename_module_basenames'))),
array('custom', array(array($this, 'rename_styles_module'))),
array('custom', array(array($this, 'add_group_teampage'))),
array('custom', array(array($this, 'update_group_legend'))),
array('custom', array(array($this, 'localise_global_announcements'))),
array('custom', array(array($this, 'update_ucp_pm_basename'))),
array('custom', array(array($this, 'update_ucp_profile_auth'))),
array('custom', array(array($this, 'move_customise_modules'))),
array('config.update', array('version', '3.1.0-dev')),
);
}
public function move_customise_modules()
{
// Move language management to new location in the Customise tab
// First get language module id
$sql = 'SELECT module_id FROM ' . MODULES_TABLE . "
WHERE module_basename = 'acp_language'";
$result = $this->db->sql_query($sql);
$language_module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
// Next get language management module id of the one just created
$sql = 'SELECT module_id FROM ' . MODULES_TABLE . "
WHERE module_langname = 'ACP_LANGUAGE'";
$result = $this->db->sql_query($sql);
$language_management_module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
if (!class_exists('acp_modules'))
{
include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
}
// acp_modules calls adm_back_link, which is undefined at this point
if (!function_exists('adm_back_link'))
{
include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext);
}
$module_manager = new acp_modules();
$module_manager->module_class = 'acp';
$module_manager->move_module($language_module_id, $language_management_module_id);
}
public function update_ucp_pm_basename()
{
$sql = 'SELECT module_id, module_basename
FROM ' . MODULES_TABLE . "
WHERE module_basename <> 'ucp_pm' AND
module_langname='UCP_PM'";
$result = $this->db->sql_query_limit($sql, 1);
if ($row = $this->db->sql_fetchrow($result))
{
// This update is still not applied. Applying it
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_basename = 'ucp_pm'
WHERE module_id = " . (int) $row['module_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
public function update_ucp_profile_auth()
{
// Update the auth setting for the module
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_auth = 'acl_u_chgprofileinfo'
WHERE module_class = 'ucp'
AND module_basename = 'ucp_profile'
AND module_mode = 'profile_info'";
$this->sql_query($sql);
}
public function rename_styles_module()
{
// Rename styles module to Customise
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_langname = 'ACP_CAT_CUSTOMISE'
WHERE module_langname = 'ACP_CAT_STYLES'";
$this->sql_query($sql);
}
public function rename_module_basenames()
{
// rename all module basenames to full classname
$sql = 'SELECT module_id, module_basename, module_class
FROM ' . MODULES_TABLE;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$module_id = (int) $row['module_id'];
unset($row['module_id']);
if (!empty($row['module_basename']) && !empty($row['module_class']))
{
// all the class names start with class name or with phpbb_ for auto loading
if (strpos($row['module_basename'], $row['module_class'] . '_') !== 0 &&
strpos($row['module_basename'], 'phpbb_') !== 0)
{
$row['module_basename'] = $row['module_class'] . '_' . $row['module_basename'];
$sql_update = $this->db->sql_build_array('UPDATE', $row);
$sql = 'UPDATE ' . MODULES_TABLE . '
SET ' . $sql_update . '
WHERE module_id = ' . $module_id;
$this->sql_query($sql);
}
}
}
$this->db->sql_freeresult($result);
}
public function add_group_teampage()
{
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_teampage = 1
WHERE group_type = ' . GROUP_SPECIAL . "
AND group_name = 'ADMINISTRATORS'";
$this->sql_query($sql);
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_teampage = 2
WHERE group_type = ' . GROUP_SPECIAL . "
AND group_name = 'GLOBAL_MODERATORS'";
$this->sql_query($sql);
}
public function update_group_legend()
{
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . '
WHERE group_legend = 1
ORDER BY group_name ASC';
$result = $this->db->sql_query($sql);
$next_legend = 1;
while ($row = $this->db->sql_fetchrow($result))
{
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_legend = ' . $next_legend . '
WHERE group_id = ' . (int) $row['group_id'];
$this->sql_query($sql);
$next_legend++;
}
$this->db->sql_freeresult($result);
}
public function localise_global_announcements()
{
// Localise Global Announcements
$sql = 'SELECT topic_id, topic_approved, (topic_replies + 1) AS topic_posts, topic_last_post_id, topic_last_post_subject, topic_last_post_time, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour
FROM ' . TOPICS_TABLE . '
WHERE forum_id = 0
AND topic_type = ' . POST_GLOBAL;
$result = $this->db->sql_query($sql);
$global_announcements = $update_lastpost_data = array();
$update_lastpost_data['forum_last_post_time'] = 0;
$update_forum_data = array(
'forum_posts' => 0,
'forum_topics' => 0,
'forum_topics_real' => 0,
);
while ($row = $this->db->sql_fetchrow($result))
{
$global_announcements[] = (int) $row['topic_id'];
$update_forum_data['forum_posts'] += (int) $row['topic_posts'];
$update_forum_data['forum_topics_real']++;
if ($row['topic_approved'])
{
$update_forum_data['forum_topics']++;
}
if ($update_lastpost_data['forum_last_post_time'] < $row['topic_last_post_time'])
{
$update_lastpost_data = array(
'forum_last_post_id' => (int) $row['topic_last_post_id'],
'forum_last_post_subject' => $row['topic_last_post_subject'],
'forum_last_post_time' => (int) $row['topic_last_post_time'],
'forum_last_poster_id' => (int) $row['topic_last_poster_id'],
'forum_last_poster_name' => $row['topic_last_poster_name'],
'forum_last_poster_colour' => $row['topic_last_poster_colour'],
);
}
}
$this->db->sql_freeresult($result);
if (!empty($global_announcements))
{
// Update the post/topic-count for the forum and the last-post if needed
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . '
WHERE forum_type = ' . FORUM_POST;
$result = $this->db->sql_query_limit($sql, 1);
$ga_forum_id = $this->db->sql_fetchfield('forum_id');
$this->db->sql_freeresult($result);
$sql = 'SELECT forum_last_post_time
FROM ' . FORUMS_TABLE . '
WHERE forum_id = ' . $ga_forum_id;
$result = $this->db->sql_query($sql);
$lastpost = (int) $this->db->sql_fetchfield('forum_last_post_time');
$this->db->sql_freeresult($result);
$sql_update = 'forum_posts = forum_posts + ' . $update_forum_data['forum_posts'] . ', ';
$sql_update .= 'forum_topics_real = forum_topics_real + ' . $update_forum_data['forum_topics_real'] . ', ';
$sql_update .= 'forum_topics = forum_topics + ' . $update_forum_data['forum_topics'];
if ($lastpost < $update_lastpost_data['forum_last_post_time'])
{
$sql_update .= ', ' . $this->db->sql_build_array('UPDATE', $update_lastpost_data);
}
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET ' . $sql_update . '
WHERE forum_id = ' . $ga_forum_id;
$this->sql_query($sql);
// Update some forum_ids
$table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);
foreach ($table_ary as $table)
{
$sql = "UPDATE $table
SET forum_id = $ga_forum_id
WHERE " . $this->db->sql_in_set('topic_id', $global_announcements);
$this->sql_query($sql);
}
unset($table_ary);
}
}
}

View file

@ -0,0 +1,69 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_extensions extends phpbb_db_migration
{
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'ext');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'ext' => array(
'COLUMNS' => array(
'ext_name' => array('VCHAR', ''),
'ext_active' => array('BOOL', 0),
'ext_state' => array('TEXT', ''),
),
'KEYS' => array(
'ext_name' => array('UNIQUE', 'ext_name'),
),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'ext',
),
);
}
public function update_data()
{
return array(
// Module will be renamed later
array('module.add', array(
'acp',
'ACP_CAT_STYLES',
'ACP_EXTENSION_MANAGEMENT'
)),
array('module.add', array(
'acp',
'ACP_EXTENSION_MANAGEMENT',
array(
'module_basename' => 'acp_extensions',
'modes' => array('main'),
),
)),
array('permission.add', array('a_extensions', true, 'a_styles')),
);
}
}

View file

@ -0,0 +1,160 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_notifications extends phpbb_db_migration
{
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'notifications');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_310_dev');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'notification_types' => array(
'COLUMNS' => array(
'notification_type' => array('VCHAR:255', ''),
'notification_type_enabled' => array('BOOL', 1),
),
'PRIMARY_KEY' => array('notification_type', 'notification_type_enabled'),
),
$this->table_prefix . 'notifications' => array(
'COLUMNS' => array(
'notification_id' => array('UINT', NULL, 'auto_increment'),
'item_type' => array('VCHAR:255', ''),
'item_id' => array('UINT', 0),
'item_parent_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'notification_read' => array('BOOL', 0),
'notification_time' => array('TIMESTAMP', 1),
'notification_data' => array('TEXT_UNI', ''),
),
'PRIMARY_KEY' => 'notification_id',
'KEYS' => array(
'item_ident' => array('INDEX', array('item_type', 'item_id')),
'user' => array('INDEX', array('user_id', 'notification_read')),
),
),
$this->table_prefix . 'user_notifications' => array(
'COLUMNS' => array(
'item_type' => array('VCHAR:255', ''),
'item_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'method' => array('VCHAR:255', ''),
'notify' => array('BOOL', 1),
),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'notification_types',
$this->table_prefix . 'notifications',
$this->table_prefix . 'user_notifications',
),
);
}
public function update_data()
{
return array(
array('module.add', array(
'ucp',
'UCP_MAIN',
array(
'module_basename' => 'ucp_notifications',
'modes' => array('notification_list'),
),
)),
array('module.add', array(
'ucp',
'UCP_PREFS',
array(
'module_basename' => 'ucp_notifications',
'modes' => array('notification_options'),
),
)),
array('config.add', array('load_notifications', 1)),
array('custom', array(array($this, 'convert_notifications'))),
);
}
public function convert_notifications()
{
$convert_notifications = array(
array(
'check' => ($this->config['allow_topic_notify']),
'item_type' => 'post',
),
array(
'check' => ($this->config['allow_forum_notify']),
'item_type' => 'topic',
),
array(
'check' => ($this->config['allow_bookmarks']),
'item_type' => 'bookmark',
),
array(
'check' => ($this->config['allow_privmsg']),
'item_type' => 'pm',
),
);
foreach ($convert_notifications as $convert_data)
{
if ($convert_data['check'])
{
$sql = 'SELECT user_id, user_notify_type
FROM ' . USERS_TABLE . '
WHERE user_notify = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array(
'item_type' => $convert_data['item_type'],
'item_id' => 0,
'user_id' => $row['user_id'],
'method' => '',
)));
if ($row['user_notify_type'] == NOTIFY_EMAIL || $row['user_notify_type'] == NOTIFY_BOTH)
{
$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array(
'item_type' => $convert_data['item_type'],
'item_id' => 0,
'user_id' => $row['user_id'],
'method' => 'email',
)));
}
if ($row['user_notify_type'] == NOTIFY_IM || $row['user_notify_type'] == NOTIFY_BOTH)
{
$this->sql_query('INSERT INTO ' . $this->table_prefix . 'user_notifications ' . $this->db->sql_build_array('INSERT', array(
'item_type' => $convert_data['item_type'],
'item_id' => 0,
'user_id' => $row['user_id'],
'method' => 'jabber',
)));
}
}
$this->db->sql_freeresult($result);
}
}
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_reported_posts_display extends phpbb_db_migration
{
public function effectively_installed()
{
return $this->db_tools->sql_column_exists($this->table_prefix . 'reports', 'reported_post_enable_bbcode');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'reports' => array(
'reported_post_enable_bbcode' => array('BOOL', 1),
'reported_post_enable_smilies' => array('BOOL', 1),
'reported_post_enable_magic_url' => array('BOOL', 1),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'reports' => array(
'reported_post_enable_bbcode',
'reported_post_enable_smilies',
'reported_post_enable_magic_url',
),
),
);
}
}

View file

@ -0,0 +1,157 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration
{
public function effectively_installed()
{
return !$this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_data()
{
return array(
array('custom', array(array($this, 'styles_update'))),
);
}
public function styles_update()
{
// Get list of valid 3.1 styles
$available_styles = array('prosilver');
$iterator = new DirectoryIterator($this->phpbb_root_path . 'styles');
$skip_dirs = array('.', '..', 'prosilver');
foreach ($iterator as $fileinfo)
{
if ($fileinfo->isDir() && !in_array($fileinfo->getFilename(), $skip_dirs) && file_exists($fileinfo->getPathname() . '/style.cfg'))
{
$style_cfg = parse_cfg_file($fileinfo->getPathname() . '/style.cfg');
if (isset($style_cfg['phpbb_version']) && version_compare($style_cfg['phpbb_version'], '3.1.0-dev', '>='))
{
// 3.1 style
$available_styles[] = $fileinfo->getFilename();
}
}
}
// Get all installed styles
if ($this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset'))
{
$sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_id, i.imageset_path
FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . 'styles_theme c, ' . $this->table_prefix . "styles_imageset i
WHERE t.template_id = s.template_id
AND c.theme_id = s.theme_id
AND i.imageset_id = s.imageset_id";
}
else
{
$sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_id
FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . "stles_theme c
WHERE t.template_id = s.template_id
AND c.theme_id = s.theme_id";
}
$result = $this->db->sql_query($sql);
$styles = array();
while ($row = $this->db->sql_fetchrow($result))
{
$styles[] = $row;
}
$this->db->sql_freeresult($result);
// Decide which styles to keep, all others will be deleted
$valid_styles = array();
foreach ($styles as $style_row)
{
if (
// Delete styles with parent style (not supported yet)
$style_row['template_inherits_id'] == 0 &&
// Check if components match
$style_row['template_path'] == $style_row['theme_path'] && (!isset($style_row['imageset_path']) || $style_row['template_path'] == $style_row['imageset_path']) &&
// Check if components are valid
in_array($style_row['template_path'], $available_styles)
)
{
// Valid style. Keep it
$sql_ary = array(
'style_path' => $style_row['template_path'],
'bbcode_bitfield' => $style_row['bbcode_bitfield'],
'style_parent_id' => 0,
'style_parent_tree' => '',
);
$this->sql_query('UPDATE ' . STYLES_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE style_id = ' . $style_row['style_id']);
$valid_styles[] = (int) $style_row['style_id'];
}
}
// Remove old entries from styles table
if (!sizeof($valid_styles))
{
// No valid styles: remove everything and add prosilver
$this->sql_query('DELETE FROM ' . STYLES_TABLE, $errored, $error_ary);
$sql_ary = array(
'style_name' => 'prosilver',
'style_copyright' => '&copy; phpBB Group',
'style_active' => 1,
'style_path' => 'prosilver',
'bbcode_bitfield' => 'lNg=',
'style_parent_id' => 0,
'style_parent_tree' => '',
// Will be removed in the next step
'imageset_id' => 0,
'template_id' => 0,
'theme_id' => 0,
);
$sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
$this->sql_query($sql);
$sql = 'SELECT style_id
FROM ' . $table . "
WHERE style_name = 'prosilver'";
$result = $this->sql_query($sql);
$default_style = $this->db->sql_fetchfield($result);
$this->db->sql_freeresult($result);
set_config('default_style', $default_style);
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = 0';
$this->sql_query($sql);
}
else
{
// There are valid styles in styles table. Remove styles that are outdated
$this->sql_query('DELETE FROM ' . STYLES_TABLE . '
WHERE ' . $this->db->sql_in_set('style_id', $valid_styles, true));
// Change default style
if (!in_array($this->config['default_style'], $valid_styles))
{
$this->sql_query('UPDATE ' . CONFIG_TABLE . "
SET config_value = '" . $valid_styles[0] . "'
WHERE config_name = 'default_style'");
}
// Reset styles for users
$this->sql_query('UPDATE ' . USERS_TABLE . '
SET user_style = 0
WHERE ' . $this->db->sql_in_set('user_style', $valid_styles, true));
}
}
}

View file

@ -0,0 +1,129 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_style_update_p2 extends phpbb_db_migration
{
public function effectively_installed()
{
return !$this->db_tools->sql_table_exists($this->table_prefix . 'styles_imageset');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_310_style_update_p1');
}
public function update_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'styles' => array(
'imageset_id',
'template_id',
'theme_id',
),
),
'drop_tables' => array(
$this->table_prefix . 'styles_imageset',
$this->table_prefix . 'styles_imageset_data',
$this->table_prefix . 'styles_template',
$this->table_prefix . 'styles_template_data',
$this->table_prefix . 'styles_theme',
),
);
}
public function revert_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'styles' => array(
'imageset_id' => array('UINT', 0),
'template_id' => array('UINT', 0),
'theme_id' => array('UINT', 0),
),
),
'add_tables' => array(
$this->table_prefix . 'styles_imageset' => array(
'COLUMNS' => array(
'imageset_id' => array('UINT', NULL, 'auto_increment'),
'imageset_name' => array('VCHAR_UNI:255', ''),
'imageset_copyright' => array('VCHAR_UNI', ''),
'imageset_path' => array('VCHAR:100', ''),
),
'PRIMARY_KEY' => 'imageset_id',
'KEYS' => array(
'imgset_nm' => array('UNIQUE', 'imageset_name'),
),
),
$this->table_prefix . 'styles_imageset_data' => array(
'COLUMNS' => array(
'image_id' => array('UINT', NULL, 'auto_increment'),
'image_name' => array('VCHAR:200', ''),
'image_filename' => array('VCHAR:200', ''),
'image_lang' => array('VCHAR:30', ''),
'image_height' => array('USINT', 0),
'image_width' => array('USINT', 0),
'imageset_id' => array('UINT', 0),
),
'PRIMARY_KEY' => 'image_id',
'KEYS' => array(
'i_d' => array('INDEX', 'imageset_id'),
),
),
$this->table_prefix . 'styles_template' => array(
'COLUMNS' => array(
'template_id' => array('UINT', NULL, 'auto_increment'),
'template_name' => array('VCHAR_UNI:255', ''),
'template_copyright' => array('VCHAR_UNI', ''),
'template_path' => array('VCHAR:100', ''),
'bbcode_bitfield' => array('VCHAR:255', 'kNg='),
'template_storedb' => array('BOOL', 0),
'template_inherits_id' => array('UINT:4', 0),
'template_inherit_path' => array('VCHAR', ''),
),
'PRIMARY_KEY' => 'template_id',
'KEYS' => array(
'tmplte_nm' => array('UNIQUE', 'template_name'),
),
),
$this->table_prefix . 'styles_template_data' => array(
'COLUMNS' => array(
'template_id' => array('UINT', 0),
'template_filename' => array('VCHAR:100', ''),
'template_included' => array('TEXT', ''),
'template_mtime' => array('TIMESTAMP', 0),
'template_data' => array('MTEXT_UNI', ''),
),
'KEYS' => array(
'tid' => array('INDEX', 'template_id'),
'tfn' => array('INDEX', 'template_filename'),
),
),
$this->table_prefix . 'styles_theme' => array(
'COLUMNS' => array(
'theme_id' => array('UINT', NULL, 'auto_increment'),
'theme_name' => array('VCHAR_UNI:255', ''),
'theme_copyright' => array('VCHAR_UNI', ''),
'theme_path' => array('VCHAR:100', ''),
'theme_storedb' => array('BOOL', 0),
'theme_mtime' => array('TIMESTAMP', 0),
'theme_data' => array('MTEXT_UNI', ''),
),
'PRIMARY_KEY' => 'theme_id',
'KEYS' => array(
'theme_name' => array('UNIQUE', 'theme_name'),
),
),
),
);
}
}

View file

@ -1,16 +1,67 @@
<?php <?php
/** /**
* *
* @package phpBB3 * @package migration
* @copyright (c) 2012 phpBB Group * @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/ */
/** class phpbb_db_migration_data_310_timezone extends phpbb_db_migration
* phpBB Update Helpers
*/
class phpbb_update_helpers
{ {
public function effectively_installed()
{
return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_dst');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'users' => array(
'user_timezone' => array('VCHAR:100', ''),
),
),
);
}
public function update_data()
{
return array(
array('custom', array(array($this, 'update_timezones'))),
);
}
public function update_timezones()
{
// Update user timezones
$sql = 'SELECT user_dst, user_timezone
FROM ' . $this->table_prefix . 'users
GROUP BY user_timezone, user_dst';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql = 'UPDATE ' . $this->table_prefix . "users
SET user_timezone = '" . $this->db->sql_escape($this->convert_phpbb30_timezone($row['user_timezone'], $row['user_dst'])) . "'
WHERE user_timezone = '" . $this->db->sql_escape($row['user_timezone']) . "'
AND user_dst = " . (int) $row['user_dst'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
// Update board default timezone
$sql = 'UPDATE ' . $this->table_prefix . "config
SET config_value = '" . $this->convert_phpbb30_timezone($this->config['board_timezone'], $this->config['board_dst']) . "'
WHERE config_name = 'board_timezone'";
$this->sql_query($sql);
}
/** /**
* Determine the new timezone for a given phpBB 3.0 timezone and * Determine the new timezone for a given phpBB 3.0 timezone and
* "Daylight Saving Time" option * "Daylight Saving Time" option
@ -19,7 +70,7 @@ class phpbb_update_helpers
* @param $dst int Users daylight saving time * @param $dst int Users daylight saving time
* @return string Users new php Timezone which is used since 3.1 * @return string Users new php Timezone which is used since 3.1
*/ */
function convert_phpbb30_timezone($timezone, $dst) public function convert_phpbb30_timezone($timezone, $dst)
{ {
$offset = $timezone + $dst; $offset = $timezone + $dst;

View file

@ -0,0 +1,43 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_timezone_p2 extends phpbb_db_migration
{
public function effectively_installed()
{
return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_dst');
}
static public function depends_on()
{
return array('phpbb_db_migration_data_310_timezone');
}
public function update_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'users' => array(
'user_dst',
),
),
);
}
public function revert_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'users' => array(
'user_dst' => array('BOOL', 0),
),
),
);
}
}

View file

@ -52,4 +52,28 @@ class phpbb_db_migration_exception extends \Exception
{ {
return $this->message . ': ' . var_export($this->parameters, true); return $this->message . ': ' . var_export($this->parameters, true);
} }
/**
* Get the parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get localised message (with $user->lang())
*
* @param phpbb_user $user
* @return string
*/
public function getLocalisedMessage(phpbb_user $user)
{
$parameters = $this->getParameters();
array_unshift($parameters, $this->getMessage());
return call_user_func_array(array($user, 'lang'), $parameters);
}
} }

View file

@ -49,7 +49,7 @@ class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interfac
{ {
if (isset($this->config[$config_name])) if (isset($this->config[$config_name]))
{ {
throw new phpbb_db_migration_exception('CONFIG_ALREADY_EXISTS', $config_name); throw new phpbb_db_migration_exception('CONFIG_ALREADY_EXIST', $config_name);
} }
$this->config->set($config_name, $config_value, !$is_dynamic); $this->config->set($config_name, $config_value, !$is_dynamic);

View file

@ -183,25 +183,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
$basename = str_replace(array('/', '\\'), '', $basename); $basename = str_replace(array('/', '\\'), '', $basename);
$class = str_replace(array('/', '\\'), '', $class); $class = str_replace(array('/', '\\'), '', $class);
$include_path = ($include_path === false) ? $this->phpbb_root_path . 'includes/' : $include_path; $module = $this->get_module_info($class, $basename);
$info_file = "$class/info/$basename.{$this->php_ext}";
// The manual and automatic ways both failed...
if (!file_exists($include_path . $info_file))
{
throw new phpbb_db_migration_exception('MODULE_INFO_FILE_NOT_EXIST', $class, $info_file);
}
$classname = "{$basename}_info";
if (!class_exists($classname))
{
include($include_path . $info_file);
}
$info = new $classname;
$module = $info->module();
unset($info);
$result = ''; $result = '';
foreach ($module['modes'] as $mode => $module_info) foreach ($module['modes'] as $mode => $module_info)
@ -242,14 +224,14 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
if (!$module_id) if (!$module_id)
{ {
throw new phpbb_db_migration_exception('MODULE_PARENT_NOT_EXIST', $parent); throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent);
} }
$parent = $data['parent_id'] = $module_id; $parent = $data['parent_id'] = $module_id;
} }
else if (!$this->exists($class, false, $parent)) else if (!$this->exists($class, false, $parent))
{ {
throw new phpbb_db_migration_exception('MODULE_PARENT_NOT_EXIST', $parent); throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent);
} }
if ($this->exists($class, $parent, $data['module_langname'])) if ($this->exists($class, $parent, $data['module_langname']))
@ -373,30 +355,13 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
$basename = str_replace(array('/', '\\'), '', $module['module_basename']); $basename = str_replace(array('/', '\\'), '', $module['module_basename']);
$class = str_replace(array('/', '\\'), '', $class); $class = str_replace(array('/', '\\'), '', $class);
$include_path = ($include_path === false) ? $this->phpbb_root_path . 'includes/' : $include_path; $module_info = $this->get_module_info($class, $basename);
$info_file = "$class/info/$basename.{$this->php_ext}";
if (!file_exists($include_path . $info_file))
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $info_file);
}
$classname = "{$basename}_info";
if (!class_exists($classname))
{
include($include_path . $info_file);
}
$info = new $classname;
$module_info = $info->module();
unset($info);
foreach ($module_info['modes'] as $mode => $info) foreach ($module_info['modes'] as $mode => $info)
{ {
if (!isset($module['modes']) || in_array($mode, $module['modes'])) if (!isset($module['modes']) || in_array($mode, $module['modes']))
{ {
$this->remove($class, $parent, $info['title']) . '<br />'; $this->remove($class, $parent, $info['title']);
} }
} }
} }
@ -477,7 +442,7 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
$result = $acp_modules->delete_module($module_id); $result = $acp_modules->delete_module($module_id);
if (!empty($result)) if (!empty($result))
{ {
throw new phpbb_db_migration_exception('CANNOT_REMOVE_MODULE', $module_id); throw new phpbb_db_migration_exception('MODULE_NOT_REMOVABLE', $module_id, $result);
} }
} }
@ -510,4 +475,28 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
return call_user_func_array(array(&$this, $call), $arguments); return call_user_func_array(array(&$this, $call), $arguments);
} }
} }
/**
* Wrapper for acp_modules::get_module_infos()
*
* @param string $class Module Class
* @param string $basename Module Basename
* @return array Module Information
*/
protected function get_module_info($class, $basename)
{
if (!class_exists('acp_modules'))
{
include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
}
$acp_modules = new acp_modules();
$module = $acp_modules->get_module_infos($basename, $class, true);
if (empty($module))
{
throw new phpbb_db_migration_exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename);
}
return array_pop($module);
}
} }

View file

@ -107,7 +107,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte
{ {
if ($this->exists($auth_option, $global)) if ($this->exists($auth_option, $global))
{ {
throw new phpbb_db_migration_exception('PERMISSION_ALREADY_EXISTS', $auth_option); throw new phpbb_db_migration_exception('PERMISSION_ALREADY_EXIST', $auth_option);
} }
// We've added permissions, so set to true to notify the user. // We've added permissions, so set to true to notify the user.
@ -252,7 +252,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte
if ($role_id) if ($role_id)
{ {
throw new phpbb_db_migration_exception('ROLE_ALREADY_EXISTS', $old_role_name); return;
} }
$sql = 'SELECT MAX(role_order) AS max_role_order $sql = 'SELECT MAX(role_order) AS max_role_order
@ -290,7 +290,7 @@ class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_inte
if (!$role_id) if (!$role_id)
{ {
throw new phpbb_db_migration_exception('ROLE_NOT_EXISTS', $old_role_name); throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $old_role_name);
} }
$sql = 'UPDATE ' . ACL_ROLES_TABLE . " $sql = 'UPDATE ' . ACL_ROLES_TABLE . "

View file

@ -31,6 +31,9 @@ class phpbb_db_migrator
/** @var phpbb_db_tools */ /** @var phpbb_db_tools */
protected $db_tools; protected $db_tools;
/** @var phpbb_extension_manager */
protected $extension_manager;
/** @var string */ /** @var string */
protected $table_prefix; protected $table_prefix;
@ -90,6 +93,16 @@ class phpbb_db_migrator
$this->load_migration_state(); $this->load_migration_state();
} }
/**
* Set Extension Manager (required)
*
* Not in constructor to prevent circular reference error
*/
public function set_extension_manager(phpbb_extension_manager $extension_manager)
{
$this->extension_manager = $extension_manager;
}
/** /**
* Loads all migrations and their application state from the database. * Loads all migrations and their application state from the database.
* *
@ -99,18 +112,26 @@ class phpbb_db_migrator
{ {
$this->migration_state = array(); $this->migration_state = array();
// prevent errors in case the table does not exist yet
$this->db->sql_return_on_error(true);
$sql = "SELECT * $sql = "SELECT *
FROM " . $this->migrations_table; FROM " . $this->migrations_table;
$result = $this->db->sql_query($sql); $result = $this->db->sql_query($sql);
while ($migration = $this->db->sql_fetchrow($result)) if (!$this->db->sql_error_triggered)
{ {
$this->migration_state[$migration['migration_name']] = $migration; while ($migration = $this->db->sql_fetchrow($result))
{
$this->migration_state[$migration['migration_name']] = $migration;
$this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']); $this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']);
}
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->db->sql_return_on_error(false);
} }
/** /**
@ -172,55 +193,32 @@ class phpbb_db_migrator
* If FALSE, we will not check. You SHOULD check at least once * If FALSE, we will not check. You SHOULD check at least once
* to prevent errors (if including multiple directories, check * to prevent errors (if including multiple directories, check
* with the last call to prevent throwing errors unnecessarily). * with the last call to prevent throwing errors unnecessarily).
* @param bool $recursive Set to true to also load data files from subdirectories
* @return array Array of migration names * @return array Array of migration names
*/ */
public function load_migrations($path, $check_fulfillable = true, $recursive = true) public function load_migrations($path, $check_fulfillable = true)
{ {
if (!is_dir($path)) if (!is_dir($path))
{ {
throw new phpbb_db_migration_exception('DIRECTORY INVALID', $path); throw new phpbb_db_migration_exception('DIRECTORY INVALID', $path);
} }
$handle = opendir($path); $migrations = array();
while (($file = readdir($handle)) !== false)
$finder = $this->extension_manager->get_finder();
$files = $finder
->extension_directory("/")
->find_from_paths(array('/' => $path));
foreach ($files as $file)
{ {
if ($file == '.' || $file == '..') $migrations[$file['path'] . $file['filename']] = '';
}
$migrations = $finder->get_classes_from_files($migrations);
foreach ($migrations as $migration)
{
if (!in_array($migration, $this->migrations))
{ {
continue; $this->migrations[] = $migration;
}
// Recursion through subdirectories
if (is_dir($path . $file) && $recursive)
{
$this->load_migrations($path . $file . '/', $check_fulfillable, $recursive);
}
if (strpos($file, '_') !== 0 && strrpos($file, '.' . $this->php_ext) === (strlen($file) - strlen($this->php_ext) - 1))
{
// We try to find what class existed by comparing the classes declared before and after including the file.
$declared_classes = get_declared_classes();
include ($path . $file);
$added_classes = array_diff(get_declared_classes(), $declared_classes);
if (
// If two classes have been added and phpbb_db_migration is one of them, we've only added one real migration
!(sizeof($added_classes) == 2 && in_array('phpbb_db_migration', $added_classes)) &&
// Otherwise there should only be one class added
sizeof($added_classes) != 1
)
{
throw new phpbb_db_migration_exception('MIGRATION DATA FILE INVALID', $path . $file);
}
$name = array_pop($added_classes);
if (!in_array($name, $this->migrations))
{
$this->migrations[] = $name;
}
} }
} }
@ -228,9 +226,10 @@ class phpbb_db_migrator
{ {
foreach ($this->migrations as $name) foreach ($this->migrations as $name)
{ {
if ($this->unfulfillable($name)) $unfulfillable = $this->unfulfillable($name);
if ($unfulfillable !== false)
{ {
throw new phpbb_db_migration_exception('MIGRATION NOT FULFILLABLE', $name); throw new phpbb_db_migration_exception('MIGRATION_NOT_FULFILLABLE', $name, $unfulfillable);
} }
} }
} }
@ -307,23 +306,22 @@ class phpbb_db_migrator
'class' => $migration, 'class' => $migration,
); );
if ($migration->effectively_installed()) if (!isset($this->migration_state[$name]))
{ {
$state = array( if ($migration->effectively_installed())
'migration_depends_on' => $migration->depends_on(), {
'migration_schema_done' => true, $state = array(
'migration_data_done' => true, 'migration_depends_on' => $migration->depends_on(),
'migration_data_state' => '', 'migration_schema_done' => true,
'migration_start_time' => 0, 'migration_data_done' => true,
'migration_end_time' => 0, 'migration_data_state' => '',
); 'migration_start_time' => 0,
} 'migration_end_time' => 0,
else );
{ }
if (!isset($this->migration_state[$name])) else
{ {
$state['migration_start_time'] = time(); $state['migration_start_time'] = time();
$this->insert_migration($name, $state);
} }
} }
@ -352,14 +350,7 @@ class phpbb_db_migrator
} }
} }
$insert = $state; $this->insert_migration($name, $state);
$insert['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'UPDATE ' . $this->migrations_table . '
SET ' . $this->db->sql_build_array('UPDATE', $insert) . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$this->migration_state[$name] = $state;
return true; return true;
} }
@ -425,20 +416,13 @@ class phpbb_db_migrator
} }
else else
{ {
$result = $this->process_data_step($migration->revert_data(), $state['migration_data_state'], false); $result = $this->process_data_step($migration->revert_data(), '', false);
$state['migration_data_state'] = ($result === true) ? '' : $result; $state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true) ? false : true; $state['migration_data_done'] = ($result === true) ? false : true;
} }
$insert = $state; $this->insert_migration($name, $state);
$insert['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'UPDATE ' . $this->migrations_table . '
SET ' . $this->db->sql_build_array('UPDATE', $insert) . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$this->migration_state[$name] = $state;
} }
else else
{ {
@ -651,7 +635,7 @@ class phpbb_db_migrator
} }
/** /**
* Insert migration row into the database * Insert/Update migration row into the database
* *
* @param string $name Name of the migration * @param string $name Name of the migration
* @param array $state * @param array $state
@ -660,12 +644,22 @@ class phpbb_db_migrator
protected function insert_migration($name, $state) protected function insert_migration($name, $state)
{ {
$migration_row = $state; $migration_row = $state;
$migration_row['migration_name'] = $name;
$migration_row['migration_depends_on'] = serialize($state['migration_depends_on']); $migration_row['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'INSERT INTO ' . $this->migrations_table . ' if (isset($this->migration_state[$name]))
' . $this->db->sql_build_array('INSERT', $migration_row); {
$this->db->sql_query($sql); $sql = 'UPDATE ' . $this->migrations_table . '
SET ' . $this->db->sql_build_array('UPDATE', $migration_row) . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
}
else
{
$migration_row['migration_name'] = $name;
$sql = 'INSERT INTO ' . $this->migrations_table . '
' . $this->db->sql_build_array('INSERT', $migration_row);
$this->db->sql_query($sql);
}
$this->migration_state[$name] = $state; $this->migration_state[$name] = $state;
} }
@ -674,7 +668,7 @@ class phpbb_db_migrator
* Checks if a migration's dependencies can even theoretically be satisfied. * Checks if a migration's dependencies can even theoretically be satisfied.
* *
* @param string $name The class name of the migration * @param string $name The class name of the migration
* @return bool Whether the migration cannot be fulfilled * @return bool|string False if fulfillable, string of missing migration name if unfulfillable
*/ */
public function unfulfillable($name) public function unfulfillable($name)
{ {
@ -685,7 +679,7 @@ class phpbb_db_migrator
if (!class_exists($name)) if (!class_exists($name))
{ {
return true; return $name;
} }
$migration = $this->get_migration($name); $migration = $this->get_migration($name);
@ -693,9 +687,10 @@ class phpbb_db_migrator
foreach ($depends as $depend) foreach ($depends as $depend)
{ {
if ($this->unfulfillable($depend)) $unfulfillable = $this->unfulfillable($depend);
if ($unfulfillable !== false)
{ {
return true; return $unfulfillable;
} }
} }
@ -715,7 +710,7 @@ class phpbb_db_migrator
{ {
// skip unfulfillable migrations, but fulfillables mean we // skip unfulfillable migrations, but fulfillables mean we
// are not finished yet // are not finished yet
if ($this->unfulfillable($name)) if ($this->unfulfillable($name) !== false)
{ {
continue; continue;
} }

View file

@ -15,6 +15,8 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* A base class for extensions without custom enable/disable/purge code. * A base class for extensions without custom enable/disable/purge code.
* *
@ -22,6 +24,19 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_extension_base implements phpbb_extension_interface class phpbb_extension_base implements phpbb_extension_interface
{ {
/** @var ContainerInterface */
protected $container;
/**
* Constructor
*
* @param ContainerInterface $container Container object
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/** /**
* Single enable step that does nothing * Single enable step that does nothing
* *

View file

@ -247,15 +247,28 @@ class phpbb_extension_finder
* phpBB naming rules an incorrect class name will be returned. * phpBB naming rules an incorrect class name will be returned.
* *
* @param bool $cache Whether the result should be cached * @param bool $cache Whether the result should be cached
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @return array An array of found class names * @return array An array of found class names
*/ */
public function get_classes($cache = true) public function get_classes($cache = true, $use_all_available = false)
{ {
$this->query['extension_suffix'] .= $this->php_ext; $this->query['extension_suffix'] .= $this->php_ext;
$this->query['core_suffix'] .= $this->php_ext; $this->query['core_suffix'] .= $this->php_ext;
$files = $this->find($cache, false); $files = $this->find($cache, false, $use_all_available);
return $this->get_classes_from_files($files);
}
/**
* Get class names from a list of files
*
* @param array $files Array of files (from find())
* @return array Array of class names
*/
public function get_classes_from_files($files)
{
$classes = array(); $classes = array();
foreach ($files as $file => $ext_name) foreach ($files as $file => $ext_name)
{ {
@ -270,23 +283,27 @@ class phpbb_extension_finder
* Finds all directories matching the configured options * Finds all directories matching the configured options
* *
* @param bool $cache Whether the result should be cached * @param bool $cache Whether the result should be cached
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @param bool $extension_keys Whether the result should have extension name as array key * @param bool $extension_keys Whether the result should have extension name as array key
* @return array An array of paths to found directories * @return array An array of paths to found directories
*/ */
public function get_directories($cache = true, $extension_keys = false) public function get_directories($cache = true, $use_all_available = false, $extension_keys = false)
{ {
return $this->find_with_root_path($cache, true, $extension_keys); return $this->find_with_root_path($cache, true, $use_all_available, $extension_keys);
} }
/** /**
* Finds all files matching the configured options. * Finds all files matching the configured options.
* *
* @param bool $cache Whether the result should be cached * @param bool $cache Whether the result should be cached
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @return array An array of paths to found files * @return array An array of paths to found files
*/ */
public function get_files($cache = true) public function get_files($cache = true, $use_all_available = false)
{ {
return $this->find_with_root_path($cache, false); return $this->find_with_root_path($cache, false, $use_all_available);
} }
/** /**
@ -295,13 +312,15 @@ class phpbb_extension_finder
* @param bool $cache Whether the result should be cached * @param bool $cache Whether the result should be cached
* @param bool $is_dir Directories will be returned when true, only files * @param bool $is_dir Directories will be returned when true, only files
* otherwise * otherwise
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @param bool $extension_keys If true, result will be associative array * @param bool $extension_keys If true, result will be associative array
* with extension name as key * with extension name as key
* @return array An array of paths to found items * @return array An array of paths to found items
*/ */
protected function find_with_root_path($cache = true, $is_dir = false, $extension_keys = false) protected function find_with_root_path($cache = true, $is_dir = false, $use_all_available = false, $extension_keys = false)
{ {
$items = $this->find($cache, $is_dir); $items = $this->find($cache, $is_dir, $use_all_available);
$result = array(); $result = array();
foreach ($items as $item => $ext_name) foreach ($items as $item => $ext_name)
@ -325,12 +344,51 @@ class phpbb_extension_finder
* @param bool $cache Whether the result should be cached * @param bool $cache Whether the result should be cached
* @param bool $is_dir Directories will be returned when true, only files * @param bool $is_dir Directories will be returned when true, only files
* otherwise * otherwise
* @param bool $use_all_available Use all available instead of just all
* enabled extensions
* @return array An array of paths to found items * @return array An array of paths to found items
*/ */
public function find($cache = true, $is_dir = false) public function find($cache = true, $is_dir = false, $use_all_available = false)
{
if ($use_all_available)
{
$extensions = $this->extension_manager->all_available();
}
else
{
$extensions = $this->extension_manager->all_enabled();
}
if ($this->query['core_path'])
{
$extensions['/'] = $this->phpbb_root_path . $this->query['core_path'];
}
$files = array();
$file_list = $this->find_from_paths($extensions, $cache, $is_dir);
foreach ($file_list as $file)
{
$files[$file['named_path']] = $file['ext_name'];
}
return $files;
}
/**
* Finds all file system entries matching the configured options from
* an array of paths
*
* @param array $extensions Array of extensions (name => full relative path)
* @param bool $cache Whether the result should be cached
* @param bool $is_dir Directories will be returned when true, only files
* otherwise
* @return array An array of paths to found items
*/
public function find_from_paths($extensions, $cache = true, $is_dir = false)
{ {
$this->query['is_dir'] = $is_dir; $this->query['is_dir'] = $is_dir;
$query = md5(serialize($this->query)); $query = md5(serialize($this->query) . serialize($extensions));
if (!defined('DEBUG') && $cache && isset($this->cached_queries[$query])) if (!defined('DEBUG') && $cache && isset($this->cached_queries[$query]))
{ {
@ -339,13 +397,6 @@ class phpbb_extension_finder
$files = array(); $files = array();
$extensions = $this->extension_manager->all_enabled();
if ($this->query['core_path'])
{
$extensions['/'] = $this->phpbb_root_path . $this->query['core_path'];
}
foreach ($extensions as $name => $path) foreach ($extensions as $name => $path)
{ {
$ext_name = $name; $ext_name = $name;
@ -419,7 +470,12 @@ class phpbb_extension_finder
(!$prefix || substr($filename, 0, strlen($prefix)) === $prefix) && (!$prefix || substr($filename, 0, strlen($prefix)) === $prefix) &&
(!$directory || preg_match($directory_pattern, $relative_path))) (!$directory || preg_match($directory_pattern, $relative_path)))
{ {
$files[str_replace(DIRECTORY_SEPARATOR, '/', $location . $name . substr($relative_path, 1))] = $ext_name; $files[] = array(
'named_path' => str_replace(DIRECTORY_SEPARATOR, '/', $location . $name . substr($relative_path, 1)),
'ext_name' => $ext_name,
'path' => str_replace(array(DIRECTORY_SEPARATOR, $this->phpbb_root_path), array('/', ''), $file_info->getPath()) . '/',
'filename' => $filename,
);
} }
} }
} }

View file

@ -15,6 +15,8 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* The extension manager provides means to activate/deactivate extensions. * The extension manager provides means to activate/deactivate extensions.
* *
@ -22,8 +24,12 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_extension_manager class phpbb_extension_manager
{ {
/** @var ContainerInterface */
protected $container;
protected $db; protected $db;
protected $config; protected $config;
protected $migrator;
protected $cache; protected $cache;
protected $php_ext; protected $php_ext;
protected $extensions; protected $extensions;
@ -34,6 +40,7 @@ class phpbb_extension_manager
/** /**
* Creates a manager and loads information from database * Creates a manager and loads information from database
* *
* @param ContainerInterface $container A container
* @param phpbb_db_driver $db A database connection * @param phpbb_db_driver $db A database connection
* @param phpbb_config $config phpbb_config * @param phpbb_config $config phpbb_config
* @param string $extension_table The name of the table holding extensions * @param string $extension_table The name of the table holding extensions
@ -42,8 +49,9 @@ class phpbb_extension_manager
* @param phpbb_cache_driver_interface $cache A cache instance or null * @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext * @param string $cache_name The name of the cache variable, defaults to _ext
*/ */
public function __construct(phpbb_db_driver $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
{ {
$this->container = $container;
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->db = $db; $this->db = $db;
$this->config = $config; $this->config = $config;
@ -60,6 +68,14 @@ class phpbb_extension_manager
} }
} }
/**
* Set migrator (get around circular reference)
*/
public function set_migrator(phpbb_db_migrator $migrator)
{
$this->migrator = $migrator;
}
/** /**
* Loads all extension information from the database * Loads all extension information from the database
* *
@ -126,11 +142,11 @@ class phpbb_extension_manager
if (class_exists($extension_class_name)) if (class_exists($extension_class_name))
{ {
return new $extension_class_name; return new $extension_class_name($this->container);
} }
else else
{ {
return new phpbb_extension_base; return new phpbb_extension_base($this->container);
} }
} }
@ -166,6 +182,12 @@ class phpbb_extension_manager
$old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false; $old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false;
// Returns false if not completed
if (!$this->handle_migrations($name, 'enable'))
{
return true;
}
$extension = $this->get_extension($name); $extension = $this->get_extension($name);
$state = $extension->enable_step($old_state); $state = $extension->enable_step($old_state);
@ -317,6 +339,12 @@ class phpbb_extension_manager
$old_state = unserialize($this->extensions[$name]['ext_state']); $old_state = unserialize($this->extensions[$name]['ext_state']);
// Returns false if not completed
if (!$this->handle_migrations($name, 'purge'))
{
return true;
}
$extension = $this->get_extension($name); $extension = $this->get_extension($name);
$state = $extension->purge_step($old_state); $state = $extension->purge_step($old_state);
@ -490,4 +518,58 @@ class phpbb_extension_manager
{ {
return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder'); return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
} }
/**
* Handle installing/reverting migrations
*
* @param string $extension_name Name of the extension
* @param string $mode enable or purge
* @return bool True if completed, False if not completed
*/
protected function handle_migrations($extension_name, $mode)
{
$migrations_path = $this->phpbb_root_path . $this->get_extension_path($extension_name) . 'migrations/';
if (!file_exists($migrations_path) || !is_dir($migrations_path))
{
return true;
}
$migrations = $this->migrator->load_migrations($migrations_path);
// What is a safe limit of execution time? Half the max execution time should be safe.
$safe_time_limit = (ini_get('max_execution_time') / 2);
$start_time = time();
if ($mode == 'enable')
{
while (!$this->migrator->finished())
{
$this->migrator->update();
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
if ((time() - $start_time) >= $safe_time_limit)
{
return false;
}
}
}
else if ($mode == 'purge')
{
foreach ($migrations as $migration)
{
while ($this->migrator->migration_state($migration) !== false)
{
$this->migrator->revert($migration);
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
if ((time() - $start_time) >= $safe_time_limit)
{
return false;
}
}
}
}
return true;
}
} }

View file

@ -97,7 +97,18 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false, $
} }
/** /**
* Set config value. Creates missing config entry. * Sets a configuration option's value.
*
* Please note that this function does not update the is_dynamic value for
* an already existing config option.
*
* @param string $config_name The configuration option's name
* @param string $config_value New configuration value
* @param bool $is_dynamic Whether this variable should be cached (false) or
* if it changes too frequently (true) to be
* efficiently cached.
*
* @return null
* *
* @deprecated * @deprecated
*/ */
@ -119,7 +130,15 @@ function set_config($config_name, $config_value, $is_dynamic = false, phpbb_conf
} }
/** /**
* Set dynamic config value with arithmetic operation. * Increments an integer config value directly in the database.
*
* @param string $config_name The configuration option's name
* @param int $increment Amount to increment by
* @param bool $is_dynamic Whether this variable should be cached (false) or
* if it changes too frequently (true) to be
* efficiently cached.
*
* @return null
* *
* @deprecated * @deprecated
*/ */
@ -1328,7 +1347,7 @@ function phpbb_timezone_select($user, $default = '', $truncate = false)
function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0) function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0)
{ {
global $db, $user, $config; global $db, $user, $config;
global $request; global $request, $phpbb_container;
$post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time; $post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time;
@ -1336,6 +1355,20 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
{ {
if ($forum_id === false || !sizeof($forum_id)) if ($forum_id === false || !sizeof($forum_id))
{ {
// Mark all forums read (index page)
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Mark all topic notifications read for this user
$phpbb_notifications->mark_notifications_read(array(
'topic',
'quote',
'bookmark',
'post',
'approve_topic',
'approve_post',
), false, $user->data['user_id'], $post_time);
if ($config['load_db_lastread'] && $user->data['is_registered']) if ($config['load_db_lastread'] && $user->data['is_registered'])
{ {
// Mark all forums read (index page) // Mark all forums read (index page)
@ -1390,6 +1423,32 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$forum_id = array($forum_id); $forum_id = array($forum_id);
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->mark_notifications_read_by_parent(array(
'topic',
'approve_topic',
), $forum_id, $user->data['user_id'], $post_time);
// Mark all post/quote notifications read for this user in this forum
$topic_ids = array();
$sql = 'SELECT topic_id
FROM ' . TOPICS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $forum_id);
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$topic_ids[] = $row['topic_id'];
}
$db->sql_freeresult($result);
$phpbb_notifications->mark_notifications_read_by_parent(array(
'quote',
'bookmark',
'post',
'approve_post',
), $topic_ids, $user->data['user_id'], $post_time);
// Add 0 to forums array to mark global announcements correctly // Add 0 to forums array to mark global announcements correctly
// $forum_id[] = 0; // $forum_id[] = 0;
@ -1487,6 +1546,21 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
return; return;
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Mark post notifications read for this user in this topic
$phpbb_notifications->mark_notifications_read(array(
'topic',
'approve_topic',
), $topic_id, $user->data['user_id'], $post_time);
$phpbb_notifications->mark_notifications_read_by_parent(array(
'quote',
'bookmark',
'post',
'approve_post',
), $topic_id, $user->data['user_id'], $post_time);
if ($config['load_db_lastread'] && $user->data['is_registered']) if ($config['load_db_lastread'] && $user->data['is_registered'])
{ {
$sql = 'UPDATE ' . TOPICS_TRACK_TABLE . " $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . "
@ -4994,7 +5068,7 @@ function phpbb_build_hidden_fields_for_query_params($request, $exclude = null)
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{ {
global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
global $phpbb_dispatcher, $request; global $phpbb_dispatcher, $request, $phpbb_container;
if (defined('HEADER_INC')) if (defined('HEADER_INC'))
{ {
@ -5183,8 +5257,26 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
$timezone_name = $user->lang['timezones'][$timezone_name]; $timezone_name = $user->lang['timezones'][$timezone_name];
} }
// Output the notifications
$notifications = false;
if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE)
{
$phpbb_notifications = $phpbb_container->get('notification_manager');
$notifications = $phpbb_notifications->load_notifications(array(
'all_unread' => true,
'limit' => 5,
));
foreach ($notifications['notifications'] as $notification)
{
$template->assign_block_vars('notifications', $notification->prepare_for_display());
}
}
$hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f')); $hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f'));
// The following assigns all _common_ variables that may be used at any point in a template. // The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array( $template->assign_vars(array(
'SITENAME' => $config['sitename'], 'SITENAME' => $config['sitename'],
@ -5201,6 +5293,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread, 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox, 'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox,
'UNREAD_NOTIFICATIONS_COUNT' => ($notifications !== false) ? $notifications['unread_count'] : '',
'NOTIFICATIONS_COUNT' => ($notifications !== false) ? $user->lang('NOTIFICATIONS_COUNT', $notifications['unread_count']) : '',
'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'),
'U_NOTIFICATION_SETTINGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&amp;mode=notification_options'),
'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'],
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
'S_USER_NEW' => $user->data['user_new'], 'S_USER_NEW' => $user->data['user_new'],

View file

@ -443,6 +443,13 @@ function validate_config_vars($config_vars, &$cfg_array, &$error)
} }
break; break;
case 'email':
if (!preg_match('/^' . get_preg_expression('email') . '$/i', $cfg_array[$config_name]))
{
$error[] = $user->lang['EMAIL_INVALID_EMAIL'];
}
break;
// Absolute path // Absolute path
case 'script_path': case 'script_path':
if (!$cfg_array[$config_name]) if (!$cfg_array[$config_name])

View file

@ -618,7 +618,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true)
*/ */
function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true) function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true)
{ {
global $db, $config; global $db, $config, $phpbb_container;
$approved_topics = 0; $approved_topics = 0;
$forum_ids = $topic_ids = array(); $forum_ids = $topic_ids = array();
@ -715,6 +715,14 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
set_config_count('num_topics', $approved_topics * (-1), true); set_config_count('num_topics', $approved_topics * (-1), true);
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications(array(
'topic',
'approve_topic',
'topic_in_queue',
), $topic_ids);
return $return; return $return;
} }
@ -723,7 +731,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
*/ */
function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true) function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true)
{ {
global $db, $config, $phpbb_root_path, $phpEx, $auth, $user; global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container;
if ($where_type === 'range') if ($where_type === 'range')
{ {
@ -892,6 +900,16 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false); delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false);
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications(array(
'quote',
'bookmark',
'post',
'approve_post',
'post_in_queue',
), $post_ids);
return sizeof($post_ids); return sizeof($post_ids);
} }

View file

@ -392,6 +392,28 @@ class messenger
} }
} }
/**
* Generates a valid message id to be used in emails
*
* @return string message id
*/
function generate_message_id()
{
global $config;
$domain = 'phpbb.generated';
if ($config['server_name'])
{
$domain = $config['server_name'];
}
else if (!empty($_SERVER['SERVER_NAME']))
{
$domain = $_SERVER['SERVER_NAME'];
}
return md5(unique_id(time())) . '@' . $domain;
}
/** /**
* Return email header * Return email header
*/ */
@ -418,7 +440,7 @@ class messenger
$headers[] = 'Return-Path: <' . $config['board_email'] . '>'; $headers[] = 'Return-Path: <' . $config['board_email'] . '>';
$headers[] = 'Sender: <' . $config['board_email'] . '>'; $headers[] = 'Sender: <' . $config['board_email'] . '>';
$headers[] = 'MIME-Version: 1.0'; $headers[] = 'MIME-Version: 1.0';
$headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . $config['server_name'] . '>'; $headers[] = 'Message-ID: <' . $this->generate_message_id() . '>';
$headers[] = 'Date: ' . date('r', time()); $headers[] = 'Date: ' . date('r', time());
$headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed
$headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit

View file

@ -1175,238 +1175,6 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
return true; return true;
} }
/**
* User Notification
*/
function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id, $author_name = '')
{
global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
$topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false;
$forum_notification = ($mode == 'post') ? true : false;
if (!$topic_notification && !$forum_notification)
{
trigger_error('NO_MODE');
}
if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify']))
{
return;
}
$topic_title = ($topic_notification) ? $topic_title : $subject;
$topic_title = censor_text($topic_title);
// Exclude guests, current user and banned users from notifications
if (!function_exists('phpbb_get_banned_user_ids'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
$sql_ignore_users = phpbb_get_banned_user_ids();
$sql_ignore_users[ANONYMOUS] = ANONYMOUS;
$sql_ignore_users[$user->data['user_id']] = $user->data['user_id'];
$notify_rows = array();
// -- get forum_userids || topic_userids
$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u
WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . '
AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . '
AND w.notify_status = ' . NOTIFY_YES . '
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
AND u.user_id = w.user_id';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$notify_user_id = (int) $row['user_id'];
$notify_rows[$notify_user_id] = array(
'user_id' => $notify_user_id,
'username' => $row['username'],
'user_email' => $row['user_email'],
'user_jabber' => $row['user_jabber'],
'user_lang' => $row['user_lang'],
'notify_type' => ($topic_notification) ? 'topic' : 'forum',
'template' => ($topic_notification) ? 'topic_notify' : 'newtopic_notify',
'method' => $row['user_notify_type'],
'allowed' => false
);
// Add users who have been already notified to ignore list
$sql_ignore_users[$notify_user_id] = $notify_user_id;
}
$db->sql_freeresult($result);
// forum notification is sent to those not already receiving topic notifications
if ($topic_notification)
{
$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u
WHERE fw.forum_id = $forum_id
AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . '
AND fw.notify_status = ' . NOTIFY_YES . '
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
AND u.user_id = fw.user_id';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$notify_user_id = (int) $row['user_id'];
$notify_rows[$notify_user_id] = array(
'user_id' => $notify_user_id,
'username' => $row['username'],
'user_email' => $row['user_email'],
'user_jabber' => $row['user_jabber'],
'user_lang' => $row['user_lang'],
'notify_type' => 'forum',
'template' => 'forum_notify',
'method' => $row['user_notify_type'],
'allowed' => false
);
}
$db->sql_freeresult($result);
}
if (!sizeof($notify_rows))
{
return;
}
// Make sure users are allowed to read the forum
foreach ($auth->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary)
{
foreach ($forum_ary as $auth_option => $user_ary)
{
foreach ($user_ary as $user_id)
{
$notify_rows[$user_id]['allowed'] = true;
}
}
}
// Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;)
$msg_users = $delete_ids = $update_notification = array();
foreach ($notify_rows as $user_id => $row)
{
if (!$row['allowed'] || !trim($row['user_email']))
{
$delete_ids[$row['notify_type']][] = $row['user_id'];
}
else
{
$msg_users[] = $row;
$update_notification[$row['notify_type']][] = $row['user_id'];
/*
* We also update the forums watch table for this user when we are
* sending out a topic notification to prevent sending out another
* notification in case this user is also subscribed to the forum
* this topic was posted in.
* Since an UPDATE query is used, this has no effect on users only
* subscribed to the topic (i.e. no row is created) and should not
* be a performance issue.
*/
if ($row['notify_type'] === 'topic')
{
$update_notification['forum'][] = $row['user_id'];
}
}
}
unset($notify_rows);
// Now, we are able to really send out notifications
if (sizeof($msg_users))
{
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
$msg_list_ary = array();
foreach ($msg_users as $row)
{
$pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]);
$msg_list_ary[$row['template']][$pos]['method'] = $row['method'];
$msg_list_ary[$row['template']][$pos]['email'] = $row['user_email'];
$msg_list_ary[$row['template']][$pos]['jabber'] = $row['user_jabber'];
$msg_list_ary[$row['template']][$pos]['name'] = $row['username'];
$msg_list_ary[$row['template']][$pos]['lang'] = $row['user_lang'];
$msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id'];
}
unset($msg_users);
foreach ($msg_list_ary as $email_template => $email_list)
{
foreach ($email_list as $addr)
{
$messenger->template($email_template, $addr['lang']);
$messenger->to($addr['email'], $addr['name']);
$messenger->im($addr['jabber'], $addr['name']);
$messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($addr['name']),
'TOPIC_TITLE' => htmlspecialchars_decode($topic_title),
'FORUM_NAME' => htmlspecialchars_decode($forum_name),
'AUTHOR_NAME' => htmlspecialchars_decode($author_name),
'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id",
'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id",
'U_NEWEST_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id",
'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic",
'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum",
));
$messenger->send($addr['method']);
}
}
unset($msg_list_ary);
$messenger->save_queue();
}
// Handle the DB updates
$db->sql_transaction('begin');
if (!empty($update_notification['topic']))
{
$sql = 'UPDATE ' . TOPICS_WATCH_TABLE . '
SET notify_status = ' . NOTIFY_NO . "
WHERE topic_id = $topic_id
AND " . $db->sql_in_set('user_id', $update_notification['topic']);
$db->sql_query($sql);
}
if (!empty($update_notification['forum']))
{
$sql = 'UPDATE ' . FORUMS_WATCH_TABLE . '
SET notify_status = ' . NOTIFY_NO . "
WHERE forum_id = $forum_id
AND " . $db->sql_in_set('user_id', $update_notification['forum']);
$db->sql_query($sql);
}
// Now delete the user_ids not authorised to receive notifications on this topic/forum
if (!empty($delete_ids['topic']))
{
$sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . "
WHERE topic_id = $topic_id
AND " . $db->sql_in_set('user_id', $delete_ids['topic']);
$db->sql_query($sql);
}
if (!empty($delete_ids['forum']))
{
$sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . "
WHERE forum_id = $forum_id
AND " . $db->sql_in_set('user_id', $delete_ids['forum']);
$db->sql_query($sql);
}
$db->sql_transaction('commit');
}
// //
// Post handling functions // Post handling functions
// //
@ -1642,7 +1410,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)
*/ */
function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
{ {
global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path; global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container;
// We do not handle erasing posts here // We do not handle erasing posts here
if ($mode == 'delete') if ($mode == 'delete')
@ -2454,10 +2222,76 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
} }
// Send Notifications // Send Notifications
if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) $notification_data = array_merge($data, array(
'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject,
'post_username' => $username,
'poster_id' => $poster_id,
'post_text' => $data['message'],
'post_time' => $current_time,
'post_subject' => $subject,
));
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($post_approval)
{ {
$username = ($username) ? $username : $user->data['username']; switch ($mode)
user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id'], $username); {
case 'post':
$phpbb_notifications->add_notifications(array(
'quote',
'topic',
), $notification_data);
break;
case 'reply':
case 'quote':
$phpbb_notifications->add_notifications(array(
'quote',
'bookmark',
'post',
), $notification_data);
break;
case 'edit_topic':
case 'edit_first_post':
case 'edit':
case 'edit_last_post':
$phpbb_notifications->update_notifications(array(
'quote',
'bookmark',
'topic',
'post',
), $notification_data);
break;
}
}
else
{
switch ($mode)
{
case 'post':
$phpbb_notifications->add_notifications('topic_in_queue', $notification_data);
break;
case 'reply':
case 'quote':
$phpbb_notifications->add_notifications('post_in_queue', $notification_data);
break;
case 'edit_topic':
case 'edit_first_post':
case 'edit':
case 'edit_last_post':
$phpbb_notifications->delete_notifications('topic', $data['topic_id']);
$phpbb_notifications->delete_notifications(array(
'quote',
'bookmark',
'post',
), $data['post_id']);
break;
}
} }
$params = $add_anchor = ''; $params = $add_anchor = '';

View file

@ -876,7 +876,11 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)
return; return;
} }
global $db, $user; global $db, $user, $phpbb_container;
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->mark_notifications_read('pm', $msg_id, $user_id);
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
SET pm_unread = 0 SET pm_unread = 0
@ -981,7 +985,7 @@ function handle_mark_actions($user_id, $mark_action)
*/ */
function delete_pm($user_id, $msg_ids, $folder_id) function delete_pm($user_id, $msg_ids, $folder_id)
{ {
global $db, $user, $phpbb_root_path, $phpEx; global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
$user_id = (int) $user_id; $user_id = (int) $user_id;
$folder_id = (int) $folder_id; $folder_id = (int) $folder_id;
@ -1093,6 +1097,10 @@ function delete_pm($user_id, $msg_ids, $folder_id)
$user->data['user_unread_privmsg'] -= $num_unread; $user->data['user_unread_privmsg'] -= $num_unread;
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications('pm', array_keys($delete_rows));
// Now we have to check which messages we can delete completely // Now we have to check which messages we can delete completely
$sql = 'SELECT msg_id $sql = 'SELECT msg_id
FROM ' . PRIVMSGS_TO_TABLE . ' FROM ' . PRIVMSGS_TO_TABLE . '
@ -1157,7 +1165,7 @@ function phpbb_delete_user_pms($user_id)
*/ */
function phpbb_delete_users_pms($user_ids) function phpbb_delete_users_pms($user_ids)
{ {
global $db, $user, $phpbb_root_path, $phpEx; global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
$user_id_sql = $db->sql_in_set('user_id', $user_ids); $user_id_sql = $db->sql_in_set('user_id', $user_ids);
$author_id_sql = $db->sql_in_set('author_id', $user_ids); $author_id_sql = $db->sql_in_set('author_id', $user_ids);
@ -1202,6 +1210,8 @@ function phpbb_delete_users_pms($user_ids)
$db->sql_transaction('begin'); $db->sql_transaction('begin');
$phpbb_notifications = $phpbb_container->get('notification_manager');
if (!empty($undelivered_msg)) if (!empty($undelivered_msg))
{ {
// A pm is delivered, if for any recipient the message was moved // A pm is delivered, if for any recipient the message was moved
@ -1270,6 +1280,8 @@ function phpbb_delete_users_pms($user_ids)
WHERE folder_id = ' . PRIVMSGS_NO_BOX . ' WHERE folder_id = ' . PRIVMSGS_NO_BOX . '
AND ' . $db->sql_in_set('msg_id', $delivered_msg); AND ' . $db->sql_in_set('msg_id', $delivered_msg);
$db->sql_query($sql); $db->sql_query($sql);
$phpbb_notifications->delete_notifications('pm', $delivered_msg);
} }
if (!empty($undelivered_msg)) if (!empty($undelivered_msg))
@ -1281,6 +1293,8 @@ function phpbb_delete_users_pms($user_ids)
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
$db->sql_query($sql); $db->sql_query($sql);
$phpbb_notifications->delete_notifications('pm', $undelivered_msg);
} }
} }
@ -1323,6 +1337,8 @@ function phpbb_delete_users_pms($user_ids)
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $delete_ids); WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
$db->sql_query($sql); $db->sql_query($sql);
$phpbb_notifications->delete_notifications('pm', $delete_ids);
} }
} }
@ -1559,7 +1575,7 @@ function get_folder_status($folder_id, $folder)
*/ */
function submit_pm($mode, $subject, &$data, $put_in_outbox = true) function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{ {
global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path; global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path, $phpbb_container;
// We do not handle erasing pms here // We do not handle erasing pms here
if ($mode == 'delete') if ($mode == 'delete')
@ -1859,97 +1875,25 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$db->sql_transaction('commit'); $db->sql_transaction('commit');
// Send Notifications // Send Notifications
if ($mode != 'edit') $pm_data = array_merge($data, array(
'message_subject' => $subject,
'recipients' => $recipients,
));
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($mode == 'edit')
{ {
pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']); $phpbb_notifications->update_notifications('pm', $pm_data);
}
else
{
$phpbb_notifications->add_notifications('pm', $pm_data);
} }
return $data['msg_id']; return $data['msg_id'];
} }
/**
* PM Notification
*/
function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id)
{
global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
$subject = censor_text($subject);
// Exclude guests, current user and banned users from notifications
unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
if (!sizeof($recipients))
{
return;
}
if (!function_exists('phpbb_get_banned_user_ids'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
$banned_users = phpbb_get_banned_user_ids(array_keys($recipients));
$recipients = array_diff(array_keys($recipients), $banned_users);
if (!sizeof($recipients))
{
return;
}
$sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $recipients);
$result = $db->sql_query($sql);
$msg_list_ary = array();
while ($row = $db->sql_fetchrow($result))
{
if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
{
$msg_list_ary[] = array(
'method' => $row['user_notify_type'],
'email' => $row['user_email'],
'jabber' => $row['user_jabber'],
'name' => $row['username'],
'lang' => $row['user_lang']
);
}
}
$db->sql_freeresult($result);
if (!sizeof($msg_list_ary))
{
return;
}
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
foreach ($msg_list_ary as $pos => $addr)
{
$messenger->template('privmsg_notify', $addr['lang']);
$messenger->to($addr['email'], $addr['name']);
$messenger->im($addr['jabber'], $addr['name']);
$messenger->assign_vars(array(
'SUBJECT' => htmlspecialchars_decode($subject),
'AUTHOR_NAME' => htmlspecialchars_decode($author),
'USERNAME' => htmlspecialchars_decode($addr['name']),
'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox",
'U_VIEW_MESSAGE' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id",
));
$messenger->send($addr['method']);
}
unset($msg_list_ary);
$messenger->save_queue();
unset($messenger);
}
/** /**
* Display Message History * Display Message History
*/ */

View file

@ -33,7 +33,7 @@ class mcp_pm_reports
function main($id, $mode) function main($id, $mode)
{ {
global $auth, $db, $user, $template, $cache; global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action; global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
@ -89,6 +89,10 @@ class mcp_pm_reports
trigger_error('NO_REPORT'); trigger_error('NO_REPORT');
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->mark_notifications_read_by_parent('report_pm', $report_id, $user->data['user_id']);
$pm_id = $report['pm_id']; $pm_id = $report['pm_id'];
$report_id = $report['report_id']; $report_id = $report['report_id'];

View file

@ -33,7 +33,7 @@ class mcp_queue
function main($id, $mode) function main($id, $mode)
{ {
global $auth, $db, $user, $template, $cache; global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action; global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
@ -78,12 +78,16 @@ class mcp_queue
$post_id = request_var('p', 0); $post_id = request_var('p', 0);
$topic_id = request_var('t', 0); $topic_id = request_var('t', 0);
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($topic_id) if ($topic_id)
{ {
$topic_info = get_topic_data(array($topic_id), 'm_approve'); $topic_info = get_topic_data(array($topic_id), 'm_approve');
if (isset($topic_info[$topic_id]['topic_first_post_id'])) if (isset($topic_info[$topic_id]['topic_first_post_id']))
{ {
$post_id = (int) $topic_info[$topic_id]['topic_first_post_id']; $post_id = (int) $topic_info[$topic_id]['topic_first_post_id'];
$phpbb_notifications->mark_notifications_read('topic_in_queue', $topic_id, $user->data['user_id']);
} }
else else
{ {
@ -91,6 +95,8 @@ class mcp_queue
} }
} }
$phpbb_notifications->mark_notifications_read('post_in_queue', $post_id, $user->data['user_id']);
$post_info = get_post_data(array($post_id), 'm_approve', true); $post_info = get_post_data(array($post_id), 'm_approve', true);
if (!sizeof($post_info)) if (!sizeof($post_info))
@ -451,7 +457,7 @@ function approve_post($post_id_list, $id, $mode)
{ {
global $db, $template, $user, $config; global $db, $template, $user, $config;
global $phpEx, $phpbb_root_path; global $phpEx, $phpbb_root_path;
global $request; global $request, $phpbb_container;
if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{ {
@ -597,54 +603,51 @@ function approve_post($post_id_list, $id, $mode)
sync('forum', 'forum_id', array_keys($forum_id_list), true, true); sync('forum', 'forum_id', array_keys($forum_id_list), true, true);
unset($topic_id_list, $forum_id_list); unset($topic_id_list, $forum_id_list);
$messenger = new messenger();
// Notify Poster?
if ($notify_poster)
{
foreach ($post_info as $post_id => $post_data)
{
if ($post_data['poster_id'] == ANONYMOUS)
{
continue;
}
$email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_approved' : 'post_approved';
$messenger->template($email_template, $post_data['user_lang']);
$messenger->to($post_data['user_email'], $post_data['username']);
$messenger->im($post_data['user_jabber'], $post_data['username']);
$messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($post_data['username']),
'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])),
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])),
'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&e=0",
'U_VIEW_POST' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&p=$post_id&e=$post_id")
);
$messenger->send($post_data['user_notify_type']);
}
}
$messenger->save_queue();
// Send out normal user notifications // Send out normal user notifications
$email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']); $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Handle notifications
foreach ($post_info as $post_id => $post_data) foreach ($post_info as $post_id => $post_data)
{ {
if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id'])
{ {
// Forum Notifications $phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']);
user_notification('post', $post_data['topic_title'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id);
$phpbb_notifications->add_notifications(array(
'quote',
'topic',
), $post_data);
$phpbb_notifications->mark_notifications_read('quote', $post_data['post_id'], $user->data['user_id']);
$phpbb_notifications->mark_notifications_read('topic', $post_data['topic_id'], $user->data['user_id']);
if ($notify_poster)
{
$phpbb_notifications->add_notifications('approve_topic', $post_data);
}
} }
else else
{ {
// Topic Notifications $phpbb_notifications->delete_notifications('post_in_queue', $post_id);
user_notification('reply', $post_data['post_subject'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id);
$phpbb_notifications->add_notifications(array(
'quote',
'bookmark',
'post',
), $post_data);
$phpbb_notifications->mark_notifications_read(array(
'quote',
'bookmark',
'post',
),$post_data['post_id'], $user->data['user_id']);
if ($notify_poster)
{
$phpbb_notifications->add_notifications('approve_post', $post_data);
}
} }
} }
@ -734,7 +737,7 @@ function disapprove_post($post_id_list, $id, $mode)
{ {
global $db, $template, $user, $config; global $db, $template, $user, $config;
global $phpEx, $phpbb_root_path; global $phpEx, $phpbb_root_path;
global $request; global $request, $phpbb_container;
if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{ {
@ -867,20 +870,29 @@ function disapprove_post($post_id_list, $id, $mode)
} }
} }
$messenger = new messenger(); $phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($post_info as $post_id => $post_data)
{
if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id'])
{
$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']);
}
else
{
$phpbb_notifications->delete_notifications('post_in_queue', $post_id);
}
}
// Notify Poster? // Notify Poster?
if ($notify_poster) if ($notify_poster)
{ {
$lang_reasons = array(); $lang_reasons = array();
// Handle notifications
foreach ($post_info as $post_id => $post_data) foreach ($post_info as $post_id => $post_data)
{ {
if ($post_data['poster_id'] == ANONYMOUS) $post_data['disapprove_reason'] = '';
{
continue;
}
if (isset($disapprove_reason_lang)) if (isset($disapprove_reason_lang))
{ {
// Okay we need to get the reason from the posters language // Okay we need to get the reason from the posters language
@ -906,33 +918,30 @@ function disapprove_post($post_id_list, $id, $mode)
} }
} }
$email_disapprove_reason = $lang_reasons[$post_data['user_lang']]; $post_data['disapprove_reason'] = $lang_reasons[$post_data['user_lang']];
$email_disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; $post_data['disapprove_reason'] .= ($reason) ? "\n\n" . $reason : '';
} }
$email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_disapproved' : 'post_disapproved'; if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id'])
{
$messenger->template($email_template, $post_data['user_lang']); if ($notify_poster)
{
$messenger->to($post_data['user_email'], $post_data['username']); $phpbb_notifications->add_notifications('disapprove_topic', $post_data);
$messenger->im($post_data['user_jabber'], $post_data['username']); }
}
$messenger->assign_vars(array( else
'USERNAME' => htmlspecialchars_decode($post_data['username']), {
'REASON' => htmlspecialchars_decode($email_disapprove_reason), if ($notify_poster)
'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), {
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title']))) $phpbb_notifications->add_notifications('disapprove_post', $post_data);
); }
}
$messenger->send($post_data['user_notify_type']);
} }
unset($lang_reasons); unset($lang_reasons);
} }
unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang); unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang);
$messenger->save_queue();
if ($num_disapproved_topics) if ($num_disapproved_topics)
{ {
$success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS'; $success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS';

View file

@ -33,7 +33,7 @@ class mcp_reports
function main($id, $mode) function main($id, $mode)
{ {
global $auth, $db, $user, $template, $cache; global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action; global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
@ -87,6 +87,10 @@ class mcp_reports
trigger_error('NO_REPORT'); trigger_error('NO_REPORT');
} }
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->mark_notifications_read('report_post', $post_id, $user->data['user_id']);
if (!$report_id && $report['report_closed']) if (!$report_id && $report['report_closed'])
{ {
trigger_error('REPORT_CLOSED'); trigger_error('REPORT_CLOSED');
@ -436,7 +440,7 @@ class mcp_reports
function close_report($report_id_list, $mode, $action, $pm = false) function close_report($report_id_list, $mode, $action, $pm = false)
{ {
global $db, $template, $user, $config, $auth; global $db, $template, $user, $config, $auth;
global $phpEx, $phpbb_root_path; global $phpEx, $phpbb_root_path, $phpbb_container;
$pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 '; $pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 ';
$id_column = ($pm) ? 'pm_id' : 'post_id'; $id_column = ($pm) ? 'pm_id' : 'post_id';
@ -622,11 +626,11 @@ function close_report($report_id_list, $mode, $action, $pm = false)
} }
} }
$messenger = new messenger();
// Notify reporters // Notify reporters
if (sizeof($notify_reporters)) if (sizeof($notify_reporters))
{ {
$phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($notify_reporters as $report_id => $reporter) foreach ($notify_reporters as $report_id => $reporter)
{ {
if ($reporter['user_id'] == ANONYMOUS) if ($reporter['user_id'] == ANONYMOUS)
@ -636,30 +640,25 @@ function close_report($report_id_list, $mode, $action, $pm = false)
$post_id = $reporter[$id_column]; $post_id = $reporter[$id_column];
$messenger->template((($pm) ? 'pm_report_' : 'report_') . $action . 'd', $reporter['user_lang']);
$messenger->to($reporter['user_email'], $reporter['username']);
$messenger->im($reporter['user_jabber'], $reporter['username']);
if ($pm) if ($pm)
{ {
$messenger->assign_vars(array( $phpbb_notifications->add_notifications('report_pm_closed', array_merge($post_info[$post_id], array(
'USERNAME' => htmlspecialchars_decode($reporter['username']), 'reporter' => $reporter['user_id'],
'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']), 'closer_id' => $user->data['user_id'],
'PM_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['message_subject'])), 'from_user_id' => $post_info[$post_id]['author_id'],
)); )));
$phpbb_notifications->delete_notifications('report_pm', $post_id);
} }
else else
{ {
$messenger->assign_vars(array( $phpbb_notifications->add_notifications('report_post_closed', array_merge($post_info[$post_id], array(
'USERNAME' => htmlspecialchars_decode($reporter['username']), 'reporter' => $reporter['user_id'],
'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']), 'closer_id' => $user->data['user_id'],
'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])), )));
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title'])))
);
}
$messenger->send($reporter['user_notify_type']); $phpbb_notifications->delete_notifications('report_post', $post_id);
}
} }
} }
@ -674,8 +673,6 @@ function close_report($report_id_list, $mode, $action, $pm = false)
unset($notify_reporters, $post_info, $reports); unset($notify_reporters, $post_info, $reports);
$messenger->save_queue();
$success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS'; $success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS';
} }
else else

View file

@ -0,0 +1,853 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Notifications service class
* @package notifications
*/
class phpbb_notification_manager
{
/** @var array */
protected $notification_types;
/** @var array */
protected $notification_methods;
/** @var ContainerBuilder */
protected $phpbb_container;
/** @var phpbb_user_loader */
protected $user_loader;
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_user */
protected $user;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/** @var string */
protected $notification_types_table;
/** @var string */
protected $notifications_table;
/** @var string */
protected $user_notifications_table;
/**
* Notification Constructor
*
* @param array $notification_types
* @param array $notification_methods
* @param ContainerBuilder $phpbb_container
* @param phpbb_user_loader $user_loader
* @param phpbb_db_driver $db
* @param phpbb_user $user
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $notification_types_table
* @param string $notifications_table
* @param string $user_notifications_table
* @return phpbb_notification_manager
*/
public function __construct($notification_types, $notification_methods, $phpbb_container, phpbb_user_loader $user_loader, phpbb_db_driver $db, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
$this->phpbb_container = $phpbb_container;
$this->user_loader = $user_loader;
$this->db = $db;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->notification_types_table = $notification_types_table;
$this->notifications_table = $notifications_table;
$this->user_notifications_table = $user_notifications_table;
}
/**
* Load the user's notifications
*
* @param array $options Optional options to control what notifications are loaded
* notification_id Notification id to load (or array of notification ids)
* user_id User id to load notifications for (Default: $user->data['user_id'])
* order_by Order by (Default: notification_time)
* order_dir Order direction (Default: DESC)
* limit Number of notifications to load (Default: 5)
* start Notifications offset (Default: 0)
* all_unread Load all unread notifications? If set to true, count_unread is set to true (Default: false)
* count_unread Count all unread notifications? (Default: false)
* count_total Count all notifications? (Default: false)
* @return array Array of information based on the request with keys:
* 'notifications' array of notification type objects
* 'unread_count' number of unread notifications the user has if count_unread is true in the options
* 'total_count' number of notifications the user has if count_total is true in the options
*/
public function load_notifications(array $options = array())
{
// Merge default options
$options = array_merge(array(
'notification_id' => false,
'user_id' => $this->user->data['user_id'],
'order_by' => 'notification_time',
'order_dir' => 'DESC',
'limit' => 0,
'start' => 0,
'all_unread' => false,
'count_unread' => false,
'count_total' => false,
), $options);
// If all_unread, count_unread must be true
$options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread'];
// Anonymous users and bots never receive notifications
if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE))
{
return array(
'notifications' => array(),
'unread_count' => 0,
'total_count' => 0,
);
}
$notifications = $user_ids = array();
$load_special = array();
$total_count = $unread_count = 0;
if ($options['count_unread'])
{
// Get the total number of unread notifications
$sql = 'SELECT COUNT(n.notification_id) AS unread_count
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
AND n.notification_read = 0
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
$unread_count = (int) $this->db->sql_fetchfield('unread_count', $result);
$this->db->sql_freeresult($result);
}
if ($options['count_total'])
{
// Get the total number of notifications
$sql = 'SELECT COUNT(n.notification_id) AS total_count
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
$total_count = (int) $this->db->sql_fetchfield('total_count', $result);
$this->db->sql_freeresult($result);
}
if (!$options['count_total'] || $total_count)
{
$rowset = array();
// Get the main notifications
$sql = 'SELECT n.*
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] .
(($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : ' AND n.notification_id = ' . (int) $options['notification_id']) : '') . '
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1
ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
$result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
while ($row = $this->db->sql_fetchrow($result))
{
$rowset[$row['notification_id']] = $row;
}
$this->db->sql_freeresult($result);
// Get all unread notifications
if ($unread_count && $options['all_unread'] && !empty($rowset))
{
$sql = 'SELECT n.*
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
AND n.notification_read = 0
AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . '
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1
ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
$result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
while ($row = $this->db->sql_fetchrow($result))
{
$rowset[$row['notification_id']] = $row;
}
$this->db->sql_freeresult($result);
}
foreach ($rowset as $row)
{
$notification = $this->get_item_type_class($row['item_type'], $row);
// Array of user_ids to query all at once
$user_ids = array_merge($user_ids, $notification->users_to_query());
// Some notification types also require querying additional tables themselves
if (!isset($load_special[$row['item_type']]))
{
$load_special[$row['item_type']] = array();
}
$load_special[$row['item_type']] = array_merge($load_special[$row['item_type']], $notification->get_load_special());
$notifications[$row['notification_id']] = $notification;
}
$this->user_loader->load_users($user_ids);
// Allow each type to load its own special items
foreach ($load_special as $item_type => $data)
{
$item_class = $this->get_item_type_class($item_type);
$item_class->load_special($data, $notifications);
}
}
return array(
'notifications' => $notifications,
'unread_count' => $unread_count,
'total_count' => $total_count,
);
}
/**
* Mark notifications read
*
* @param bool|string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
* @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
* @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
*/
public function mark_notifications_read($item_type, $item_id, $user_id, $time = false)
{
$time = ($time !== false) ? $time : time();
$sql = 'UPDATE ' . $this->notifications_table . "
SET notification_read = 1
WHERE notification_time <= " . (int) $time .
(($item_type !== false) ? ' AND ' . (is_array($item_type) ? $this->db->sql_in_set('item_type', $item_type) : " item_type = '" . $this->db->sql_escape($item_type) . "'") : '') .
(($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : '');
$this->db->sql_query($sql);
}
/**
* Mark notifications read from a parent identifier
*
* @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
* @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
*/
public function mark_notifications_read_by_parent($item_type, $item_parent_id, $user_id, $time = false)
{
if (is_array($item_type))
{
foreach ($item_type as $type)
{
$this->mark_notifications_read_by_parent($type, $item_parent_id, $user_id, $time);
}
return;
}
$time = ($time !== false) ? $time : time();
$sql = 'UPDATE ' . $this->notifications_table . "
SET notification_read = 1
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND notification_time <= " . (int) $time .
(($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id) : 'item_parent_id = ' . (int) $item_parent_id) : '') .
(($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '');
$this->db->sql_query($sql);
}
/**
* Mark notifications read
*
* @param int|array $notification_id Notification id or array of notification ids.
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
*/
public function mark_notifications_read_by_id($notification_id, $time = false)
{
$time = ($time !== false) ? $time : time();
$sql = 'UPDATE ' . $this->notifications_table . "
SET notification_read = 1
WHERE notification_time <= " . (int) $time . '
AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id);
$this->db->sql_query($sql);
}
/**
* Add a notification
*
* @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* Note: If you send an array of types, any user who could receive multiple notifications from this single item will only receive
* a single notification. If they MUST receive multiple notifications, call this function multiple times instead of sending an array
* @param array $data Data specific for this type that will be inserted
* @param array $options Optional options to control what notifications are loaded
* ignore_users array of data to specify which users should not receive certain types of notifications
* @return array Information about what users were notified and how they were notified
*/
public function add_notifications($item_type, $data, array $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
if (is_array($item_type))
{
$notified_users = array();
$temp_options = $options;
foreach ($item_type as $type)
{
$temp_options['ignore_users'] = $options['ignore_users'] + $notified_users;
$notified_users += $this->add_notifications($type, $data, $temp_options);
}
return $notified_users;
}
$item_id = $this->get_item_type_class($item_type)->get_item_id($data);
// find out which users want to receive this type of notification
$notify_users = $this->get_item_type_class($item_type)->find_users_for_notification($data, $options);
$this->add_notifications_for_users($item_type, $data, $notify_users);
return $notify_users;
}
/**
* Add a notification for specific users
*
* @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param array $data Data specific for this type that will be inserted
* @param array $notify_users User list to notify
*/
public function add_notifications_for_users($item_type, $data, $notify_users)
{
if (is_array($item_type))
{
foreach ($item_type as $type)
{
$this->add_notifications_for_users($type, $data, $notify_users);
}
return;
}
$sql = 'SELECT notification_type
FROM ' . $this->notification_types_table . "
WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
$result = $this->db->sql_query($sql);
if ($this->db->sql_fetchrow($result) === false)
{
// Does not exist in the database, must add the item type
$sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array(
'notification_type' => $item_type,
'notification_type_enabled' => 1,
));
$this->db->sql_query($sql);
}
$this->db->sql_freeresult($result);
$item_id = $this->get_item_type_class($item_type)->get_item_id($data);
$user_ids = array();
$notification_objects = $notification_methods = array();
$new_rows = array();
// Never send notifications to the anonymous user!
unset($notify_users[ANONYMOUS]);
// Make sure not to send new notifications to users who've already been notified about this item
// This may happen when an item was added, but now new users are able to see the item
$sql = 'SELECT n.user_id
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
WHERE n.item_type = '" . $this->db->sql_escape($item_type) . "'
AND n.item_id = " . (int) $item_id . '
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
unset($notify_users[$row['user_id']]);
}
$this->db->sql_freeresult($result);
if (!sizeof($notify_users))
{
return;
}
// Allow notifications to perform actions before creating the insert array (such as run a query to cache some data needed for all notifications)
$notification = $this->get_item_type_class($item_type);
$pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
unset($notification);
// Go through each user so we can insert a row in the DB and then notify them by their desired means
foreach ($notify_users as $user => $methods)
{
$notification = $this->get_item_type_class($item_type);
$notification->user_id = (int) $user;
// Store the creation array in our new rows that will be inserted later
$new_rows[] = $notification->create_insert_array($data, $pre_create_data);
// Users are needed to send notifications
$user_ids = array_merge($user_ids, $notification->users_to_query());
foreach ($methods as $method)
{
// setup the notification methods and add the notification to the queue
if ($method) // blank means we just insert it as a notification, but do not notify them by any other means
{
if (!isset($notification_methods[$method]))
{
$notification_methods[$method] = $this->get_method_class($method);
}
$notification_methods[$method]->add_to_queue($notification);
}
}
}
// insert into the db
$this->db->sql_multi_insert($this->notifications_table, $new_rows);
// We need to load all of the users to send notifications
$this->user_loader->load_users($user_ids);
// run the queue for each method to send notifications
foreach ($notification_methods as $method)
{
$method->notify();
}
}
/**
* Update a notification
*
* @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param array $data Data specific for this type that will be updated
*/
public function update_notifications($item_type, $data)
{
if (is_array($item_type))
{
foreach ($item_type as $type)
{
$this->update_notifications($type, $data);
}
return;
}
$notification = $this->get_item_type_class($item_type);
// Allow the notifications class to over-ride the update_notifications functionality
if (method_exists($notification, 'update_notifications'))
{
// Return False to over-ride the rest of the update
if ($notification->update_notifications($data) === false)
{
return;
}
}
$item_id = $notification->get_item_id($data);
$update_array = $notification->create_update_array($data);
$sql = 'UPDATE ' . $this->notifications_table . '
SET ' . $this->db->sql_build_array('UPDATE', $update_array) . "
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND item_id = " . (int) $item_id;
$this->db->sql_query($sql);
}
/**
* Delete a notification
*
* @param string|array $item_type Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
* @param int|array $item_id Identifier within the type (or array of ids)
* @param array $data Data specific for this type that will be updated
*/
public function delete_notifications($item_type, $item_id)
{
if (is_array($item_type))
{
foreach ($item_type as $type)
{
$this->delete_notifications($type, $item_id);
}
return;
}
$sql = 'DELETE FROM ' . $this->notifications_table . "
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND " . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id);
$this->db->sql_query($sql);
}
/**
* Get all of the subscription types
*
* @return array Array of item types
*/
public function get_subscription_types()
{
$subscription_types = array();
foreach ($this->notification_types as $type_name => $data)
{
$type = $this->get_item_type_class($type_name);
if ($type instanceof phpbb_notification_type_interface && $type->is_available())
{
$options = array_merge(array(
'id' => $type->get_type(),
'lang' => 'NOTIFICATION_TYPE_' . strtoupper($type->get_type()),
'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS',
), (($type::$notification_option !== false) ? $type::$notification_option : array()));
$subscription_types[$options['group']][$options['id']] = $options;
}
}
// Move Miscellaneous to the very last section
if (isset($subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']))
{
$miscellaneous = $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'];
unset($subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);
$subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'] = $miscellaneous;
}
return $subscription_types;
}
/**
* Get all of the subscription methods
*
* @return array Array of methods
*/
public function get_subscription_methods()
{
$subscription_methods = array();
foreach ($this->notification_methods as $method_name => $data)
{
$method = $this->get_method_class($method_name);
if ($method instanceof phpbb_notification_method_interface && $method->is_available())
{
$subscription_methods[$method_name] = array(
'id' => $method->get_type(),
'lang' => 'NOTIFICATION_METHOD_' . strtoupper($method->get_type()),
);
}
}
return $subscription_methods;
}
/**
* Get global subscriptions (item_id = 0)
*
* @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
*
* @return array Subscriptions
*/
public function get_global_subscriptions($user_id = false)
{
$user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
$subscriptions = array();
foreach ($this->get_subscription_types() as $group_name => $types)
{
foreach ($types as $id => $type)
{
$sql = 'SELECT method, notify
FROM ' . $this->user_notifications_table . '
WHERE user_id = ' . (int) $user_id . "
AND item_type = '" . $this->db->sql_escape($id) . "'
AND item_id = 0";
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
if (!$row)
{
// No rows at all, default to ''
$subscriptions[$id] = array('');
}
else
{
do
{
if (!$row['notify'])
{
continue;
}
if (!isset($subscriptions[$id]))
{
$subscriptions[$id] = array();
}
$subscriptions[$id][] = $row['method'];
}
while ($row = $this->db->sql_fetchrow($result));
}
$this->db->sql_freeresult($result);
}
}
return $subscriptions;
}
/**
* Add a subscription
*
* @param string $item_type Type identifier of the subscription
* @param int $item_id The id of the item
* @param string $method The method of the notification e.g. '', 'email', or 'jabber'
* @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
*/
public function add_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
{
if ($method !== '')
{
$this->add_subscription($item_type, $item_type, '', $user_id);
}
$user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
$sql = 'SELECT notify
FROM ' . $this->user_notifications_table . "
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND item_id = " . (int) $item_id . '
AND user_id = ' .(int) $user_id . "
AND method = '" . $this->db->sql_escape($method) . "'";
$this->db->sql_query($sql);
$current = $this->db->sql_fetchfield('notify');
$this->db->sql_freeresult();
if ($current === false)
{
$sql = 'INSERT INTO ' . $this->user_notifications_table . ' ' .
$this->db->sql_build_array('INSERT', array(
'item_type' => $item_type,
'item_id' => (int) $item_id,
'user_id' => (int) $user_id,
'method' => $method,
'notify' => 1,
));
$this->db->sql_query($sql);
}
else if (!$current)
{
$sql = 'UPDATE ' . $this->user_notifications_table . "
SET notify = 1
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND item_id = " . (int) $item_id . '
AND user_id = ' .(int) $user_id . "
AND method = '" . $this->db->sql_escape($method) . "'";
$this->db->sql_query($sql);
}
}
/**
* Delete a subscription
*
* @param string $item_type Type identifier of the subscription
* @param int $item_id The id of the item
* @param string $method The method of the notification e.g. '', 'email', or 'jabber'
* @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
*/
public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
{
$user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
// If no method, make sure that no other notification methods for this item are selected before deleting
if ($method === '')
{
$sql = 'SELECT COUNT(*) as num_notifications
FROM ' . $this->user_notifications_table . "
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND item_id = " . (int) $item_id . '
AND user_id = ' .(int) $user_id . "
AND method <> ''
AND notify = 1";
$this->db->sql_query($sql);
$num_notifications = $this->db->sql_fetchfield('num_notifications');
$this->db->sql_freeresult();
if ($num_notifications)
{
return;
}
}
$sql = 'UPDATE ' . $this->user_notifications_table . "
SET notify = 0
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
AND item_id = " . (int) $item_id . '
AND user_id = ' .(int) $user_id . "
AND method = '" . $this->db->sql_escape($method) . "'";
$this->db->sql_query($sql);
if (!$this->db->sql_affectedrows())
{
$sql = 'INSERT INTO ' . $this->user_notifications_table . ' ' .
$this->db->sql_build_array('INSERT', array(
'item_type' => $item_type,
'item_id' => (int) $item_id,
'user_id' => (int) $user_id,
'method' => $method,
'notify' => 0,
));
$this->db->sql_query($sql);
}
}
/**
* Disable all notifications of a certain type
*
* This should be called when an extension which has notification types
* is disabled so that all those notifications are hidden and do not
* cause errors
*
* @param string $item_type Type identifier of the subscription
*/
public function disable_notifications($item_type)
{
$sql = 'UPDATE ' . $this->notification_types_table . "
SET notification_type_enabled = 0
WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
$this->db->sql_query($sql);
}
/**
* Purge all notifications of a certain type
*
* This should be called when an extension which has notification types
* is purged so that all those notifications are removed
*
* @param string $item_type Type identifier of the subscription
*/
public function purge_notifications($item_type)
{
$sql = 'DELETE FROM ' . $this->notifications_table . "
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'";
$this->db->sql_query($sql);
$sql = 'DELETE FROM ' . $this->notification_types_table . "
WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
$this->db->sql_query($sql);
}
/**
* Enable all notifications of a certain type
*
* This should be called when an extension which has notification types
* that was disabled is re-enabled so that all those notifications that
* were hidden are shown again
*
* @param string $item_type Type identifier of the subscription
*/
public function enable_notifications($item_type)
{
$sql = 'UPDATE ' . $this->notification_types_table . "
SET notification_type_enabled = 1
WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
$this->db->sql_query($sql);
}
/**
* Delete all notifications older than a certain time
*
* @param int $timestamp Unix timestamp to delete all notifications that were created before
*/
public function prune_notifications($timestamp)
{
$sql = 'DELETE FROM ' . $this->notifications_table . '
WHERE notification_time < ' . (int) $timestamp;
$this->db->sql_query($sql);
}
/**
* Helper to get the notifications item type class and set it up
*/
public function get_item_type_class($item_type, $data = array())
{
$item_type = (strpos($item_type, 'notification.type.') === 0) ? $item_type : 'notification.type.' . $item_type;
$item = $this->load_object($item_type);
$item->set_initial_data($data);
return $item;
}
/**
* Helper to get the notifications method class and set it up
*/
public function get_method_class($method_name)
{
$method_name = (strpos($method_name, 'notification.method.') === 0) ? $method_name : 'notification.method.' . $method_name;
return $this->load_object($method_name);
}
/**
* Helper to load objects (notification types/methods)
*/
protected function load_object($object_name)
{
$object = $this->phpbb_container->get($object_name);
if (method_exists($object, 'set_notification_manager'))
{
$object->set_notification_manager($this);
}
return $object;
}
}

View file

@ -0,0 +1,116 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Base notifications method class
* @package notifications
*/
abstract class phpbb_notification_method_base implements phpbb_notification_method_interface
{
/** @var phpbb_notification_manager */
protected $notification_manager;
/** @var phpbb_user_loader */
protected $user_loader;
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_cache_service */
protected $cache;
/** @var phpbb_template */
protected $template;
/** @var phpbb_extension_manager */
protected $extension_manager;
/** @var phpbb_user */
protected $user;
/** @var phpbb_auth */
protected $auth;
/** @var phpbb_config */
protected $config;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/**
* Queue of messages to be sent
*
* @var array
*/
protected $queue = array();
/**
* Notification Method Base Constructor
*
* @param phpbb_user_loader $user_loader
* @param phpbb_db_driver $db
* @param phpbb_cache_driver_interface $cache
* @param phpbb_user $user
* @param phpbb_auth $auth
* @param phpbb_config $config
* @param string $phpbb_root_path
* @param string $php_ext
* @return phpbb_notification_method_base
*/
public function __construct(phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext)
{
$this->user_loader = $user_loader;
$this->db = $db;
$this->cache = $cache;
$this->user = $user;
$this->auth = $auth;
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
}
/**
* Set notification manager (required)
*
* @param phpbb_notification_manager $notification_manager
*/
public function set_notification_manager(phpbb_notification_manager $notification_manager)
{
$this->notification_manager = $notification_manager;
}
/**
* Add a notification to the queue
*
* @param phpbb_notification_type_interface $notification
*/
public function add_to_queue(phpbb_notification_type_interface $notification)
{
$this->queue[] = $notification;
}
/**
* Empty the queue
*/
protected function empty_queue()
{
$this->queue = array();
}
}

View file

@ -0,0 +1,129 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Email notification method class
* This class handles sending emails for notifications
*
* @package notifications
*/
class phpbb_notification_method_email extends phpbb_notification_method_base
{
/**
* Get notification method name
*
* @return string
*/
public function get_type()
{
return 'email';
}
/**
* Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
*
* @var mixed
*/
protected $notify_method = NOTIFY_EMAIL;
/**
* Base directory to prepend to the email template name
*
* @var string
*/
protected $email_template_base_dir = '';
/**
* Is this method available for the user?
* This is checked on the notifications options
*/
public function is_available()
{
// Email is always available
return true;
}
/**
* Parse the queue and notify the users
*/
public function notify()
{
if (!sizeof($this->queue))
{
return;
}
// Load all users we want to notify (we need their email address)
$user_ids = $users = array();
foreach ($this->queue as $notification)
{
$user_ids[] = $notification->user_id;
}
// We do not send emails to banned users
if (!function_exists('phpbb_get_banned_user_ids'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$banned_users = phpbb_get_banned_user_ids($user_ids);
// Load all the users we need
$this->user_loader->load_users($user_ids);
// Load the messenger
if (!class_exists('messenger'))
{
include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
}
$messenger = new messenger();
$board_url = generate_board_url();
// Time to go through the queue and send emails
foreach ($this->queue as $notification)
{
if ($notification->get_email_template() === false)
{
continue;
}
$user = $this->user_loader->get_user($notification->user_id);
if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users))
{
continue;
}
$messenger->template($this->email_template_base_dir . $notification->get_email_template(), $user['user_lang']);
$messenger->to($user['user_email'], $user['username']);
$messenger->assign_vars(array_merge(array(
'USERNAME' => $user['username'],
'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications',
), $notification->get_email_template_variables()));
$messenger->send($this->notify_method);
}
// Save the queue in the messenger class (has to be called or these emails could be lost?)
$messenger->save_queue();
// We're done, empty the queue
$this->empty_queue();
}
}

View file

@ -0,0 +1,48 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Base notifications method interface
* @package notifications
*/
interface phpbb_notification_method_interface
{
/**
* Get notification method name
*
* @return string
*/
public function get_type();
/**
* Is this method available for the user?
* This is checked on the notifications options
*/
public function is_available();
/**
* Add a notification to the queue
*
* @param phpbb_notification_type_interface $notification
*/
public function add_to_queue(phpbb_notification_type_interface $notification);
/**
* Parse the queue and notify the users
*/
public function notify();
}

View file

@ -0,0 +1,77 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Jabber notification method class
* This class handles sending Jabber messages for notifications
*
* @package notifications
*/
class phpbb_notification_method_jabber extends phpbb_notification_method_email
{
/**
* Get notification method name
*
* @return string
*/
public function get_type()
{
return 'jabber';
}
/**
* Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
*
* @var mixed
*/
protected $notify_method = NOTIFY_IM;
/**
* Base directory to prepend to the email template name
*
* @var string
*/
protected $email_template_base_dir = 'short/';
/**
* Is this method available for the user?
* This is checked on the notifications options
*/
public function is_available()
{
return ($this->global_available() && $this->user->data['jabber']);
}
/**
* Is this method available at all?
* This is checked before notifications are sent
*/
public function global_available()
{
return ($this->config['jab_enable'] && @extension_loaded('xml'));
}
public function notify()
{
if (!$this->global_available())
{
return;
}
return parent::notify();
}
}

View file

@ -0,0 +1,140 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post approved notifications class
* This class handles notifications for posts when they are approved (to their authors)
*
* @package notifications
*/
class phpbb_notification_type_approve_post extends phpbb_notification_type_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'approve_post';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_POST_APPROVED';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return !$this->auth->acl_get('m_approve');
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$users = array();
$users[$post['poster_id']] = array('');
$auth_read = $this->auth->acl_get_list(array_keys($users), 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
return $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], array_merge($options, array(
'item_type' => self::$notification_option['id'],
)));
}
/**
* Pre create insert array function
* This allows you to perform certain actions, like run a query
* and load data, before create_insert_array() is run. The data
* returned from this function will be sent to create_insert_array().
*
* @param array $post Post data from submit_post
* @param array $notify_users Notify users list
* Formated from find_users_for_notification()
* @return array Whatever you want to send to create_insert_array().
*/
public function pre_create_insert_array($post, $notify_users)
{
// In the parent class, this is used to check if the post is already
// read by a user and marks the notification read if it was marked read.
// Returning an empty array in effect, forces it to be marked as unread
// (and also saves a query)
return array();
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('post_subject', $post['post_subject']);
$data = parent::create_insert_array($post, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'post_approved';
}
}

View file

@ -0,0 +1,138 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Topic approved notifications class
* This class handles notifications for topics when they are approved (for authors)
*
* @package notifications
*/
class phpbb_notification_type_approve_topic extends phpbb_notification_type_topic
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'approve_topic';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_TOPIC_APPROVED';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return !$this->auth->acl_get('m_approve');
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$users = array();
$users[$post['poster_id']] = array('');
$auth_read = $this->auth->acl_get_list(array_keys($users), 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
return $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], array_merge($options, array(
'item_type' => self::$notification_option['id'],
)));
}
/**
* Pre create insert array function
* This allows you to perform certain actions, like run a query
* and load data, before create_insert_array() is run. The data
* returned from this function will be sent to create_insert_array().
*
* @param array $post Post data from submit_post
* @param array $notify_users Notify users list
* Formated from find_users_for_notification()
* @return array Whatever you want to send to create_insert_array().
*/
public function pre_create_insert_array($post, $notify_users)
{
// In the parent class, this is used to check if the post is already
// read by a user and marks the notification read if it was marked read.
// Returning an empty array in effect, forces it to be marked as unread
// (and also saves a query)
return array();
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$data = parent::create_insert_array($post, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'topic_approved';
}
}

View file

@ -0,0 +1,479 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Base notifications class
* @package notifications
*/
abstract class phpbb_notification_type_base implements phpbb_notification_type_interface
{
/** @var phpbb_notification_manager */
protected $notification_manager;
/** @var phpbb_user_loader */
protected $user_loader;
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_cache_service */
protected $cache;
/** @var phpbb_template */
protected $template;
/** @var phpbb_user */
protected $user;
/** @var phpbb_auth */
protected $auth;
/** @var phpbb_config */
protected $config;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/** @var string */
protected $notification_types_table;
/** @var string */
protected $notifications_table;
/** @var string */
protected $user_notifications_table;
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use its default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = false;
/**
* Indentification data
* item_type - Type of the item (translates to the notification type)
* item_id - ID of the item (e.g. post_id, msg_id)
* item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
* user_id
* notification_read
* notification_time
* notification_data (special serialized field that each notification type can use to store stuff)
*
* @var array $data Notification row from the database
* This must be private, all interaction should use __get(), __set(), get_data(), set_data()
*/
private $data = array();
/**
* Notification Type Base Constructor
*
* @param phpbb_user_loader $user_loader
* @param phpbb_db_driver $db
* @param phpbb_cache_driver_interface $cache
* @param phpbb_user $user
* @param phpbb_auth $auth
* @param phpbb_config $config
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $notification_types_table
* @param string $notifications_table
* @param string $user_notifications_table
* @return phpbb_notification_type_base
*/
public function __construct(phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->user_loader = $user_loader;
$this->db = $db;
$this->cache = $cache;
$this->user = $user;
$this->auth = $auth;
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->notification_types_table = $notification_types_table;
$this->notifications_table = $notifications_table;
$this->user_notifications_table = $user_notifications_table;
}
/**
* Set notification manager (required)
*
* @param phpbb_notification_manager $notification_manager
*/
public function set_notification_manager(phpbb_notification_manager $notification_manager)
{
$this->notification_manager = $notification_manager;
}
/**
* Set initial data from the database
*
* @param array $data Row directly from the database
*/
public function set_initial_data($data = array())
{
// The row from the database (unless this is a new notification we're going to add)
$this->data = $data;
$this->data['notification_data'] = (isset($this->data['notification_data'])) ? unserialize($this->data['notification_data']) : array();
}
/**
* Magic method to get data from this notification
*
* @param mixed $name
* @return mixed
*/
public function __get($name)
{
return (!isset($this->data[$name])) ? null : $this->data[$name];
}
/**
* Magic method to set data on this notification
*
* @param mixed $name
* @return null
*/
public function __set($name, $value)
{
$this->data[$name] = $value;
}
/**
* Magic method to get a string of this notification
*
* Primarily for testing
*
* @param string $name
* @return mixed
*/
public function __toString()
{
return (!empty($this->data)) ? var_export($this->data, true) : $this->get_type();
}
/**
* Get special data (only important for the classes that extend this)
*
* @param string $name Name of the variable to get
* @return mixed
*/
protected function get_data($name)
{
return ($name === false) ? $this->data['notification_data'] : ((isset($this->data['notification_data'][$name])) ? $this->data['notification_data'][$name] : null);
}
/**
* Set special data (only important for the classes that extend this)
*
* @param string $name Name of the variable to set
* @param mixed $value Value to set to the variable
* @return mixed
*/
protected function set_data($name, $value)
{
$this->data['notification_data'][$name] = $value;
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $type_data Data unique to this notification type
* @param array $pre_create_data Data from pre_create_insert_array()
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($type_data, $pre_create_data = array())
{
// Defaults
$this->data = array_merge(array(
'item_id' => static::get_item_id($type_data),
'item_type' => $this->get_type(),
'item_parent_id' => static::get_item_parent_id($type_data),
'notification_time' => time(),
'notification_read' => false,
'notification_data' => array(),
), $this->data);
$data = $this->data;
$data['notification_data'] = serialize($data['notification_data']);
return $data;
}
/**
* Function for preparing the data for update in an SQL query
* (The service handles insertion)
*
* @param array $type_data Data unique to this notification type
* @return array Array of data ready to be updated in the database
*/
public function create_update_array($type_data)
{
$data = $this->create_insert_array($type_data);
// Unset data unique to each row
unset(
$data['notification_time'], // Also unsetting time, since it always tries to change the time to current (if you actually need to change the time, over-ride this function)
$data['notification_id'],
$data['notification_read'],
$data['user_id']
);
return $data;
}
/**
* Mark this item read
*
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string|null If $return is False, nothing will be returned, else the sql code to update this item
*/
public function mark_read($return = false)
{
return $this->mark(false, $return);
}
/**
* Mark this item unread
*
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string|null If $return is False, nothing will be returned, else the sql code to update this item
*/
public function mark_unread($return = false)
{
return $this->mark(true, $return);
}
/**
* Prepare to output the notification to the template
*
* @return array Template variables
*/
public function prepare_for_display()
{
if ($this->get_url())
{
$u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id);
}
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));
}
return array(
'NOTIFICATION_ID' => $this->notification_id,
'AVATAR' => $this->get_avatar(),
'FORMATTED_TITLE' => $this->get_title(),
'URL' => $this->get_url(),
'TIME' => $this->user->format_date($this->notification_time),
'UNREAD' => !$this->notification_read,
'U_MARK_READ' => (!$this->notification_read) ? $u_mark_read : '',
);
}
/**
* -------------- Fall back functions -------------------
*/
/**
* URL to unsubscribe to this notification (fall back)
*
* @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item
*/
public function get_unsubscribe_url($method = false)
{
return false;
}
/**
* Get the user's avatar (fall back)
*
* @return string
*/
public function get_avatar()
{
return '';
}
/**
* Get the special items to load (fall back)
*
* @return array
*/
public function get_load_special()
{
return array();
}
/**
* Load the special items (fall back)
*/
public function load_special($data, $notifications)
{
return;
}
/**
* Is available (fall back)
*
* @return bool
*/
public function is_available()
{
return true;
}
/**
* Pre create insert array function (fall back)
*
* @return array
*/
public function pre_create_insert_array($type_data, $notify_users)
{
return array();
}
/**
* -------------- Helper functions -------------------
*/
/**
* Find the users who want to receive notifications (helper)
*
* @param array $user_ids User IDs to check if they want to receive notifications
* (Bool False to check all users besides anonymous and bots (USER_IGNORE))
*
* @return array
*/
protected function check_user_notification_options($user_ids = false, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
'item_type' => $this->get_type(),
'item_id' => 0, // Global by default
), $options);
if ($user_ids === false)
{
$user_ids = array();
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE user_id <> ' . ANONYMOUS . '
AND user_type <> ' . USER_IGNORE;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$user_ids[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
}
if (empty($user_ids))
{
return array();
}
$rowset = $resulting_user_ids = array();
$sql = 'SELECT user_id, method, notify
FROM ' . $this->user_notifications_table . '
WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . "
AND item_type = '" . $this->db->sql_escape($options['item_type']) . "'
AND item_id = " . (int) $options['item_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$resulting_user_ids[] = $row['user_id'];
if (!$row['notify'] || (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']])))
{
continue;
}
if (!isset($rowset[$row['user_id']]))
{
$rowset[$row['user_id']] = array();
}
$rowset[$row['user_id']][] = $row['method'];
}
$this->db->sql_freeresult($result);
foreach ($user_ids as $user_id)
{
if (!in_array($user_id, $resulting_user_ids) && !isset($options['ignore_users'][$user_id]))
{
// No rows at all for this user, default to ''
$rowset[$user_id] = array('');
}
}
return $rowset;
}
/**
* Mark this item read/unread helper
*
* @param bool $unread Unread (True/False) (Default: False)
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string|null If $return is False, nothing will be returned, else the sql code to update this item
*/
protected function mark($unread = true, $return = false)
{
$this->notification_read = (bool) !$unread;
$where = array(
"item_type = '" . $this->db->sql_escape($this->item_type) . "'",
'item_id = ' . (int) $this->item_id,
'user_id = ' . (int) $this->user_id,
);
$where = implode(' AND ', $where);
if ($return)
{
return $where;
}
$sql = 'UPDATE ' . $this->notifications_table . '
SET notification_read = ' . (int) $this->notification_read . '
WHERE ' . $where;
$this->db->sql_query($sql);
}
}

View file

@ -0,0 +1,137 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Bookmark updating notifications class
* This class handles notifications for replies to a bookmarked topic
*
* @package notifications
*/
class phpbb_notification_type_bookmark extends phpbb_notification_type_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'bookmark';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_BOOKMARK';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_BOOKMARK',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return $this->config['allow_bookmarks'];
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$users = array();
$sql = 'SELECT user_id
FROM ' . BOOKMARKS_TABLE . '
WHERE ' . $this->db->sql_in_set('topic_id', $post['topic_id']) . '
AND user_id <> ' . (int) $post['poster_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$users[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
if (empty($users))
{
return array();
}
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
$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.item_type = '" . $this->get_type() . "'
AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
AND nt.notification_type = n.item_type
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;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'bookmark';
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post disapproved notifications class
* This class handles notifications for posts when they are disapproved (for authors)
*
* @package notifications
*/
class phpbb_notification_type_disapprove_post extends phpbb_notification_type_approve_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'disapprove_post';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_POST_DISAPPROVED';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
return $this->user->lang(
$this->language_key,
censor_text($this->get_data('topic_title')),
$this->get_data('disapprove_reason')
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return '';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
return array_merge(parent::get_email_template_variables(), array(
'REASON' => htmlspecialchars_decode($this->get_data('disapprove_reason')),
));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('disapprove_reason', $post['disapprove_reason']);
$data = parent::create_insert_array($post);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'post_disapproved';
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Topic disapproved notifications class
* This class handles notifications for topics when they are disapproved (for authors)
*
* @package notifications
*/
class phpbb_notification_type_disapprove_topic extends phpbb_notification_type_approve_topic
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'disapprove_topic';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_TOPIC_DISAPPROVED';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
return $this->user->lang(
$this->language_key,
censor_text($this->get_data('topic_title')),
$this->get_data('disapprove_reason')
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return '';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
return array_merge(parent::get_email_template_variables(), array(
'REASON' => htmlspecialchars_decode($this->get_data('disapprove_reason')),
));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('disapprove_reason', $post['disapprove_reason']);
$data = parent::create_insert_array($post, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'topic_disapproved';
}
}

View file

@ -0,0 +1,189 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Base notifications interface
* @package notifications
*/
interface phpbb_notification_type_interface
{
/**
* Get notification type name
*
* @return string
*/
public function get_type();
/**
* Set initial data from the database
*
* @param array $data Row directly from the database
*/
public function set_initial_data($data);
/**
* Get the id of the item
*
* @param array $type_data The type specific data
*/
public static function get_item_id($type_data);
/**
* Get the id of the parent
*
* @param array $type_data The type specific data
*/
public static function get_item_parent_id($type_data);
/**
* Is this type available to the current user (defines whether or not it will be shown in the UCP Edit notification options)
*
* @return bool True/False whether or not this is available to the user
*/
public function is_available();
/**
* Find the users who want to receive notifications
*
* @param array $type_data The type specific data
* @param array $options Options for finding users for notification
* ignore_users => array of users and user types that should not receive notifications from this type because they've already been notified
* e.g.: array(2 => array(''), 3 => array('', 'email'), ...)
*
* @return array
*/
public function find_users_for_notification($type_data, $options);
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query();
/**
* Get the special items to load
*
* @return array Data will be combined sent to load_special() so you can run a single query and get data required for this notification type
*/
public function get_load_special();
/**
* Load the special items
*
* @param array $data Data from get_load_special()
* @param array $notifications Array of notifications (key is notification_id, value is the notification objects)
*/
public function load_special($data, $notifications);
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title();
/**
* Get the url to this item
*
* @return string URL
*/
public function get_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
*/
public function get_unsubscribe_url($method);
/**
* Get the user's avatar (the user who caused the notification typically)
*
* @return string
*/
public function get_avatar();
/**
* Prepare to output the notification to the template
*/
public function prepare_for_display();
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template();
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables();
/**
* Pre create insert array function
* This allows you to perform certain actions, like run a query
* and load data, before create_insert_array() is run. The data
* returned from this function will be sent to create_insert_array().
*
* @param array $type_data The type specific data
* @param array $notify_users Notify users list
* Formated from find_users_for_notification()
* @return array Whatever you want to send to create_insert_array().
*/
public function pre_create_insert_array($type_data, $notify_users);
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $type_data The type specific data
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($type_data, $pre_create_data);
/**
* Function for preparing the data for update in an SQL query
* (The service handles insertion)
*
* @param array $type_data Data unique to this notification type
*
* @return array Array of data ready to be updated in the database
*/
public function create_update_array($type_data);
/**
* Mark this item read
*
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string
*/
public function mark_read($return);
/**
* Mark this item unread
*
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string
*/
public function mark_unread($return);
}

View file

@ -0,0 +1,184 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Private message notifications class
* This class handles notifications for private messages
*
* @package notifications
*/
class phpbb_notification_type_pm extends phpbb_notification_type_base
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'pm';
}
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_PM',
);
/**
* Is available
*/
public function is_available()
{
return ($this->config['allow_privmsg'] && $this->auth->acl_get('u_readpm'));
}
/**
* Get the id of the
*
* @param array $pm The data from the private message
*/
public static function get_item_id($pm)
{
return (int) $pm['msg_id'];
}
/**
* Get the id of the parent
*
* @param array $pm The data from the pm
*/
public static function get_item_parent_id($pm)
{
// No parent
return 0;
}
/**
* Find the users who want to receive notifications
*
* @param array $pm Data from
*
* @return array
*/
public function find_users_for_notification($pm, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
if (!sizeof($pm['recipients']))
{
return array();
}
unset($pm['recipients'][$pm['from_user_id']]);
$this->user_loader->load_users(array_keys($pm['recipients']));
return $this->check_user_notification_options(array_keys($pm['recipients']), $options);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('from_user_id'));
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$username = $this->user_loader->get_username($this->get_data('from_user_id'), 'no_profile');
return $this->user->lang('NOTIFICATION_PM', $username, $this->get_data('message_subject'));
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'privmsg_notify';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
$user_data = $this->user_loader->get_user($this->get_data('from_user_id'));
return array(
'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
'U_VIEW_MESSAGE' => generate_board_url() . '/ucp.' . $this->php_ext . "?i=pm&mode=view&p={$this->item_id}",
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'ucp.' . $this->php_ext, "i=pm&amp;mode=view&amp;p={$this->item_id}");
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('from_user_id'));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($pm, $pre_create_data = array())
{
$this->set_data('from_user_id', $pm['from_user_id']);
$this->set_data('message_subject', $pm['message_subject']);
return parent::create_insert_array($pm, $pre_create_data);
}
}

View file

@ -0,0 +1,370 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post notifications class
* This class handles notifications for replies to a topic
*
* @package notifications
*/
class phpbb_notification_type_post extends phpbb_notification_type_base
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'post';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_POST';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_POST',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return $this->config['allow_topic_notify'];
}
/**
* Get the id of the item
*
* @param array $post The data from the post
*/
public static function get_item_id($post)
{
return (int) $post['post_id'];
}
/**
* Get the id of the parent
*
* @param array $post The data from the post
*/
public static function get_item_parent_id($post)
{
return (int) $post['topic_id'];
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$users = array();
$sql = 'SELECT user_id
FROM ' . TOPICS_WATCH_TABLE . '
WHERE topic_id = ' . (int) $post['topic_id'] . '
AND notify_status = ' . NOTIFY_YES . '
AND user_id <> ' . (int) $post['poster_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$users[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
if (empty($users))
{
return array();
}
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
$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.item_type = '" . $this->get_type() . "'
AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
AND nt.notification_type = n.item_type
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;
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('poster_id'));
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$responders = $this->get_data('responders');
$usernames = array();
if (!is_array($responders))
{
$responders = array();
}
$responders = array_merge(array(array(
'poster_id' => $this->get_data('poster_id'),
'username' => $this->get_data('post_username'),
)), $responders);
foreach ($responders as $responder)
{
if ($responder['username'])
{
$usernames[] = $responder['username'];
}
else
{
$usernames[] = $this->user_loader->get_username($responder['poster_id'], 'no_profile');
}
}
return $this->user->lang(
$this->language_key,
implode(', ', $usernames),
censor_text($this->get_data('topic_title'))
);
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'topic_notify';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
if ($this->get_data('post_username'))
{
$username = $this->get_data('post_username');
}
else
{
$username = $this->user_loader->get_username($this->get_data('poster_id'), 'no_profile');
}
return array(
'AUTHOR_NAME' => htmlspecialchars_decode($username),
'POST_SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('post_subject'))),
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
'U_VIEW_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}",
'U_NEWEST_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&view=unread#unread",
'U_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
'U_FORUM' => generate_board_url() . "/viewforum.{$this->php_ext}?f={$this->get_data('forum_id')}",
'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?uid={$this->user_id}&f={$this->get_data('forum_id')}&t={$this->item_parent_id}&unwatch=topic",
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "p={$this->item_id}#p{$this->item_id}");
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
$responders = $this->get_data('responders');
$users = array(
$this->get_data('poster_id'),
);
if (is_array($responders))
{
foreach ($responders as $responder)
{
$users[] = $responder['poster_id'];
}
}
return $users;
}
/**
* Pre create insert array function
* This allows you to perform certain actions, like run a query
* and load data, before create_insert_array() is run. The data
* returned from this function will be sent to create_insert_array().
*
* @param array $post Post data from submit_post
* @param array $notify_users Notify users list
* Formated from find_users_for_notification()
* @return array Whatever you want to send to create_insert_array().
*/
public function pre_create_insert_array($post, $notify_users)
{
if (!sizeof($notify_users))
{
return array();
}
$tracking_data = array();
$sql = 'SELECT user_id, mark_time FROM ' . TOPICS_TRACK_TABLE . '
WHERE topic_id = ' . (int) $post['topic_id'] . '
AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$tracking_data[$row['user_id']] = $row['mark_time'];
}
return $tracking_data;
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('poster_id', $post['poster_id']);
$this->set_data('topic_title', $post['topic_title']);
$this->set_data('post_subject', $post['post_subject']);
$this->set_data('post_username', (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''));
$this->set_data('forum_id', $post['forum_id']);
$this->set_data('forum_name', $post['forum_name']);
$this->notification_time = $post['post_time'];
// 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)
{
$this->notification_read = true;
}
return parent::create_insert_array($post, $pre_create_data);
}
/**
* Add responders to the notification
*
* @param mixed $post
*/
public function add_responders($post)
{
// 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)));
}
$responders = $this->get_data('responders');
$responders = ($responders === null) ? array() : $responders;
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)));
}
}
$responders[] = array(
'poster_id' => $post['poster_id'],
'username' => (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''),
);
$this->set_data('responders', $responders);
return array('notification_data' => serialize($this->get_data(false)));
}
}

View file

@ -0,0 +1,137 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post in queue notifications class
* This class handles notifications for posts that are put in the moderation queue (for moderators)
*
* @package notifications
*/
class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'post_in_queue';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_POST_IN_QUEUE';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'needs_approval',
'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_MODERATION',
);
/**
* Permission to check for (in find_users_for_notification)
*
* @var string Permission name
*/
protected $permission = 'm_approve';
/**
* Is available
*/
public function is_available()
{
$m_approve = $this->auth->acl_getf($this->permission, true);
return (!empty($m_approve));
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from the post
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
// 0 is for global
$auth_approve = $this->auth->acl_get_list(false, $this->permission, array($post['forum_id'], 0));
if (empty($auth_approve))
{
return array();
}
$auth_approve[$post['forum_id']] = array_unique(array_merge($auth_approve[$post['forum_id']], $auth_approve[0]));
return $this->check_user_notification_options($auth_approve[$post['forum_id']][$this->permission], array_merge($options, array(
'item_type' => self::$notification_option['id'],
)));
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "i=queue&amp;mode=approve_details&amp;f={$this->get_data('forum_id')}&amp;p={$this->item_id}");
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$data = parent::create_insert_array($post, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'post_in_queue';
}
}

View file

@ -0,0 +1,221 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post quoting notifications class
* This class handles notifications for quoting users in a post
*
* @package notifications
*/
class phpbb_notification_type_quote extends phpbb_notification_type_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'quote';
}
/**
* regular expression to match to find usernames
*
* @var string
*/
protected static $regular_expression_match = '#\[quote=&quot;(.+?)&quot;#';
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_QUOTE';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_QUOTE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return true;
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$usernames = false;
preg_match_all(self::$regular_expression_match, $post['post_text'], $usernames);
if (empty($usernames[1]))
{
return array();
}
$usernames[1] = array_unique($usernames[1]);
$usernames = array_map('utf8_clean_string', $usernames[1]);
$users = array();
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE ' . $this->db->sql_in_set('username_clean', $usernames) . '
AND user_id <> ' . (int) $post['poster_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$users[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
if (empty($users))
{
return array();
}
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
$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.item_type = '" . $this->get_type() . "'
AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
AND nt.notification_type = n.item_type
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;
}
/**
* Update a notification
*
* @param array $data Data specific for this type that will be updated
*/
public function update_notifications($post)
{
$old_notifications = array();
$sql = 'SELECT n.user_id
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
WHERE n.item_type = '" . $this->get_type() . "'
AND n.item_id = " . self::get_item_id($post) . '
AND nt.notification_type = n.item_type
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$old_notifications[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
// Find the new users to notify
$notifications = $this->find_users_for_notification($post);
// Find the notifications we must delete
$remove_notifications = array_diff($old_notifications, array_keys($notifications));
// Find the notifications we must add
$add_notifications = array();
foreach (array_diff(array_keys($notifications), $old_notifications) as $user_id)
{
$add_notifications[$user_id] = $notifications[$user_id];
}
// Add the necessary notifications
$this->notification_manager->add_notifications_for_users($this->get_type(), $post, $add_notifications);
// Remove the necessary notifications
if (!empty($remove_notifications))
{
$sql = 'DELETE FROM ' . $this->notifications_table . "
WHERE item_type = '" . $this->get_type() . "'
AND item_id = " . self::get_item_id($post) . '
AND ' . $this->db->sql_in_set('user_id', $remove_notifications);
$this->db->sql_query($sql);
}
// return true to continue with the update code in the notifications service (this will update the rest of the notifications)
return true;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'quote';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
$user_data = $this->user_loader->get_user($this->get_data('poster_id'));
return array_merge(parent::get_email_template_variables(), array(
'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
));
}
}

View file

@ -0,0 +1,229 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Private message reproted notifications class
* This class handles notifications for private messages when they are reported
*
* @package notifications
*/
class phpbb_notification_type_report_pm extends phpbb_notification_type_pm
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'report_pm';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_REPORT_PM';
/**
* Permission to check for (in find_users_for_notification)
*
* @var string Permission name
*/
protected $permission = 'm_report';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'report',
'lang' => 'NOTIFICATION_TYPE_REPORT',
'group' => 'NOTIFICATION_GROUP_MODERATION',
);
/**
* Get the id of the parent
*
* @param array $pm The data from the pm
*/
public static function get_item_parent_id($pm)
{
return (int) $pm['report_id'];
}
/**
* Is this type available to the current user (defines whether or not it will be shown in the UCP Edit notification options)
*
* @return bool True/False whether or not this is available to the user
*/
public function is_available()
{
$m_approve = $this->auth->acl_getf($this->permission, true);
return (!empty($m_approve));
}
/**
* Find the users who want to receive notifications
* (copied from post_in_queue)
*
* @param array $post Data from the post
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
// Global
$post['forum_id'] = 0;
$auth_approve = $this->auth->acl_get_list(false, $this->permission, $post['forum_id']);
if (empty($auth_approve))
{
return array();
}
if (($key = array_search($this->user->data['user_id'], $auth_approve[$post['forum_id']][$this->permission])))
{
unset($auth_approve[$post['forum_id']][$this->permission][$key]);
}
return $this->check_user_notification_options($auth_approve[$post['forum_id']][$this->permission], array_merge($options, array(
'item_type' => self::$notification_option['id'],
)));
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'report_pm';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
return array(
'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details",
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details");
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$this->user->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
if ($this->get_data('report_text'))
{
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('message_subject')),
$this->get_data('report_text')
);
}
if (isset($this->user->lang[$this->get_data('reason_title')]))
{
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('message_subject')),
$this->user->lang[$this->get_data('reason_title')]
);
}
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('message_subject')),
$this->get_data('reason_description')
);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('reporter_id'));
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('reporter_id'));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('reporter_id', $this->user->data['user_id']);
$this->set_data('reason_title', strtoupper($post['reason_title']));
$this->set_data('reason_description', $post['reason_description']);
$this->set_data('report_text', $post['report_text']);
return parent::create_insert_array($post, $pre_create_data);
}
}

View file

@ -0,0 +1,155 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* PM report closed notifications class
* This class handles notifications for when reports are closed on PMs (for the one who reported the PM)
*
* @package notifications
*/
class phpbb_notification_type_report_pm_closed extends phpbb_notification_type_pm
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'report_pm_closed';
}
/**
* Email template to use to send notifications
*
* @var string
*/
public $email_template = '';
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_REPORT_CLOSED';
public function is_available()
{
return false;
}
/**
* Find the users who want to receive notifications
*
* @param array $pm Data from
*
* @return array
*/
public function find_users_for_notification($pm, $options = array())
{
if ($pm['reporter'] == $this->user->data['user_id'])
{
return array();
}
return array($pm['reporter'] => array(''));
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return false;
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
return array();
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return '';
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('message_subject'))
);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->get_user_avatar($this->get_data('closer_id'));
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('closer_id'));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $pm PM Data
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($pm, $pre_create_data = array())
{
$this->set_data('closer_id', $pm['closer_id']);
$data = parent::create_insert_array($pm, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
}

View file

@ -0,0 +1,196 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Reported post notifications class
* This class handles notifications for reported posts
*
* @package notifications
*/
class phpbb_notification_type_report_post extends phpbb_notification_type_post_in_queue
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'report_post';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_REPORT_POST';
/**
* Permission to check for (in find_users_for_notification)
*
* @var string Permission name
*/
protected $permission = 'm_report';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id' and 'lang')
*/
public static $notification_option = array(
'id' => 'report',
'lang' => 'NOTIFICATION_TYPE_REPORT',
'group' => 'NOTIFICATION_GROUP_MODERATION',
);
/**
* Find the users who want to receive notifications
*
* @param array $post Data from the post
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
$notify_users = parent::find_users_for_notification($post, $options);
// never notify reporter
unset($notify_users[$this->user->data['user_id']]);
return $notify_users;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'report_post';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
$board_url = generate_board_url();
return array(
'POST_SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('post_subject'))),
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
'U_VIEW_REPORT' => "{$board_url}/mcp.{$this->php_ext}?f={$this->get_data('forum_id')}&amp;p={$this->item_id}&amp;i=reports&amp;mode=report_details#reports",
'U_VIEW_POST' => "{$board_url}/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}",
'U_NEWEST_POST' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&view=unread#unread",
'U_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
'U_VIEW_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
'U_FORUM' => "{$board_url}/viewforum.{$this->php_ext}?f={$this->get_data('forum_id')}",
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "f={$this->get_data('forum_id')}&amp;p={$this->item_id}&amp;i=reports&amp;mode=report_details#reports");
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$this->user->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
if ($this->get_data('report_text'))
{
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('post_subject')),
$this->get_data('report_text')
);
}
if (isset($this->user->lang[$this->get_data('reason_title')]))
{
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('post_subject')),
$this->user->lang[$this->get_data('reason_title')]
);
}
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('post_subject')),
$this->get_data('reason_description')
);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('reporter_id'));
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('reporter_id'));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('reporter_id', $this->user->data['user_id']);
$this->set_data('reason_title', strtoupper($post['reason_title']));
$this->set_data('reason_description', $post['reason_description']);
$this->set_data('report_text', $post['report_text']);
return parent::create_insert_array($post, $pre_create_data);
}
}

View file

@ -0,0 +1,155 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Post report closed notifications class
* This class handles notifications for when reports are closed on posts (for the one who reported the post)
*
* @package notifications
*/
class phpbb_notification_type_report_post_closed extends phpbb_notification_type_post
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'report_post_closed';
}
/**
* Email template to use to send notifications
*
* @var string
*/
public $email_template = '';
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_REPORT_CLOSED';
public function is_available()
{
return false;
}
/**
* Find the users who want to receive notifications
*
* @param array $post Data from
*
* @return array
*/
public function find_users_for_notification($post, $options = array())
{
if ($post['reporter'] == $this->user->data['user_id'])
{
return array();
}
return array($post['reporter'] => array(''));
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return false;
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
return array();
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return '';
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('post_subject'))
);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('closer_id'));
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('closer_id'));
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('closer_id', $post['closer_id']);
$data = parent::create_insert_array($post, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
}

View file

@ -0,0 +1,277 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Topic notifications class
* This class handles notifications for new topics
*
* @package notifications
*/
class phpbb_notification_type_topic extends phpbb_notification_type_base
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'topic';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_TOPIC';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_TOPIC',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
/**
* Is available
*/
public function is_available()
{
return $this->config['allow_forum_notify'];
}
/**
* Get the id of the item
*
* @param array $post The data from the post
*/
public static function get_item_id($post)
{
return (int) $post['topic_id'];
}
/**
* Get the id of the parent
*
* @param array $post The data from the post
*/
public static function get_item_parent_id($post)
{
return (int) $post['forum_id'];
}
/**
* Find the users who want to receive notifications
*
* @param array $topic Data from the topic
*
* @return array
*/
public function find_users_for_notification($topic, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
$users = array();
$sql = 'SELECT user_id
FROM ' . FORUMS_WATCH_TABLE . '
WHERE forum_id = ' . (int) $topic['forum_id'] . '
AND notify_status = ' . NOTIFY_YES . '
AND user_id <> ' . (int) $topic['poster_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$users[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
if (empty($users))
{
return array();
}
$auth_read = $this->auth->acl_get_list($users, 'f_read', $topic['forum_id']);
if (empty($auth_read))
{
return array();
}
return $this->check_user_notification_options($auth_read[$topic['forum_id']]['f_read'], $options);
}
/**
* Get the user's avatar
*/
public function get_avatar()
{
return $this->user_loader->get_avatar($this->get_data('poster_id'));
}
/**
* Get the HTML formatted title of this notification
*
* @return string
*/
public function get_title()
{
if ($this->get_data('post_username'))
{
$username = $this->get_data('post_username');
}
else
{
$username = $this->user_loader->get_username($this->get_data('poster_id'), 'no_profile');
}
return $this->user->lang(
$this->language_key,
$username,
censor_text($this->get_data('topic_title')),
$this->get_data('forum_name')
);
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'newtopic_notify';
}
/**
* Get email template variables
*
* @return array
*/
public function get_email_template_variables()
{
$board_url = generate_board_url();
if ($this->get_data('post_username'))
{
$username = $this->get_data('post_username');
}
else
{
$username = $this->user_loader->get_username($this->get_data('poster_id'), 'no_profile');
}
return array(
'AUTHOR_NAME' => htmlspecialchars_decode($username),
'FORUM_NAME' => htmlspecialchars_decode($this->get_data('forum_name')),
'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
'U_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->item_parent_id}&t={$this->item_id}",
'U_VIEW_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->item_parent_id}&t={$this->item_id}",
'U_FORUM' => "{$board_url}/viewforum.{$this->php_ext}?f={$this->item_parent_id}",
'U_STOP_WATCHING_FORUM' => "{$board_url}/viewforum.{$this->php_ext}?uid={$this->user_id}&f={$this->item_parent_id}&unwatch=forum",
);
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "f={$this->item_parent_id}&amp;t={$this->item_id}");
}
/**
* Users needed to query before this notification can be displayed
*
* @return array Array of user_ids
*/
public function users_to_query()
{
return array($this->get_data('poster_id'));
}
/**
* Pre create insert array function
* This allows you to perform certain actions, like run a query
* and load data, before create_insert_array() is run. The data
* returned from this function will be sent to create_insert_array().
*
* @param array $post Post data from submit_post
* @param array $notify_users Notify users list
* Formated from find_users_for_notification()
* @return array Whatever you want to send to create_insert_array().
*/
public function pre_create_insert_array($post, $notify_users)
{
if (!sizeof($notify_users))
{
return array();
}
$tracking_data = array();
$sql = 'SELECT user_id, mark_time FROM ' . TOPICS_TRACK_TABLE . '
WHERE topic_id = ' . (int) $post['topic_id'] . '
AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$tracking_data[$row['user_id']] = $row['mark_time'];
}
return $tracking_data;
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $post Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('poster_id', $post['poster_id']);
$this->set_data('topic_title', $post['topic_title']);
$this->set_data('post_username', (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''));
$this->set_data('forum_name', $post['forum_name']);
$this->notification_time = $post['post_time'];
// 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)
{
$this->notification_read = true;
}
return parent::create_insert_array($post, $pre_create_data);
}
}

View file

@ -0,0 +1,130 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Topic in queue notifications class
* This class handles notifications for topics when they are put in the moderation queue (for moderators)
*
* @package notifications
*/
class phpbb_notification_type_topic_in_queue extends phpbb_notification_type_topic
{
/**
* Get notification type name
*
* @return string
*/
public function get_type()
{
return 'topic_in_queue';
}
/**
* Language key used to output the text
*
* @var string
*/
protected $language_key = 'NOTIFICATION_TOPIC_IN_QUEUE';
/**
* Notification option data (for outputting to the user)
*
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
public static $notification_option = array(
'id' => 'needs_approval',
'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_MODERATION',
);
/**
* Is available
*/
public function is_available()
{
$m_approve = $this->auth->acl_getf('m_approve', true);
return (!empty($m_approve));
}
/**
* Find the users who want to receive notifications
*
* @param array $topic Data from the topic
*
* @return array
*/
public function find_users_for_notification($topic, $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
// 0 is for global
$auth_approve = $this->auth->acl_get_list(false, 'm_approve', array($topic['forum_id'], 0));
if (empty($auth_approve))
{
return array();
}
$auth_approve[$topic['forum_id']] = array_unique(array_merge($auth_approve[$topic['forum_id']], $auth_approve[0]));
return $this->check_user_notification_options($auth_approve[$topic['forum_id']]['m_approve'], array_merge($options, array(
'item_type' => self::$notification_option['id'],
)));
}
/**
* Get the url to this item
*
* @return string URL
*/
public function get_url()
{
return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "i=queue&amp;mode=approve_details&amp;f={$this->item_parent_id}&amp;t={$this->item_id}");
}
/**
* Function for preparing the data for insertion in an SQL query
* (The service handles insertion)
*
* @param array $topic Data from submit_post
* @param array $pre_create_data Data from pre_create_insert_array()
*
* @return array Array of data ready to be inserted into the database
*/
public function create_insert_array($topic, $pre_create_data = array())
{
$data = parent::create_insert_array($topic, $pre_create_data);
$this->notification_time = $data['notification_time'] = time();
return $data;
}
/**
* Get email template
*
* @return string|bool
*/
public function get_email_template()
{
return 'topic_in_queue';
}
}

Some files were not shown because too many files have changed in this diff Show more