Skip to content

Commit

Permalink
Dumped the "enable_new_pm_count" setting in favor of a live new pm co…
Browse files Browse the repository at this point in the history
…unt.

A new field "pm_new_count" was added to the user table. This field keeps
track of the number of new private messages for a user, by means of new
updates that were added to the PM functions in the DB layer.

By updating the new field when needed, there is no further need to run
a query to find the number of new messages. This works around the
performance issue for which the "enable_new_pm_count" option was
originally introduced.

A database integrity check was added to the admin interface to rebuild
all new PM counts for all users.

In the templates, {USER->new_private_messages} now contains the actual
number of new messages, not just TRUE or FALSE.
  • Loading branch information
mmakaay committed Jul 26, 2011
1 parent 5cced19 commit 7efa318
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 27 deletions.
8 changes: 4 additions & 4 deletions common.php
Expand Up @@ -234,11 +234,11 @@
$PHORUM["threaded_list"] = $modes['list'];
$PHORUM["threaded_read"] = $modes['read'];

// check if the user has new private messages
if (!empty($PHORUM["enable_new_pm_count"]) &&
!empty($PHORUM["enable_pm"])) {
// Provide the number of new private messages for the user in the
// "new_private_messages" field.
if (!empty($PHORUM["enable_pm"])) {
$PHORUM['user']['new_private_messages'] =
$PHORUM['DB']->pm_checknew($PHORUM['user']['user_id']);
$PHORUM['user']['pm_new_count'];
}
}

Expand Down
2 changes: 0 additions & 2 deletions include/admin/install.php
Expand Up @@ -407,7 +407,6 @@ function toggle_sanity_info(check_id)
"enable_pm" => "1",
"display_name_source" => "username",
"user_edit_timelimit" => "0",
"enable_new_pm_count" => "1",
"enable_dropdown_userlist" => "1",
"enable_moderator_notifications" => "1",
"show_new_on_index" => "1",
Expand All @@ -424,7 +423,6 @@ function toggle_sanity_info(check_id)
"file_offsite" => "0",
"system_email_from_name" => "",
"hide_forums" => "1",
"enable_new_pm_count" => "1",
"track_user_activity" => "86400",
"track_edits" => 0,
"html_title" => "Phorum",
Expand Down
27 changes: 25 additions & 2 deletions include/admin/rebuild.php
Expand Up @@ -150,6 +150,12 @@
$okmsg .= "Postcounts for users updated.<br />";
}

if (!empty($_POST['rebuild_newpmcounts']))
{
$ret = $PHORUM['DB']->rebuild_pm_new_counts();
$okmsg .= "New PM counts for users updated.<br />";
}

if (!empty($_POST['cleanup_stale_messages']))
{
// Delete the stale messages.
Expand Down Expand Up @@ -266,14 +272,31 @@
"Phorum stores the numbers of posts a user has made in the user-data.<br/>
In case of manual changes to the database like deleting
messages manually, this data can be outdated or broken, therefore this
option rebuilds the post-counts from the existing messages for the
user-id.<br/>
option rebuilds the post-counts from the existing messages for all
users.<br/>
<br/>
<strong>ATTENTION:</strong> This can take a some time with
lots of messages and eventually lead to timeouts if your execution
timeout is too low."
);

$row = $frm->addrow(
"Rebuild user new PM counts",
$frm->checkbox('rebuild_newpmcounts',1,"Yes")
);
$frm->addhelp($row,
"Rebuild user new PM counts",
"Phorum stores the number of new PM's for a user in the user-data.<br/>
In case of manual changes to the database like deleting
PM's manually, this data can be outdated or broken, therefore this
option rebuilds the new PM-counts from the existing PM's for the
all users.<br/>
<br/>
<strong>ATTENTION:</strong> This can take a some time with
lots of PM's and eventually lead to timeouts if your execution
timeout is too low."
);

$row = $frm->addrow(
"Rebuild display names",
$frm->checkbox('rebuild_display_names', 1 ,"Yes")
Expand Down
3 changes: 0 additions & 3 deletions include/admin/settings.php
Expand Up @@ -401,9 +401,6 @@

$row=$frm->addrow( "Private Messaging (PM):", $frm->select_tag( "enable_pm", array( "Off", "On" ), $PHORUM["enable_pm"] ) );

$row=$frm->addrow( "&nbsp;&nbsp;&nbsp;Check For New PM", $frm->select_tag( "enable_new_pm_count", array( "No", "Yes" ), $PHORUM["enable_new_pm_count"] ) );
$frm->addhelp($row, "Check For Private Messages", "By setting this to Yes, Phorum will check if a user has new private messages, and display an indicator. On a Phorum with a lot of users and private messages, this may hurt performance. This option has no effect if Private Messaging is disabled." );

$row=$frm->addrow( "&nbsp;&nbsp;&nbsp;Max number of stored messages", $frm->text_box( "max_pm_messagecount", $PHORUM["max_pm_messagecount"], 30 ) );
$frm->addhelp($row, "Max number of stored messages", "This is the maximum number of private messages that a user may store on the server. The number of private messages is the total of all messages in all PM folders together. Setting this value to zero will allow for unlimited messages.");

Expand Down
2 changes: 1 addition & 1 deletion include/api/constants.php
Expand Up @@ -40,7 +40,7 @@
/**
* Our database schema version in the format of year-month-day-serial.
*/
define( 'PHORUM_SCHEMA_VERSION', '2011040100' );
define( 'PHORUM_SCHEMA_VERSION', '2011072601' );

/**
* Our database patch level in the format of year-month-day-serial.
Expand Down
96 changes: 81 additions & 15 deletions include/db/PhorumDB.php
Expand Up @@ -6356,6 +6356,8 @@ public function pm_delete_folder($folder_id, $user_id = NULL)
NULL,
DB_MASTERQUERY
);

$this->pm_update_user_info($user_id);
}
// }}}

Expand Down Expand Up @@ -6518,15 +6520,16 @@ public function pm_messagecount($folder, $user_id = NULL)

// {{{ Method: pm_checknew()
/**
* Check if the user has any new private messages. This is useful in case
* you only want to know whether the user has new messages or not and when
* you are not interested in the exact amount of new messages.
* Check if the user has new private messages.
*
* @param mixed $user_id
* The user to check for or NULL to use the active Phorum user (default).
* The user to check for or NULL to use the active Phorum user's id
* (default, but note that directly checking the "pm_new_count"
* field for that user is more efficient).
*
* @return boolean
* TRUE in case there are new messages, FALSE otherwise.
* @return integer
* The number of new private messages for the user,
* zero when there are none.
*/
public function pm_checknew($user_id = NULL)
{
Expand All @@ -6537,14 +6540,13 @@ public function pm_checknew($user_id = NULL)

$new = $this->interact(
DB_RETURN_VALUE,
"SELECT user_id
FROM {$this->pm_xref_table}
WHERE user_id = $user_id AND
read_flag = 0",
"SELECT pm_new_count
FROM {$this->user_table}
WHERE user_id = $user_id",
NULL, NULL, 1
);

return (bool)$new;
return $new;
}
// }}}

Expand Down Expand Up @@ -6573,7 +6575,8 @@ public function pm_checknew($user_id = NULL)
* @return integer
* The id that was assigned to the new message.
*/
public function pm_send($subject, $message, $to, $from=NULL, $keepcopy=FALSE)
public function pm_send(
$subject, $message, $to, $from = NULL, $keepcopy = FALSE)
{
global $PHORUM;

Expand Down Expand Up @@ -6658,6 +6661,8 @@ public function pm_send($subject, $message, $to, $from=NULL, $keepcopy=FALSE)
);
}

$this->pm_update_user_info($to);

return $pm_id;
}
// }}}
Expand Down Expand Up @@ -6712,6 +6717,7 @@ public function pm_setflag($pm_id, $flag, $value, $user_id = NULL)
// Update message counters.
if ($flag == PHORUM_PM_READ_FLAG) {
$this->pm_update_message_info($pm_id);
$this->pm_update_user_info($user_id);
}
}
// }}}
Expand Down Expand Up @@ -6763,6 +6769,7 @@ public function pm_delete($pm_id, $folder, $user_id = NULL)

// Update message counters.
$this->pm_update_message_info($pm_id);
$this->pm_update_user_info($user_id);
}
// }}}

Expand Down Expand Up @@ -6834,6 +6841,38 @@ public function pm_move($pm_id, $from, $to, $user_id = NULL)
}
// }}}

// {{{ Method: pm_update_user_info()
/**
* Update the pm_new_count field for one or more users.
*
* @param mixed $user_id
* One user_id or an array of user_ids.
*/
public function pm_update_user_info($user_id)
{
if (!is_array($user_id)) {
$user_id = array($user_id);
}
$user_ids = array();
foreach ($user_id as $id) {
$user_ids[] = (int) $id;
}

if (empty($user_ids)) return;

$this->interact(
DB_RETURN_RES,
"UPDATE $this->user_table u
SET pm_new_count = (
SELECT count(*)
FROM $this->pm_xref_table x
WHERE read_flag = 0 AND u.user_id = x.user_id
)
WHERE u.user_id IN (" . implode(', ', $user_ids) . ")"
);
}
// }}}

// {{{ Method: pm_update_message_info()
/**
* Update the meta information for a message.
Expand All @@ -6843,11 +6882,11 @@ public function pm_move($pm_id, $from, $to, $user_id = NULL)
* message anymore, the message will be deleted from the database.
*
* @param integer $pm_id
* The id of the private message for which to update the meta information.
* The id of the private message for which to update the
* meta information.
*/
public function pm_update_message_info($pm_id)
{

settype($pm_id, 'int');

// Retrieve the meta data for the private message.
Expand Down Expand Up @@ -7260,13 +7299,40 @@ public function rebuild_search_data()
}
// }}}

// {{{ Method: rebuild_pm_new_counts()
/**
* Rebuild the user pm new counts from scratch.
*/
public function rebuild_pm_new_counts()
{
// Clear the existing PM counts.
$this->interact(
DB_RETURN_RES,
"UPDATE {$this->user_table}
SET pm_new_count = 0",
NULL,
DB_GLOBALQUERY | DB_MASTERQUERY
);

// Set the new PM counts for the users to their correct values.
$this->interact(
DB_RETURN_RES,
"UPDATE $this->user_table u
SET pm_new_count = (
SELECT count(*)
FROM $this->pm_xref_table x
WHERE read_flag = 0 AND u.user_id = x.user_id
)"
);
}
// }}}

// {{{ Method: rebuild_user_posts()
/**
* Rebuild the user post counts from scratch.
*/
public function rebuild_user_posts()
{

// Reset the post count for all users.
$this->interact(
DB_RETURN_RES,
Expand Down
1 change: 1 addition & 0 deletions include/db/PhorumMysqlDB.php
Expand Up @@ -445,6 +445,7 @@ public function create_tables()
show_signature tinyint(1) NOT NULL default 0,
email_notify tinyint(1) NOT NULL default 0,
pm_email_notify tinyint(1) NOT NULL default 1,
pm_new_count int unsigned NOT NULL default 0,
tz_offset float(4,2) NOT NULL default '-99.00',
is_dst tinyint(1) NOT NULL default 0,
user_language varchar(100) NOT NULL default '',
Expand Down
1 change: 1 addition & 0 deletions include/db/PhorumPostgresqlDB.php
Expand Up @@ -585,6 +585,7 @@ public function create_tables()
show_signature smallint NOT NULL default 0,
email_notify smallint NOT NULL default 0,
pm_email_notify smallint NOT NULL default 1,
pm_new_count bigint NOT NULL default 0,
tz_offset numeric(4,2) NOT NULL default -99.00,
is_dst smallint NOT NULL default 0,
user_language varchar(100) NOT NULL default '',
Expand Down
7 changes: 7 additions & 0 deletions include/db/upgrade/mysql/2011072600.php
@@ -0,0 +1,7 @@
<?php
if (!defined("PHORUM_ADMIN")) return;

$upgrade_queries[] =
"ALTER TABLE {$PHORUM['user_table']}
ADD COLUMN pm_new_count INT UNSIGNED NOT NULL default 0";

5 changes: 5 additions & 0 deletions include/db/upgrade/mysql/2011072601.php
@@ -0,0 +1,5 @@
<?php
if (!defined("PHORUM_ADMIN")) return;

$PHORUM['DB']->rebuild_pm_new_counts();

0 comments on commit 7efa318

Please sign in to comment.