SOAP API: do not try to unserialize an invalid filter
[mantis.git] / core / history_api.php
blob180ea56280e62f696f3c73ebf587b877d226a707
1 <?php
2 # MantisBT - A PHP based bugtracking system
4 # MantisBT is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 2 of the License, or
7 # (at your option) any later version.
9 # MantisBT is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * History API
20 * @package CoreAPI
21 * @subpackage HistoryAPI
22 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
23 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net
24 * @link http://www.mantisbt.org
26 * @uses access_api.php
27 * @uses authentication_api.php
28 * @uses bug_api.php
29 * @uses bug_revision_api.php
30 * @uses bugnote_api.php
31 * @uses columns_api.php
32 * @uses config_api.php
33 * @uses constant_inc.php
34 * @uses custom_field_api.php
35 * @uses database_api.php
36 * @uses gpc_api.php
37 * @uses helper_api.php
38 * @uses lang_api.php
39 * @uses project_api.php
40 * @uses relationship_api.php
41 * @uses sponsorship_api.php
42 * @uses user_api.php
43 * @uses utility_api.php
46 require_api( 'access_api.php' );
47 require_api( 'authentication_api.php' );
48 require_api( 'bug_api.php' );
49 require_api( 'bug_revision_api.php' );
50 require_api( 'bugnote_api.php' );
51 require_api( 'columns_api.php' );
52 require_api( 'config_api.php' );
53 require_api( 'constant_inc.php' );
54 require_api( 'custom_field_api.php' );
55 require_api( 'database_api.php' );
56 require_api( 'gpc_api.php' );
57 require_api( 'helper_api.php' );
58 require_api( 'lang_api.php' );
59 require_api( 'project_api.php' );
60 require_api( 'relationship_api.php' );
61 require_api( 'sponsorship_api.php' );
62 require_api( 'user_api.php' );
63 require_api( 'utility_api.php' );
65 /**
66 * log the changes (old / new value are supplied to reduce db access)
67 * events should be logged *after* the modification
68 * @param int $p_bug_id
69 * @param string $p_field_name
70 * @param string $p_old_value
71 * @param string $p_new_value
72 * @param int $p_user_id
73 * @param int $p_type
75 function history_log_event_direct( $p_bug_id, $p_field_name, $p_old_value, $p_new_value, $p_user_id = null, $p_type = 0 ) {
76 # Only log events that change the value
77 if( $p_new_value != $p_old_value ) {
78 if( null === $p_user_id ) {
79 $p_user_id = auth_get_current_user_id();
82 $c_field_name = $p_field_name;
83 $c_old_value = ( is_null( $p_old_value ) ? '' : $p_old_value );
84 $c_new_value = ( is_null( $p_new_value ) ? '' : $p_new_value );
85 $c_bug_id = db_prepare_int( $p_bug_id );
86 $c_user_id = db_prepare_int( $p_user_id );
87 $c_type = db_prepare_int( $p_type );
89 $t_mantis_bug_history_table = db_get_table( 'bug_history' );
91 $query = "INSERT INTO $t_mantis_bug_history_table
92 ( user_id, bug_id, date_modified, field_name, old_value, new_value, type )
93 VALUES
94 ( " . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ' )';
95 $result = db_query_bound( $query, Array( $c_user_id, $c_bug_id, db_now(), $c_field_name, $c_old_value, $c_new_value, $c_type ) );
99 /**
100 * log the changes
101 * events should be logged *after* the modification
102 * @param int $p_bug_id
103 * @param string $p_field_name
104 * @param string $p_old_value
105 * @return null
107 function history_log_event( $p_bug_id, $p_field_name, $p_old_value ) {
108 history_log_event_direct( $p_bug_id, $p_field_name, $p_old_value, bug_get_field( $p_bug_id, $p_field_name ) );
112 * log the changes
113 * events should be logged *after* the modification
114 * These are special case logs (new bug, deleted bugnote, etc.)
115 * @param int $p_bug_id
116 * @param int $p_type
117 * @param string $p_optional
118 * @param string $p_optional2
119 * @return null
121 function history_log_event_special( $p_bug_id, $p_type, $p_optional = '', $p_optional2 = '' ) {
122 $c_bug_id = db_prepare_int( $p_bug_id );
123 $c_type = db_prepare_int( $p_type );
124 $c_optional = ( $p_optional );
125 $c_optional2 = ( $p_optional2 );
126 $t_user_id = auth_get_current_user_id();
128 $t_mantis_bug_history_table = db_get_table( 'bug_history' );
130 $query = "INSERT INTO $t_mantis_bug_history_table
131 ( user_id, bug_id, date_modified, type, old_value, new_value, field_name )
132 VALUES
133 ( " . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ',' . db_param() . ', ' . db_param() . ')';
134 $result = db_query_bound( $query, Array( $t_user_id, $c_bug_id, db_now(), $c_type, $c_optional, $c_optional2, '' ) );
138 * Retrieves the history events for the specified bug id and returns it in an array
139 * The array is indexed from 0 to N-1. The second dimension is: 'date', 'username',
140 * 'note', 'change'.
141 * @param int $p_bug_id
142 * @param int $p_user_id
143 * @return array
145 function history_get_events_array( $p_bug_id, $p_user_id = null ) {
146 $t_normal_date_format = config_get( 'normal_date_format' );
148 $raw_history = history_get_raw_events_array( $p_bug_id, $p_user_id );
149 $raw_history_count = count( $raw_history );
150 $history = array();
152 for( $i = 0;$i < $raw_history_count;$i++ ) {
153 $history[$i] = history_localize_item( $raw_history[$i]['field'], $raw_history[$i]['type'], $raw_history[$i]['old_value'], $raw_history[$i]['new_value'] );
154 $history[$i]['date'] = date( $t_normal_date_format, $raw_history[$i]['date'] );
155 $history[$i]['userid'] = $raw_history[$i]['userid'];
156 $history[$i]['username'] = $raw_history[$i]['username'];
159 return( $history );
163 * Retrieves the raw history events for the specified bug id and returns it in an array
164 * The array is indexed from 0 to N-1. The second dimension is: 'date', 'userid', 'username',
165 * 'field','type','old_value','new_value'
166 * @param int $p_bug_id
167 * @param int $p_user_id
168 * @return array
170 function history_get_raw_events_array( $p_bug_id, $p_user_id = null ) {
171 $t_mantis_bug_history_table = db_get_table( 'bug_history' );
172 $t_mantis_user_table = db_get_table( 'user' );
173 $t_history_order = config_get( 'history_order' );
174 $c_bug_id = db_prepare_int( $p_bug_id );
176 $t_user_id = (( null === $p_user_id ) ? auth_get_current_user_id() : $p_user_id );
178 $t_roadmap_view_access_level = config_get( 'roadmap_view_threshold' );
179 $t_due_date_view_threshold = config_get( 'due_date_view_threshold' );
181 # grab history and display by date_modified then field_name
182 # @@@ by MASC I guess it's better by id then by field_name. When we have more history lines with the same
183 # date, it's better to respect the storing order otherwise we should risk to mix different information
184 # I give you an example. We create a child of a bug with different custom fields. In the history of the child
185 # bug we will find the line related to the relationship mixed with the custom fields (the history is creted
186 # for the new bug with the same timestamp...)
187 $query = "SELECT *
188 FROM $t_mantis_bug_history_table
189 WHERE bug_id=" . db_param() . "
190 ORDER BY date_modified $t_history_order,id";
191 $result = db_query_bound( $query, Array( $c_bug_id ) );
192 $raw_history_count = db_num_rows( $result );
193 $raw_history = array();
195 $t_private_bugnote_threshold = config_get( 'private_bugnote_threshold' );
196 $t_private_bugnote_visible = access_has_bug_level( config_get( 'private_bugnote_threshold' ), $p_bug_id, $t_user_id );
197 $t_tag_view_threshold = config_get( 'tag_view_threshold' );
198 $t_show_monitor_list_threshold = config_get( 'show_monitor_list_threshold' );
200 $t_standard_fields = columns_get_standard();
202 for( $i = 0, $j = 0;$i < $raw_history_count;++$i ) {
203 $t_row = db_fetch_array( $result );
205 $v_type = $t_row['type'];
206 $v_field_name = $t_row['field_name'];
207 $v_user_id = $t_row['user_id'];
208 $v_new_value = $t_row['new_value'];
209 $v_old_value = $t_row['old_value'];
210 $v_date_modified = $t_row['date_modified'];
212 if ( $v_type == NORMAL_TYPE ) {
213 if ( !in_array( $v_field_name, $t_standard_fields ) ) {
215 // check that the item should be visible to the user
216 // custom fields - we are passing 32 here to notify the API that the custom field name is truncated by the history column from 64 to 32 characters.
217 $t_field_id = custom_field_get_id_from_name( $v_field_name, 32 );
218 if( false !== $t_field_id && !custom_field_has_read_access( $t_field_id, $p_bug_id, $t_user_id ) ) {
219 continue;
223 if ( ( $v_field_name == 'target_version' ) && !access_has_bug_level( $t_roadmap_view_access_level, $p_bug_id, $t_user_id ) ) {
224 continue;
227 if ( ( $v_field_name == 'due_date' ) && !access_has_bug_level( $t_due_date_view_threshold, $p_bug_id, $t_user_id ) ) {
228 continue;
232 // bugnotes
233 if( $t_user_id != $v_user_id ) {
234 // bypass if user originated note
235 if(( $v_type == BUGNOTE_ADDED ) || ( $v_type == BUGNOTE_UPDATED ) || ( $v_type == BUGNOTE_DELETED ) ) {
236 if( !$t_private_bugnote_visible && ( bugnote_get_field( $v_old_value, 'view_state' ) == VS_PRIVATE ) ) {
237 continue;
241 if( $v_type == BUGNOTE_STATE_CHANGED ) {
242 if( !$t_private_bugnote_visible && ( bugnote_get_field( $v_new_value, 'view_state' ) == VS_PRIVATE ) ) {
243 continue;
248 // tags
249 if( $v_type == TAG_ATTACHED || $v_type == TAG_DETACHED || $v_type == TAG_RENAMED ) {
250 if( !access_has_bug_level( $t_tag_view_threshold, $p_bug_id, $t_user_id ) ) {
251 continue;
255 // monitoring
256 if( $v_type == BUG_MONITOR || $v_type == BUG_UNMONITOR ) {
257 if( !access_has_bug_level( $t_show_monitor_list_threshold, $p_bug_id, $t_user_id ) ) {
258 continue;
262 $raw_history[$j]['date'] = $v_date_modified;
263 $raw_history[$j]['userid'] = $v_user_id;
265 # user_get_name handles deleted users, and username vs realname
266 $raw_history[$j]['username'] = user_get_name( $v_user_id );
268 $raw_history[$j]['field'] = $v_field_name;
269 $raw_history[$j]['type'] = $v_type;
270 $raw_history[$j]['old_value'] = $v_old_value;
271 $raw_history[$j]['new_value'] = $v_new_value;
273 $j++;
276 # end for loop
278 return $raw_history;
282 * Localizes one raw history item specified by set the next parameters: $p_field_name, $p_type, $p_old_value, $p_new_value
283 * Returns array with two elements indexed as 'note' and 'change'
284 * @param string $p_field_name
285 * @param int $p_type
286 * @param string $p_old_value
287 * @param string $p_new_value
288 * @param bool $p_linkify
289 * @return array
291 function history_localize_item( $p_field_name, $p_type, $p_old_value, $p_new_value, $p_linkify=true ) {
292 $t_note = '';
293 $t_change = '';
294 $t_field_localized = $p_field_name;
295 $t_raw = true;
297 if( PLUGIN_HISTORY == $p_type ) {
298 $t_note = lang_get_defaulted( "plugin_$p_field_name", $p_field_name );
299 $t_change = ( isset( $p_new_value ) ? "$p_old_value => $p_new_value" : $p_old_value );
301 return array( 'note' => $t_note, 'change' => $t_change, 'raw' => true );
304 switch( $p_field_name ) {
305 case 'category':
306 $t_field_localized = lang_get( 'category' );
307 break;
308 case 'status':
309 $p_old_value = get_enum_element( 'status', $p_old_value );
310 $p_new_value = get_enum_element( 'status', $p_new_value );
311 $t_field_localized = lang_get( 'status' );
312 break;
313 case 'severity':
314 $p_old_value = get_enum_element( 'severity', $p_old_value );
315 $p_new_value = get_enum_element( 'severity', $p_new_value );
316 $t_field_localized = lang_get( 'severity' );
317 break;
318 case 'reproducibility':
319 $p_old_value = get_enum_element( 'reproducibility', $p_old_value );
320 $p_new_value = get_enum_element( 'reproducibility', $p_new_value );
321 $t_field_localized = lang_get( 'reproducibility' );
322 break;
323 case 'resolution':
324 $p_old_value = get_enum_element( 'resolution', $p_old_value );
325 $p_new_value = get_enum_element( 'resolution', $p_new_value );
326 $t_field_localized = lang_get( 'resolution' );
327 break;
328 case 'priority':
329 $p_old_value = get_enum_element( 'priority', $p_old_value );
330 $p_new_value = get_enum_element( 'priority', $p_new_value );
331 $t_field_localized = lang_get( 'priority' );
332 break;
333 case 'eta':
334 $p_old_value = get_enum_element( 'eta', $p_old_value );
335 $p_new_value = get_enum_element( 'eta', $p_new_value );
336 $t_field_localized = lang_get( 'eta' );
337 break;
338 case 'view_state':
339 $p_old_value = get_enum_element( 'view_state', $p_old_value );
340 $p_new_value = get_enum_element( 'view_state', $p_new_value );
341 $t_field_localized = lang_get( 'view_status' );
342 break;
343 case 'projection':
344 $p_old_value = get_enum_element( 'projection', $p_old_value );
345 $p_new_value = get_enum_element( 'projection', $p_new_value );
346 $t_field_localized = lang_get( 'projection' );
347 break;
348 case 'sticky':
349 $p_old_value = gpc_string_to_bool( $p_old_value ) ? lang_get( 'yes' ) : lang_get( 'no' );
350 $p_new_value = gpc_string_to_bool( $p_new_value ) ? lang_get( 'yes' ) : lang_get( 'no' );
351 $t_field_localized = lang_get( 'sticky_issue' );
352 break;
353 case 'project_id':
354 if( project_exists( $p_old_value ) ) {
355 $p_old_value = project_get_field( $p_old_value, 'name' );
356 } else {
357 $p_old_value = '@' . $p_old_value . '@';
360 # Note that the new value maybe an intermediately project and not the
361 # current one.
362 if( project_exists( $p_new_value ) ) {
363 $p_new_value = project_get_field( $p_new_value, 'name' );
364 } else {
365 $p_new_value = '@' . $p_new_value . '@';
367 $t_field_localized = lang_get( 'email_project' );
368 break;
369 case 'handler_id':
370 $t_field_localized = lang_get( 'assigned_to' );
371 case 'reporter_id':
372 if( 'reporter_id' == $p_field_name ) {
373 $t_field_localized = lang_get( 'reporter' );
375 if( 0 == $p_old_value ) {
376 $p_old_value = '';
377 } else {
378 $p_old_value = user_get_name( $p_old_value );
381 if( 0 == $p_new_value ) {
382 $p_new_value = '';
383 } else {
384 $p_new_value = user_get_name( $p_new_value );
386 break;
387 case 'version':
388 $t_field_localized = lang_get( 'product_version' );
389 break;
390 case 'fixed_in_version':
391 $t_field_localized = lang_get( 'fixed_in_version' );
392 break;
393 case 'target_version':
394 $t_field_localized = lang_get( 'target_version' );
395 break;
396 case 'date_submitted':
397 $t_field_localized = lang_get( 'date_submitted' );
398 break;
399 case 'last_updated':
400 $t_field_localized = lang_get( 'last_update' );
401 break;
402 case 'os':
403 $t_field_localized = lang_get( 'os' );
404 break;
405 case 'os_build':
406 $t_field_localized = lang_get( 'os_version' );
407 break;
408 case 'build':
409 $t_field_localized = lang_get( 'build' );
410 break;
411 case 'platform':
412 $t_field_localized = lang_get( 'platform' );
413 break;
414 case 'summary':
415 $t_field_localized = lang_get( 'summary' );
416 break;
417 case 'duplicate_id':
418 $t_field_localized = lang_get( 'duplicate_id' );
419 break;
420 case 'sponsorship_total':
421 $t_field_localized = lang_get( 'sponsorship_total' );
422 break;
423 case 'due_date':
424 if( $p_old_value !== '' ) {
425 $p_old_value = date( config_get( 'normal_date_format' ), (int) $p_old_value );
427 if( $p_new_value !== '' ) {
428 $p_new_value = date( config_get( 'normal_date_format' ), (int) $p_new_value );
430 $t_field_localized = lang_get( 'due_date' );
431 break;
432 default:
434 # assume it's a custom field name
435 $t_field_id = custom_field_get_id_from_name( $p_field_name );
436 if( false !== $t_field_id ) {
437 $t_cf_type = custom_field_type( $t_field_id );
438 if( '' != $p_old_value ) {
439 $p_old_value = string_custom_field_value_for_email( $p_old_value, $t_cf_type );
441 $p_new_value = string_custom_field_value_for_email( $p_new_value, $t_cf_type );
445 if( NORMAL_TYPE != $p_type ) {
446 switch( $p_type ) {
447 case NEW_BUG:
448 $t_note = lang_get( 'new_bug' );
449 break;
450 case BUGNOTE_ADDED:
451 $t_note = lang_get( 'bugnote_added' ) . ': ' . $p_old_value;
452 break;
453 case BUGNOTE_UPDATED:
454 $t_note = lang_get( 'bugnote_edited' ) . ': ' . $p_old_value;
455 $t_old_value = (int)$p_old_value;
456 $t_new_value = (int)$p_new_value;
457 if ( $p_linkify && bug_revision_exists( $t_new_value ) ) {
458 if ( bugnote_exists( $t_old_value ) ) {
459 $t_bug_revision_view_page_argument = 'bugnote_id=' . $t_old_value . '#r' . $t_new_value;
460 } else {
461 $t_bug_revision_view_page_argument = 'rev_id=' . $t_new_value;
463 $t_change = '<a href="bug_revision_view_page.php?' . $t_bug_revision_view_page_argument . '">' .
464 lang_get( 'view_revisions' ) . '</a>';
465 $t_raw = false;
467 break;
468 case BUGNOTE_DELETED:
469 $t_note = lang_get( 'bugnote_deleted' ) . ': ' . $p_old_value;
470 break;
471 case DESCRIPTION_UPDATED:
472 $t_note = lang_get( 'description_updated' );
473 $t_old_value = (int)$p_old_value;
474 if ( $p_linkify && bug_revision_exists( $t_old_value ) ) {
475 $t_change = '<a href="bug_revision_view_page.php?rev_id=' . $t_old_value . '#r' . $t_old_value . '">' .
476 lang_get( 'view_revisions' ) . '</a>';
477 $t_raw = false;
479 break;
480 case ADDITIONAL_INFO_UPDATED:
481 $t_note = lang_get( 'additional_information_updated' );
482 $t_old_value = (int)$p_old_value;
483 if ( $p_linkify && bug_revision_exists( $t_old_value ) ) {
484 $t_change = '<a href="bug_revision_view_page.php?rev_id=' . $t_old_value . '#r' . $t_old_value . '">' .
485 lang_get( 'view_revisions' ) . '</a>';
486 $t_raw = false;
488 break;
489 case STEP_TO_REPRODUCE_UPDATED:
490 $t_note = lang_get( 'steps_to_reproduce_updated' );
491 $t_old_value = (int)$p_old_value;
492 if ( $p_linkify && bug_revision_exists( $t_old_value ) ) {
493 $t_change = '<a href="bug_revision_view_page.php?rev_id=' . $t_old_value . '#r' . $t_old_value . '">' .
494 lang_get( 'view_revisions' ) . '</a>';
495 $t_raw = false;
497 break;
498 case FILE_ADDED:
499 $t_note = lang_get( 'file_added' ) . ': ' . $p_old_value;
500 break;
501 case FILE_DELETED:
502 $t_note = lang_get( 'file_deleted' ) . ': ' . $p_old_value;
503 break;
504 case BUGNOTE_STATE_CHANGED:
505 $p_old_value = get_enum_element( 'view_state', $p_old_value );
506 $t_note = lang_get( 'bugnote_view_state' ) . ': ' . $p_new_value . ': ' . $p_old_value;
507 break;
508 case BUG_MONITOR:
509 $p_old_value = user_get_name( $p_old_value );
510 $t_note = lang_get( 'bug_monitor' ) . ': ' . $p_old_value;
511 break;
512 case BUG_UNMONITOR:
513 $p_old_value = user_get_name( $p_old_value );
514 $t_note = lang_get( 'bug_end_monitor' ) . ': ' . $p_old_value;
515 break;
516 case BUG_DELETED:
517 $t_note = lang_get( 'bug_deleted' ) . ': ' . $p_old_value;
518 break;
519 case BUG_ADD_SPONSORSHIP:
520 $t_note = lang_get( 'sponsorship_added' );
521 $t_change = user_get_name( $p_old_value ) . ': ' . sponsorship_format_amount( $p_new_value );
522 break;
523 case BUG_UPDATE_SPONSORSHIP:
524 $t_note = lang_get( 'sponsorship_updated' );
525 $t_change = user_get_name( $p_old_value ) . ': ' . sponsorship_format_amount( $p_new_value );
526 break;
527 case BUG_DELETE_SPONSORSHIP:
528 $t_note = lang_get( 'sponsorship_deleted' );
529 $t_change = user_get_name( $p_old_value ) . ': ' . sponsorship_format_amount( $p_new_value );
530 break;
531 case BUG_PAID_SPONSORSHIP:
532 $t_note = lang_get( 'sponsorship_paid' );
533 $t_change = user_get_name( $p_old_value ) . ': ' . get_enum_element( 'sponsorship', $p_new_value );
534 break;
535 case BUG_ADD_RELATIONSHIP:
536 $t_note = lang_get( 'relationship_added' );
537 $t_change = relationship_get_description_for_history( $p_old_value ) . ' ' . bug_format_id( $p_new_value );
538 break;
539 case BUG_REPLACE_RELATIONSHIP:
540 $t_note = lang_get( 'relationship_replaced' );
541 $t_change = relationship_get_description_for_history( $p_old_value ) . ' ' . bug_format_id( $p_new_value );
542 break;
543 case BUG_DEL_RELATIONSHIP:
544 $t_note = lang_get( 'relationship_deleted' );
546 # Fix for #7846: There are some cases where old value is empty, this may be due to an old bug.
547 if( !is_blank( $p_old_value ) && $p_old_value > 0 ) {
548 $t_change = relationship_get_description_for_history( $p_old_value ) . ' ' . bug_format_id( $p_new_value );
549 } else {
550 $t_change = bug_format_id( $p_new_value );
552 break;
553 case BUG_CLONED_TO:
554 $t_note = lang_get( 'bug_cloned_to' );
555 $t_change = bug_format_id( $p_new_value );
556 break;
557 case BUG_CREATED_FROM:
558 $t_note = lang_get( 'bug_created_from' );
559 $t_change = bug_format_id( $p_new_value );
560 break;
561 case TAG_ATTACHED:
562 $t_note = lang_get( 'tag_history_attached' ) . ': ' . $p_old_value;
563 break;
564 case TAG_DETACHED:
565 $t_note = lang_get( 'tag_history_detached' ) . ': ' . $p_old_value;
566 break;
567 case TAG_RENAMED:
568 $t_note = lang_get( 'tag_history_renamed' );
569 $t_change = $p_old_value . ' => ' . $p_new_value;
570 break;
571 case BUG_REVISION_DROPPED:
572 $t_note = lang_get( 'bug_revision_dropped_history' ) . ': ' . bug_revision_get_type_name( $p_new_value ) . ': ' . $p_old_value;
573 break;
574 case BUGNOTE_REVISION_DROPPED:
575 $t_note = lang_get( 'bugnote_revision_dropped_history' ) . ': ' . $p_new_value . ': ' . $p_old_value;
576 break;
580 # output special cases
581 if( NORMAL_TYPE == $p_type ) {
582 $t_note = $t_field_localized;
583 $t_change = $p_old_value . ' => ' . $p_new_value;
586 # end if DEFAULT
587 return array( 'note' => $t_note, 'change' => $t_change, 'raw' => $t_raw );
591 * delete all history associated with a bug
592 * @param int $p_bug_id
593 * @return true
595 function history_delete( $p_bug_id ) {
596 $c_bug_id = db_prepare_int( $p_bug_id );
598 $t_bug_history_table = db_get_table( 'bug_history' );
600 $query = 'DELETE FROM ' . $t_bug_history_table . ' WHERE bug_id=' . db_param();
601 db_query_bound( $query, Array( $c_bug_id ) );
603 # db_query errors on failure so:
604 return true;