Skip to content

Commit

Permalink
Count only visible notes
Browse files Browse the repository at this point in the history
Fix counting the number of notes to skip those that are not visible
according to the user's access levels (private notes).

Bugnote count is built alongside bugnote statistics.

This commit rewrites the statistics generation to account for user
access level for each bug and each project.

Removes duplicate logic (sql queries) from:
- bug_api.php: function bug_get_bugnote_stats()
- filter_api.php: function filter_get_bug_rows()

Fixes: #0006939
  • Loading branch information
cproensa authored and dregad committed Aug 19, 2016
1 parent aa07b7e commit 0b175c8
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 32 deletions.
108 changes: 90 additions & 18 deletions core/bug_api.php
Expand Up @@ -1544,6 +1544,93 @@ function bug_get_newest_bugnote_timestamp( $p_bug_id ) {
}
}

/**
* For a list of bug ids, return array of bugnote stats:
* the timestamp for the most recent time at which a bugnote
* associated with the bug was modified and the total bugnote
* count in one db query.
* @param array $p_bugs_id Array of Integer representing bug identifiers.
* @param integer|null $p_user_id User for checking access levels. null defaults to current user
* @return array objects consisting of bugnote stats
* @access public
* @uses database_api.php
*/
function bug_get_bugnote_stats_array( array $p_bugs_id, $p_user_id = null ) {
$t_id_array = array();
foreach( $p_bugs_id as $t_id ) {
$t_id_array[$t_id] = (int)$t_id;
}
if( empty( $t_id_array ) ) {
return array();
}

if ( null === $p_user_id ) {
$t_user_id = auth_get_current_user_id();
}
else {
$t_user_id = $p_user_id;
}

db_param_push();
$t_params = array();
$t_in_clause_elems = array();
foreach( $t_id_array as $t_id ) {
$t_in_clause_elems[] = db_param();
$t_params[] = $t_id;
}
$t_where_string = ' WHERE n.bug_id in (' . implode( ', ', $t_id_array ) . ')';
$t_query = 'SELECT n.id, n.bug_id, n.reporter_id, n.view_state, n.last_modified, n.date_submitted, b.project_id'
. ' FROM {bugnote} n JOIN {bug} b ON (n.bug_id = b.id)'
. ' WHERE n.bug_id IN (' . implode( ', ', $t_in_clause_elems ) . ')'
. ' ORDER BY b.project_id, n.bug_id, n.last_modified';
# perform query
$t_result = db_query( $t_query, $t_params );
$t_query_row = db_fetch_array( $t_result );
$t_counter = 0;
$t_stats = array();
# We need to check for each bugnote if it has permissions to view in respective project.
# bugnotes are grouped by project_id and bug_id to save calls to config_get
if( $t_query_row ) {
do {
$c_bug_id = (int)$t_query_row['bug_id'];
if( 0 == $t_counter || $t_current_project_id !== $t_query_row['project_id'] ) {
# evaluating a new project from the rowset
$t_current_project_id = $t_query_row['project_id'];
$t_user_access_level = access_get_project_level( $t_query_row['project_id'], $t_user_id );
$t_private_bugnote_visible = access_compare_level( $t_user_access_level, config_get( 'private_bugnote_threshold', null, $t_user_id, $t_query_row['project_id'] ) );
}
if( 0 == $t_counter || $t_current_bug_id !== $c_bug_id ) {
# evaluating a new bug from the rowset
$t_current_bug_id = $c_bug_id;
$t_note_count = 0;
$t_last_submit_date= 0;
}
$t_note_visible = $t_private_bugnote_visible || $t_query_row['reporter_id'] == $t_user_id || ( VS_PUBLIC == $t_query_row['view_state'] );
if( $t_note_visible ) {
# only count the bugnote if user has access
$t_stats[$c_bug_id]['bug_id'] = $c_bug_id;
$t_stats[$c_bug_id]['last_modified'] = $t_query_row['last_modified'];
$t_stats[$c_bug_id]['count'] = ++$t_note_count;
$t_stats[$c_bug_id]['last_modified_bugnote'] = $t_query_row['id'];
if( $t_query_row['date_submitted'] > $t_last_submit_date ) {
$t_last_submit_date = $t_query_row['date_submitted'];
$t_stats[$c_bug_id]['last_submitted_bugnote'] = $t_query_row['id'];
}
if( isset( $t_id_array[$c_bug_id] ) ) {
unset( $t_id_array[$c_bug_id] );
}
}
$t_counter++;
}
while ( $t_query_row = db_fetch_array( $t_result ) );
}
# The remaining bug ids, are those without visible notes. Save false as chached value.
foreach( $t_id_array as $t_id ) {
$t_stats[$t_id] = false;
}
return $t_stats;
}

/**
* return the timestamp for the most recent time at which a bugnote
* associated with the bug was modified and the total bugnote
Expand All @@ -1560,25 +1647,10 @@ function bug_get_bugnote_stats( $p_bug_id ) {
if( array_key_exists( '_stats', $g_cache_bug[$c_bug_id] ) ) {
return $g_cache_bug[$c_bug_id]['_stats'];
}

# @todo - optimise - max(), count()
db_param_push();
$t_query = 'SELECT last_modified FROM {bugnote} WHERE bug_id=' . db_param() . ' ORDER BY last_modified ASC';
$t_result = db_query( $t_query, array( $c_bug_id ) );

$t_bugnote_count = 0;
while( $t_row = db_fetch_array( $t_result ) ) {
$t_bugnote_count++;
}

if( $t_bugnote_count === 0 ) {
return false;
else {
$t_stats = bug_get_bugnote_stats_array( array( $p_bug_id ) );
return $t_stats[$p_bug_id];
}

$t_stats['last_modified'] = $t_row['last_modified'];
$t_stats['count'] = $t_bugnote_count;

return $t_stats;
}

/**
Expand Down
18 changes: 4 additions & 14 deletions core/filter_api.php
Expand Up @@ -2193,23 +2193,13 @@ function filter_get_bug_rows_query_clauses( array $p_filter, $p_project_id = nul
* @return array
*/
function filter_cache_result( array $p_rows, array $p_id_array_lastmod ) {
$t_id_array_lastmod = array_unique( $p_id_array_lastmod );
$t_where_string = ' WHERE {bugnote}.bug_id in (' . implode( ', ', $t_id_array_lastmod ) . ')';
$t_query = 'SELECT DISTINCT bug_id,MAX(last_modified) as last_modified, COUNT(last_modified) as count FROM {bugnote} ' . $t_where_string . ' GROUP BY bug_id';

# perform query
$t_result = db_query( $t_query );
$t_row_count = db_num_rows( $t_result );
while ( $t_row = db_fetch_array( $t_result ) ) {
$t_stats[$t_row['bug_id']] = $t_row;
}

$t_stats = bug_get_bugnote_stats_array( $p_id_array_lastmod );
$t_rows = array();
foreach( $p_rows as $t_row ) {
if( !isset( $t_stats[$t_row['id']] ) ) {
$t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row ) );
} else {
if( isset( $t_stats[$t_row['id']] ) && false !== $t_stats[$t_row['id']] ) {
$t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row, $t_stats[$t_row['id']] ) );
} else {
$t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row ) );
}
}
return $t_rows;
Expand Down

0 comments on commit 0b175c8

Please sign in to comment.