| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisConnect - A webservice interface to Mantis Bug Tracker 3 # Copyright (C) 2004-2011 Victor Boctor - vboctor@users.sourceforge.net 4 # This program is distributed under dual licensing. These include 5 # GPL and a commercial licenses. Victor Boctor reserves the right to 6 # change the license of future releases. 7 # See docs/ folder for more details 8 9 require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'mc_core.php' ); 10 11 /** 12 * Check if an issue with the given id exists. 13 * 14 * @param string $p_username The name of the user trying to access the issue. 15 * @param string $p_password The password of the user. 16 * @param integer $p_issue_id The id of the issue to check. 17 * @return boolean true if there is an issue with the given id, false otherwise. 18 */ 19 function mc_issue_exists( $p_username, $p_password, $p_issue_id ) { 20 $t_user_id = mci_check_login( $p_username, $p_password ); 21 if( $t_user_id === false ) { 22 return mci_soap_fault_login_failed(); 23 } 24 25 if( !bug_exists( $p_issue_id ) ) { 26 return false; 27 } 28 29 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 30 if( !mci_has_readonly_access( $t_user_id, $t_project_id ) ) { 31 32 // if we return an error here, then we answered the question! 33 return false; 34 } 35 36 return true; 37 } 38 39 /** 40 * Get all details about an issue. 41 * 42 * @param string $p_username The name of the user trying to access the issue. 43 * @param string $p_password The password of the user. 44 * @param integer $p_issue_id The id of the issue to retrieve. 45 * @return Array that represents an IssueData structure 46 */ 47 function mc_issue_get( $p_username, $p_password, $p_issue_id ) { 48 $t_user_id = mci_check_login( $p_username, $p_password ); 49 if( $t_user_id === false ) { 50 return mci_soap_fault_login_failed(); 51 } 52 53 $t_lang = mci_get_user_lang( $t_user_id ); 54 55 if( !bug_exists( $p_issue_id ) ) { 56 return new soap_fault( 'Client', '', 'Issue does not exist.' ); 57 } 58 59 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 60 if( !mci_has_readonly_access( $t_user_id, $t_project_id ) ) { 61 return mci_soap_fault_access_denied( $t_user_id ); 62 } 63 64 if( !access_has_bug_level( VIEWER, $p_issue_id, $t_user_id ) ){ 65 return mci_soap_fault_access_denied( $t_user_id ); 66 } 67 68 $t_bug = bug_get( $p_issue_id, true ); 69 $t_issue_data = array(); 70 71 $t_issue_data['id'] = $p_issue_id; 72 $t_issue_data['view_state'] = mci_enum_get_array_by_id( $t_bug->view_state, 'view_state', $t_lang ); 73 $t_issue_data['last_updated'] = timestamp_to_iso8601( $t_bug->last_updated ); 74 75 $t_issue_data['project'] = mci_project_as_array_by_id( $t_bug->project_id ); 76 $t_issue_data['category'] = mci_get_category( $t_bug->category_id ); 77 $t_issue_data['priority'] = mci_enum_get_array_by_id( $t_bug->priority, 'priority', $t_lang ); 78 $t_issue_data['severity'] = mci_enum_get_array_by_id( $t_bug->severity, 'severity', $t_lang ); 79 $t_issue_data['status'] = mci_enum_get_array_by_id( $t_bug->status, 'status', $t_lang ); 80 81 $t_issue_data['reporter'] = mci_account_get_array_by_id( $t_bug->reporter_id ); 82 $t_issue_data['summary'] = $t_bug->summary; 83 $t_issue_data['version'] = mci_null_if_empty( $t_bug->version ); 84 $t_issue_data['build'] = mci_null_if_empty( $t_bug->build ); 85 $t_issue_data['platform'] = mci_null_if_empty( $t_bug->platform ); 86 $t_issue_data['os'] = mci_null_if_empty( $t_bug->os ); 87 $t_issue_data['os_build'] = mci_null_if_empty( $t_bug->os_build ); 88 $t_issue_data['reproducibility'] = mci_enum_get_array_by_id( $t_bug->reproducibility, 'reproducibility', $t_lang ); 89 $t_issue_data['date_submitted'] = timestamp_to_iso8601( $t_bug->date_submitted ); 90 91 $t_issue_data['sponsorship_total'] = $t_bug->sponsorship_total; 92 93 if( !empty( $t_bug->handler_id ) ) { 94 $t_issue_data['handler'] = mci_account_get_array_by_id( $t_bug->handler_id ); 95 } 96 97 $t_issue_data['projection'] = mci_enum_get_array_by_id( $t_bug->projection, 'projection', $t_lang ); 98 $t_issue_data['eta'] = mci_enum_get_array_by_id( $t_bug->eta, 'eta', $t_lang ); 99 100 $t_issue_data['resolution'] = mci_enum_get_array_by_id( $t_bug->resolution, 'resolution', $t_lang ); 101 $t_issue_data['fixed_in_version'] = mci_null_if_empty( $t_bug->fixed_in_version ); 102 $t_issue_data['target_version'] = mci_null_if_empty( $t_bug->target_version ); 103 $t_issue_data['due_date'] = mci_issue_get_due_date( $t_bug ); 104 105 $t_issue_data['description'] = $t_bug->description; 106 $t_issue_data['steps_to_reproduce'] = mci_null_if_empty( $t_bug->steps_to_reproduce ); 107 $t_issue_data['additional_information'] = mci_null_if_empty( $t_bug->additional_information ); 108 109 $t_issue_data['attachments'] = mci_issue_get_attachments( $p_issue_id ); 110 $t_issue_data['relationships'] = mci_issue_get_relationships( $p_issue_id, $t_user_id ); 111 $t_issue_data['notes'] = mci_issue_get_notes( $p_issue_id ); 112 $t_issue_data['custom_fields'] = mci_issue_get_custom_fields( $p_issue_id ); 113 $t_issue_data['monitors'] = mci_account_get_array_by_ids( bug_get_monitors ( $p_issue_id ) ); 114 115 return $t_issue_data; 116 } 117 118 /** 119 * Returns the category name, possibly null if no category is assigned 120 * 121 * @param int $p_category_id 122 * @return string 123 */ 124 function mci_get_category( $p_category_id ) { 125 if ( $p_category_id == 0 ) 126 return ''; 127 128 return mci_null_if_empty( category_get_name( $p_category_id ) ); 129 } 130 131 /** 132 * 133 * @param BugData $bug 134 * @return soapval the value to be encoded as the due date 135 */ 136 function mci_issue_get_due_date( $p_bug ) { 137 if ( access_has_bug_level( config_get( 'due_date_view_threshold' ), $p_bug->id ) && !date_is_null( $p_bug->due_date ) ) { 138 return new soapval( 'due_date', 'xsd:dateTime', timestamp_to_iso8601( $p_bug->due_date ) ); 139 } else { 140 return new soapval( 'due_date','xsd:dateTime', null ); 141 } 142 143 } 144 145 /** 146 * Sets the supplied array of custom field values to the specified issue id. 147 * 148 * @param $p_issue_id Issue id to apply custom field values to. 149 * @param $p_custom_fields The array of custom field values as described in the webservice complex types. 150 * @param boolean $p_log_insert create history logs for new values 151 */ 152 function mci_issue_set_custom_fields( $p_issue_id, &$p_custom_fields, $p_log_insert ) { 153 # set custom field values on the submitted issue 154 if( isset( $p_custom_fields ) && is_array( $p_custom_fields ) ) { 155 foreach( $p_custom_fields as $t_custom_field ) { 156 # get custom field id from object ref 157 $t_custom_field_id = mci_get_custom_field_id_from_objectref( $t_custom_field['field'] ); 158 159 if( $t_custom_field_id == 0 ) { 160 return new soap_fault( 'Client', '', 'Custom field ' . $t_custom_field['field']['name'] . ' not found.' ); 161 } 162 163 # skip if current user doesn't have login access. 164 if( !custom_field_has_write_access( $t_custom_field_id, $p_issue_id ) ) { 165 continue; 166 } 167 168 $t_value = $t_custom_field['value']; 169 170 if( !custom_field_validate( $t_custom_field_id, $t_value ) ) { 171 return new soap_fault( 'Client', '', 'Invalid custom field value for field id ' . $t_custom_field_id . ' .'); 172 } 173 174 if( !custom_field_set_value( $t_custom_field_id, $p_issue_id, $t_value, $p_log_insert ) ) { 175 return new soap_fault( 'Server', '', 'Unable to set custom field value for field id ' . $t_custom_field_id . ' to issue ' . $p_issue_id. ' .' ); 176 } 177 } 178 } 179 } 180 181 /** 182 * Get the custom field values associated with the specified issue id. 183 * 184 * @param $p_issue_id Issue id to get the custom field values for. 185 * 186 * @return null if no custom field defined for the project that contains the issue, or if no custom 187 * fields are accessible to the current user. 188 */ 189 function mci_issue_get_custom_fields( $p_issue_id ) { 190 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 191 192 $t_custom_fields = array(); 193 $t_related_custom_field_ids = custom_field_get_linked_ids( $t_project_id ); 194 195 foreach( $t_related_custom_field_ids as $t_id ) { 196 $t_def = custom_field_get_definition( $t_id ); 197 198 if( custom_field_has_read_access( $t_id, $p_issue_id ) ) { 199 200 # user has not access to read this custom field. 201 $t_value = custom_field_get_value( $t_id, $p_issue_id ); 202 if( $t_value === false ) { 203 continue; 204 } 205 206 # return a blank string if the custom field value is undefined 207 if( $t_value === null ) { 208 $t_value = ''; 209 } 210 211 $t_custom_field_value = array(); 212 $t_custom_field_value['field'] = array(); 213 $t_custom_field_value['field']['id'] = $t_id; 214 $t_custom_field_value['field']['name'] = $t_def['name']; 215 $t_custom_field_value['value'] = $t_value; 216 217 $t_custom_fields[] = $t_custom_field_value; 218 } 219 } 220 221 # foreach 222 223 return( count( $t_custom_fields ) == 0 ? null : $t_custom_fields ); 224 } 225 226 /** 227 * Get the attachments of an issue. 228 * 229 * @param integer $p_issue_id The id of the issue to retrieve the attachments for 230 * @return Array that represents an AttachmentData structure 231 */ 232 function mci_issue_get_attachments( $p_issue_id ) { 233 $t_attachment_rows = bug_get_attachments( $p_issue_id ); 234 235 if ( $t_attachment_rows == null) { 236 return array(); 237 } 238 239 $t_result = array(); 240 foreach( $t_attachment_rows as $t_attachment_row ) { 241 if ( !file_can_view_bug_attachments( $p_issue_id, (int)$t_attachment_row['user_id'] ) ) { 242 continue; 243 } 244 $t_attachment = array(); 245 $t_attachment['id'] = $t_attachment_row['id']; 246 $t_attachment['filename'] = $t_attachment_row['filename']; 247 $t_attachment['size'] = $t_attachment_row['filesize']; 248 $t_attachment['content_type'] = $t_attachment_row['file_type']; 249 $t_attachment['date_submitted'] = timestamp_to_iso8601( $t_attachment_row['date_added'] ); 250 $t_attachment['download_url'] = mci_get_mantis_path() . 'file_download.php?file_id=' . $t_attachment_row['id'] . '&type=bug'; 251 $t_attachment['user_id'] = $t_attachment_row['user_id']; 252 $t_result[] = $t_attachment; 253 } 254 255 return $t_result; 256 } 257 258 /** 259 * Get the relationships of an issue. 260 * 261 * @param integer $p_issue_id The id of the issue to retrieve the relationships for 262 * @return Array that represents an RelationShipData structure 263 */ 264 function mci_issue_get_relationships( $p_issue_id, $p_user_id ) { 265 $t_relationships = array(); 266 267 $t_src_relationships = relationship_get_all_src( $p_issue_id ); 268 foreach( $t_src_relationships as $t_relship_row ) { 269 if( access_has_bug_level( config_get( 'mc_readonly_access_level_threshold' ), $t_relship_row->dest_bug_id, $p_user_id ) ) { 270 $t_relationship = array(); 271 $t_reltype = array(); 272 $t_relationship['id'] = $t_relship_row->id; 273 $t_reltype['id'] = $t_relship_row->type; 274 $t_reltype['name'] = relationship_get_description_src_side( $t_relship_row->type ); 275 $t_relationship['type'] = $t_reltype; 276 $t_relationship['target_id'] = $t_relship_row->dest_bug_id; 277 $t_relationships[] = $t_relationship; 278 } 279 } 280 281 $t_dest_relationships = relationship_get_all_dest( $p_issue_id ); 282 foreach( $t_dest_relationships as $t_relship_row ) { 283 if( access_has_bug_level( config_get( 'mc_readonly_access_level_threshold' ), $t_relship_row->src_bug_id, $p_user_id ) ) { 284 $t_relationship = array(); 285 $t_relationship['id'] = $t_relship_row->id; 286 $t_reltype = array(); 287 $t_reltype['id'] = relationship_get_complementary_type( $t_relship_row->type ); 288 $t_reltype['name'] = relationship_get_description_dest_side( $t_relship_row->type ); 289 $t_relationship['type'] = $t_reltype; 290 $t_relationship['target_id'] = $t_relship_row->src_bug_id; 291 $t_relationships[] = $t_relationship; 292 } 293 } 294 295 return (count( $t_relationships ) == 0 ? null : $t_relationships ); 296 } 297 298 /** 299 * Get all visible notes for a specific issue 300 * 301 * @param integer $p_issue_id The id of the issue to retrieve the notes for 302 * @return Array that represents an IssueNoteData structure 303 */ 304 function mci_issue_get_notes( $p_issue_id ) { 305 $t_user_id = auth_get_current_user_id(); 306 $t_lang = mci_get_user_lang( $t_user_id ); 307 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 308 $t_user_bugnote_order = 'ASC'; // always get the notes in ascending order for consistency to the calling application. 309 $t_has_time_tracking_access = access_has_bug_level( config_get( 'time_tracking_view_threshold' ), $p_issue_id ); 310 311 $t_result = array(); 312 foreach( bugnote_get_all_visible_bugnotes( $p_issue_id, $t_user_bugnote_order, 0 ) as $t_value ) { 313 $t_bugnote = array(); 314 $t_bugnote['id'] = $t_value->id; 315 $t_bugnote['reporter'] = mci_account_get_array_by_id( $t_value->reporter_id ); 316 $t_bugnote['date_submitted'] = timestamp_to_iso8601( $t_value->date_submitted ); 317 $t_bugnote['last_modified'] = timestamp_to_iso8601( $t_value->last_modified ); 318 $t_bugnote['text'] = $t_value->note; 319 $t_bugnote['view_state'] = mci_enum_get_array_by_id( $t_value->view_state, 'view_state', $t_lang ); 320 $t_bugnote['time_tracking'] = $t_has_time_tracking_access ? $t_value->time_tracking : 0; 321 $t_bugnote['note_type'] = $t_value->note_type; 322 $t_bugnote['note_attr'] = $t_value->note_attr; 323 324 $t_result[] = $t_bugnote; 325 } 326 327 return (count( $t_result ) == 0 ? null : $t_result ); 328 } 329 330 /** 331 * Sets the monitors of the specified issue 332 * 333 * <p>This functions performs access level checks and only performs operations which would 334 * modify the existing monitors list.</p> 335 * 336 * @param int $p_issue_id the issue id to set the monitors for 337 * @param int $p_user_id the user which requests the monitor change 338 * @param array $p_monitors An array of arrays with the <em>id</em> field set to the id 339 * of the users which should monitor this issue. 340 */ 341 function mci_issue_set_monitors( $p_issue_id , $p_user_id, $p_monitors ) { 342 343 $t_existing_monitors = bug_get_monitors( $p_issue_id ); 344 345 $t_monitors = array(); 346 foreach ( $p_monitors as $t_monitor ) 347 $t_monitors[] = $t_monitor['id']; 348 349 foreach ( $t_monitors as $t_user_id ) { 350 351 if ( $p_user_id == $t_user_id ) { 352 if ( ! access_has_bug_level( config_get( 'monitor_bug_threshold' ), $p_issue_id ) ) 353 continue; 354 } else { 355 if ( !access_has_bug_level( config_get( 'monitor_add_others_bug_threshold' ), $p_issue_id ) ) 356 continue; 357 } 358 359 if ( in_array( $p_user_id, $t_existing_monitors) ) 360 continue; 361 362 bug_monitor( $p_issue_id, $t_user_id); 363 } 364 365 foreach ( $t_existing_monitors as $t_user_id ) { 366 367 if ( $p_user_id == $t_user_id ) { 368 if ( ! access_has_bug_level( config_get( 'monitor_bug_threshold' ), $p_issue_id ) ) 369 continue; 370 } else { 371 if ( !access_has_bug_level( config_get( 'monitor_delete_others_bug_threshold' ), $p_issue_id ) ) 372 continue; 373 } 374 375 if ( in_array( $p_user_id, $t_monitors) ) 376 continue; 377 378 bug_unmonitor( $p_issue_id, $t_user_id); 379 } 380 } 381 382 /** 383 * Get the biggest issue id currently used. 384 * 385 * @param string $p_username The name of the user trying to retrieve the information 386 * @param string $p_password The password of the user. 387 * @param int $p_project_id -1 default project, 0 for all projects, otherwise project id. 388 * @return integer The biggest used issue id. 389 */ 390 function mc_issue_get_biggest_id( $p_username, $p_password, $p_project_id ) { 391 $t_user_id = mci_check_login( $p_username, $p_password ); 392 if( $t_user_id === false ) { 393 return mci_soap_fault_login_failed(); 394 } 395 396 $t_any = defined( 'META_FILTER_ANY' ) ? META_FILTER_ANY : 'any'; 397 $t_none = defined( 'META_FILTER_NONE' ) ? META_FILTER_NONE : 'none'; 398 399 $t_filter = array( 400 'category_id' => Array( 401 '0' => $t_any, 402 ), 403 'severity' => Array( 404 '0' => $t_any, 405 ), 406 'status' => Array( 407 '0' => $t_any, 408 ), 409 'highlight_changed' => 0, 410 'reporter_id' => Array( 411 '0' => $t_any, 412 ), 413 'handler_id' => Array( 414 '0' => $t_any, 415 ), 416 'resolution' => Array( 417 '0' => $t_any, 418 ), 419 'build' => Array( 420 '0' => $t_any, 421 ), 422 'version' => Array( 423 '0' => $t_any, 424 ), 425 'hide_status' => Array( 426 '0' => $t_none, 427 ), 428 'monitor_user_id' => Array( 429 '0' => $t_any, 430 ), 431 'dir' => 'DESC', 432 'sort' => 'id', 433 ); 434 435 $t_page_number = 1; 436 $t_per_page = 1; 437 $t_bug_count = 0; 438 $t_page_count = 0; 439 440 # Get project id, if -1, then retrieve the current which will be the default since there is no cookie. 441 $t_project_id = $p_project_id; 442 if( $t_project_id == -1 ) { 443 $t_project_id = helper_get_current_project(); 444 } 445 446 if(( $t_project_id > 0 ) && !project_exists( $t_project_id ) ) { 447 return new soap_fault( 'Client', '', "Project '$t_project_id' does not exist." ); 448 } 449 450 if( !mci_has_readonly_access( $t_user_id, $t_project_id ) ) { 451 return mci_soap_fault_access_denied( $t_user_id ); 452 } 453 454 $t_rows = filter_get_bug_rows( $t_page_number, $t_per_page, $t_page_count, $t_bug_count, $t_filter, $t_project_id, $t_user_id ); 455 if( count( $t_rows ) == 0 ) { 456 return 0; 457 } else { 458 return $t_rows[0]->id; 459 } 460 } 461 462 /** 463 * Get the id of an issue via the issue's summary. 464 * 465 * @param string $p_username The name of the user trying to delete the issue. 466 * @param string $p_password The password of the user. 467 * @param string $p_summary The summary of the issue to retrieve. 468 * @return integer The id of the issue with the given summary, 0 if there is no such issue. 469 */ 470 function mc_issue_get_id_from_summary( $p_username, $p_password, $p_summary ) { 471 $t_user_id = mci_check_login( $p_username, $p_password ); 472 if( $t_user_id === false ) { 473 return mci_soap_fault_login_failed(); 474 } 475 476 $t_bug_table = db_get_table( 'bug' ); 477 478 $query = "SELECT id 479 FROM $t_bug_table 480 WHERE summary = " . db_param(); 481 482 $result = db_query_bound( $query, Array( $p_summary ), 1 ); 483 484 if( db_num_rows( $result ) == 0 ) { 485 return 0; 486 } else { 487 while(( $row = db_fetch_array( $result ) ) !== false ) { 488 $t_issue_id = (int) $row['id']; 489 $t_project_id = bug_get_field( $t_issue_id, 'project_id' ); 490 491 if( mci_has_readonly_access( $t_user_id, $t_project_id ) ) { 492 return $t_issue_id; 493 } 494 } 495 496 // no issue found that belongs to a project that the user has read access to. 497 return 0; 498 } 499 } 500 501 /** 502 * Add an issue to the database. 503 * 504 * @param string $p_username The name of the user trying to add the issue. 505 * @param string $p_password The password of the user. 506 * @param Array $p_issue A IssueData structure containing information about the new issue. 507 * @return integer The id of the created issue. 508 */ 509 function mc_issue_add( $p_username, $p_password, $p_issue ) { 510 $t_user_id = mci_check_login( $p_username, $p_password ); 511 if( $t_user_id === false ) { 512 return mci_soap_fault_login_failed(); 513 } 514 515 $t_project = $p_issue['project']; 516 517 $t_project_id = mci_get_project_id( $t_project ); 518 519 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 520 return mci_soap_fault_access_denied( $t_user_id ); 521 } 522 523 $t_handler_id = isset( $p_issue['handler'] ) ? mci_get_user_id( $p_issue['handler'] ) : 0; 524 $t_priority_id = isset( $p_issue['priority'] ) ? mci_get_priority_id( $p_issue['priority'] ) : config_get( 'default_bug_priority' ); 525 $t_severity_id = isset( $p_issue['severity'] ) ? mci_get_severity_id( $p_issue['severity'] ) : config_get( 'default_bug_severity' ); 526 $t_status_id = isset( $p_issue['status'] ) ? mci_get_status_id( $p_issue['status'] ) : config_get( 'bug_submit_status' ); 527 $t_reproducibility_id = isset( $p_issue['reproducibility'] ) ? mci_get_reproducibility_id( $p_issue['reproducibility'] ) : config_get( 'default_bug_reproducibility' ); 528 $t_resolution_id = isset( $p_issue['resolution'] ) ? mci_get_resolution_id( $p_issue['resolution'] ) : config_get('default_bug_resolution'); 529 $t_projection_id = isset( $p_issue['projection'] ) ? mci_get_projection_id( $p_issue['projection'] ) : config_get('default_bug_resolution'); 530 $t_eta_id = isset( $p_issue['eta'] ) ? mci_get_eta_id( $p_issue['eta'] ) : config_get('default_bug_eta'); 531 $t_view_state_id = isset( $p_issue['view_state'] ) ? mci_get_view_state_id( $p_issue['view_state'] ) : config_get( 'default_bug_view_status' ); 532 $t_reporter_id = isset( $p_issue['reporter'] ) ? mci_get_user_id( $p_issue['reporter'] ) : 0; 533 $t_summary = $p_issue['summary']; 534 $t_description = $p_issue['description']; 535 $t_notes = isset( $p_issue['notes'] ) ? $p_issue['notes'] : array(); 536 537 if( $t_reporter_id == 0 ) { 538 $t_reporter_id = $t_user_id; 539 } else { 540 if( $t_reporter_id != $t_user_id ) { 541 542 # Make sure that active user has access level required to specify a different reporter. 543 $t_specify_reporter_access_level = config_get( 'mc_specify_reporter_on_add_access_level_threshold' ); 544 if( !access_has_project_level( $t_specify_reporter_access_level, $t_project_id, $t_user_id ) ) { 545 return mci_soap_fault_access_denied( $t_user_id, "Active user does not have access level required to specify a different issue reporter" ); 546 } 547 } 548 } 549 550 if(( $t_project_id == 0 ) || !project_exists( $t_project_id ) ) { 551 if( $t_project_id == 0 ) { 552 return new soap_fault( 'Client', '', "Project '" . $t_project['name'] . "' does not exist." ); 553 } else { 554 return new soap_fault( 'Client', '', "Project with id '" . $t_project_id . "' does not exist." ); 555 } 556 } 557 558 if( !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id, $t_user_id ) ) { 559 return mci_soap_fault_access_denied( "User '$t_user_id' does not have access right to report issues" ); 560 } 561 562 #if ( !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id ) || 563 # !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id, $v_reporter ) ) { 564 # return new soap_fault( 'Client', '', "User does not have access right to report issues." ); 565 #} 566 567 if(( $t_handler_id != 0 ) && !user_exists( $t_handler_id ) ) { 568 return new soap_fault( 'Client', '', "User '$t_handler_id' does not exist." ); 569 } 570 571 $t_category = isset ( $p_issue['category'] ) ? $p_issue['category'] : null; 572 573 $t_category_id = translate_category_name_to_id( $t_category, $t_project_id ); 574 if ( $t_category_id == 0 && !config_get( 'allow_no_category' ) ) { 575 if ( !isset( $p_issue['category'] ) || is_blank( $p_issue['category'] ) ) { 576 return new soap_fault( 'Client', '', "Category field must be supplied." ); 577 } else { 578 return new soap_fault( 'Client', '', "Category '" . $p_issue['category'] . "' not found for project '$t_project_id'." ); 579 } 580 } 581 582 if ( isset( $p_issue['version'] ) && !is_blank( $p_issue['version'] ) && !version_get_id( $p_issue['version'], $t_project_id ) ) { 583 $t_version = $p_issue['version']; 584 585 $t_error_when_version_not_found = config_get( 'mc_error_when_version_not_found' ); 586 if( $t_error_when_version_not_found == ON ) { 587 $t_project_name = project_get_name( $t_project_id ); 588 return new soap_fault( 'Client', '', "Version '$t_version' does not exist in project '$t_project_name'." ); 589 } else { 590 $t_version_when_not_found = config_get( 'mc_version_when_not_found' ); 591 $t_version = $t_version_when_not_found; 592 } 593 } 594 595 if ( is_blank( $t_summary ) ) { 596 return new soap_fault( 'Client', '', "Mandatory field 'summary' is missing." ); 597 } 598 599 if ( is_blank( $t_description ) ) { 600 return new soap_fault( 'Client', '', "Mandatory field 'description' is missing." ); 601 } 602 603 $t_bug_data = new BugData; 604 $t_bug_data->profile_id = 0; 605 $t_bug_data->project_id = $t_project_id; 606 $t_bug_data->reporter_id = $t_reporter_id; 607 $t_bug_data->handler_id = $t_handler_id; 608 $t_bug_data->priority = $t_priority_id; 609 $t_bug_data->severity = $t_severity_id; 610 $t_bug_data->reproducibility = $t_reproducibility_id; 611 $t_bug_data->status = $t_status_id; 612 $t_bug_data->resolution = $t_resolution_id; 613 $t_bug_data->projection = $t_projection_id; 614 $t_bug_data->category_id = $t_category_id; 615 $t_bug_data->date_submitted = isset( $p_issue['date_submitted'] ) ? $p_issue['date_submitted'] : ''; 616 $t_bug_data->last_updated = isset( $p_issue['last_updated'] ) ? $p_issue['last_updated'] : ''; 617 $t_bug_data->eta = $t_eta_id; 618 $t_bug_data->os = isset( $p_issue['os'] ) ? $p_issue['os'] : ''; 619 $t_bug_data->os_build = isset( $p_issue['os_build'] ) ? $p_issue['os_build'] : ''; 620 $t_bug_data->platform = isset( $p_issue['platform'] ) ? $p_issue['platform'] : ''; 621 $t_bug_data->version = isset( $p_issue['version'] ) ? $p_issue['version'] : ''; 622 $t_bug_data->fixed_in_version = isset( $p_issue['fixed_in_version'] ) ? $p_issue['fixed_in_version'] : ''; 623 $t_bug_data->build = isset( $p_issue['build'] ) ? $p_issue['build'] : ''; 624 $t_bug_data->view_state = $t_view_state_id; 625 $t_bug_data->summary = $t_summary; 626 $t_bug_data->sponsorship_total = isset( $p_issue['sponsorship_total'] ) ? $p_issue['sponsorship_total'] : 0; 627 628 if ( isset( $p_issue['due_date'] ) && access_has_global_level( config_get( 'due_date_update_threshold' ) ) ) { 629 $t_bug_data->due_date = mci_iso8601_to_timestamp( $p_issue['due_date'] ); 630 } else { 631 $t_bug_data->due_date = date_get_null(); 632 } 633 634 if( access_has_project_level( config_get( 'roadmap_update_threshold' ), $t_bug_data->project_id, $t_user_id ) ) { 635 $t_bug_data->target_version = isset( $p_issue['target_version'] ) ? $p_issue['target_version'] : ''; 636 } 637 638 # omitted: 639 # var $bug_text_id 640 # $t_bug_data->profile_id; 641 # extended info 642 $t_bug_data->description = $t_description; 643 $t_bug_data->steps_to_reproduce = isset( $p_issue['steps_to_reproduce'] ) ? $p_issue['steps_to_reproduce'] : ''; 644 $t_bug_data->additional_information = isset( $p_issue['additional_information'] ) ? $p_issue['additional_information'] : ''; 645 646 # submit the issue 647 $t_issue_id = $t_bug_data->create(); 648 649 mci_issue_set_custom_fields( $t_issue_id, $p_issue['custom_fields'], false ); 650 if ( isset ( $p_issue['monitors'] ) ) 651 mci_issue_set_monitors( $t_issue_id , $t_user_id, $p_issue['monitors'] ); 652 653 if( isset( $t_notes ) && is_array( $t_notes ) ) { 654 foreach( $t_notes as $t_note ) { 655 if( isset( $t_note['view_state'] ) ) { 656 $t_view_state = $t_note['view_state']; 657 } else { 658 $t_view_state = config_get( 'default_bugnote_view_status' ); 659 } 660 661 $note_type = isset ( $t_note['note_type'] ) ? (int) $t_note['note_type'] : BUGNOTE; 662 $note_attr = isset ( $t_note['note_type'] ) ? $t_note['note_attr'] : ''; 663 664 $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); 665 bugnote_add( $t_issue_id, $t_note['text'], mci_get_time_tracking_from_note( $t_issue_id, $t_note ), $t_view_state_id == VS_PRIVATE, $note_type, $note_attr, $t_user_id, FALSE ); 666 } 667 } 668 669 email_new_bug( $t_issue_id ); 670 671 return $t_issue_id; 672 } 673 674 /** 675 * Update Issue in database 676 * 677 * Created By KGB 678 * @param string $p_username The name of the user trying to add the issue. 679 * @param string $p_password The password of the user. 680 * @param Array $p_issue A IssueData structure containing information about the new issue. 681 * @return integer The id of the created issue. 682 */ 683 function mc_issue_update( $p_username, $p_password, $p_issue_id, $p_issue ) { 684 $t_user_id = mci_check_login( $p_username, $p_password ); 685 if( $t_user_id === false ) { 686 return mci_soap_fault_login_failed(); 687 } 688 689 if( !bug_exists( $p_issue_id ) ) { 690 return new soap_fault( 'Client', '', "Issue '$p_issue_id' does not exist." ); 691 } 692 693 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 694 695 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 696 return mci_soap_fault_access_denied( $t_user_id ); 697 } 698 699 $t_project_id = mci_get_project_id( $p_issue['project'] ); 700 $t_reporter_id = isset( $p_issue['reporter'] ) ? mci_get_user_id( $p_issue['reporter'] ) : $t_user_id ; 701 $t_handler_id = isset( $p_issue['handler'] ) ? mci_get_user_id( $p_issue['handler'] ) : 0; 702 $t_project = $p_issue['project']; 703 $t_summary = isset( $p_issue['summary'] ) ? $p_issue['summary'] : ''; 704 $t_description = isset( $p_issue['description'] ) ? $p_issue['description'] : ''; 705 706 707 if(( $t_project_id == 0 ) || !project_exists( $t_project_id ) ) { 708 if( $t_project_id == 0 ) { 709 return new soap_fault( 'Client', '', "Project '" . $t_project['name'] . "' does not exist." ); 710 } 711 return new soap_fault( 'Client', '', "Project '$t_project_id' does not exist." ); 712 } 713 714 if( !access_has_bug_level( config_get( 'update_bug_threshold' ), $p_issue_id, $t_user_id ) ) { 715 return mci_soap_fault_access_denied( $t_user_id, "Not enough rights to update issues" ); 716 } 717 718 if(( $t_handler_id != 0 ) && !user_exists( $t_handler_id ) ) { 719 return new soap_fault( 'Client', '', "User '$t_handler_id' does not exist." ); 720 } 721 722 $t_category = isset ( $p_issue['category'] ) ? $p_issue['category'] : null; 723 724 $t_category_id = translate_category_name_to_id( $t_category, $t_project_id ); 725 if ( $t_category_id == 0 && !config_get( 'allow_no_category' ) ) { 726 if ( isset( $p_issue['category'] ) && !is_blank( $p_issue['category'] ) ) { 727 return new soap_fault( 'Client', '', "Category field must be supplied." ); 728 } else { 729 return new soap_fault( 'Client', '', "Category '" . $p_issue['category'] . "' not found for project '$t_project_name'." ); 730 } 731 } 732 733 if ( isset( $p_issue['version'] ) && !is_blank( $p_issue['version'] ) && !version_get_id( $p_issue['version'], $t_project_id ) ) { 734 $t_error_when_version_not_found = config_get( 'mc_error_when_version_not_found' ); 735 if( $t_error_when_version_not_found == ON ) { 736 $t_project_name = project_get_name( $t_project_id ); 737 return new soap_fault( 'Client', '', "Version '" . $p_issue['version'] . "' does not exist in project '$t_project_name'." ); 738 } else { 739 $t_version_when_not_found = config_get( 'mc_version_when_not_found' ); 740 $p_issue['version'] = $t_version_when_not_found; 741 } 742 } 743 744 if ( is_blank( $t_summary ) ) { 745 return new soap_fault( 'Client', '', "Mandatory field 'summary' is missing." ); 746 } 747 748 if ( is_blank( $t_description ) ) { 749 return new soap_fault( 'Client', '', "Mandatory field 'description' is missing." ); 750 } 751 752 // fields which we expect to always be set 753 $t_bug_data = bug_get( $p_issue_id, true ); 754 $t_bug_data->project_id = $t_project_id; 755 $t_bug_data->reporter_id = $t_reporter_id; 756 $t_bug_data->handler_id = $t_handler_id; 757 $t_bug_data->category_id = $t_category_id; 758 $t_bug_data->summary = $t_summary; 759 $t_bug_data->description = $t_description; 760 761 // fields which might not be set 762 if ( isset ( $p_issue['steps_to_reproduce'] ) ) 763 $t_bug_data->steps_to_reproduce = $p_issue['steps_to_reproduce']; 764 if ( isset ( $p_issue['additional_information'] ) ) 765 $t_bug_data->additional_information = $p_issue['additional_information']; 766 if ( isset( $p_issue['priority'] ) ) 767 $t_bug_data->priority = mci_get_priority_id( $p_issue['priority'] ); 768 if ( isset( $p_issue['severity'] ) ) 769 $t_bug_data->severity = mci_get_severity_id( $p_issue['severity'] ); 770 if ( isset( $p_issue['status'] ) ) 771 $t_bug_data->status = mci_get_status_id ( $p_issue['status'] ); 772 if ( isset ( $p_issue['reproducibility'] ) ) 773 $t_bug_data->reproducibility = mci_get_reproducibility_id( $p_issue['reproducibility'] ); 774 if ( isset ( $p_issue['resolution'] ) ) 775 $t_bug_data->resolution = mci_get_resolution_id( $p_issue['resolution'] ); 776 if ( isset ( $p_issue['projection'] ) ) 777 $t_bug_data->projection = mci_get_projection_id( $p_issue['projection'] ); 778 if ( isset ( $p_issue['eta'] ) ) 779 $t_bug_data->eta = mci_get_eta_id( $p_issue['eta'] ); 780 if ( isset ( $p_issue['view_state'] ) ) 781 $t_bug_data->view_state = mci_get_view_state_id( $p_issue['view_state'] ); 782 if ( isset ( $p_issue['date_submitted'] ) ) 783 $t_bug_data->date_submitted = $p_issue['date_submitted']; 784 if ( isset ( $p_issue['date_updated'] ) ) 785 $t_bug_data->last_updated = $p_issue['last_updated']; 786 if ( isset ( $p_issue['os'] ) ) 787 $t_bug_data->os = $p_issue['os']; 788 if ( isset ( $p_issue['os_build'] ) ) 789 $t_bug_data->os_build = $p_issue['os_build']; 790 if ( isset ( $p_issue['build'] ) ) 791 $t_bug_data->build = $p_issue['build']; 792 if ( isset ( $p_issue['platform'] ) ) 793 $t_bug_data->platform = $p_issue['platform']; 794 if ( isset ( $p_issue['version'] ) ) 795 $t_bug_data->version = $p_issue['version']; 796 if ( isset ( $p_issue['fixed_in_version'] ) ) 797 $t_bug_data->fixed_in_version = $p_issue['fixed_in_version']; 798 799 if ( isset( $p_issue['due_date'] ) && access_has_global_level( config_get( 'due_date_update_threshold' ) ) ) { 800 $t_bug_data->due_date = mci_iso8601_to_timestamp( $p_issue['due_date'] ); 801 } else { 802 $t_bug_data->due_date = date_get_null(); 803 } 804 805 if( access_has_project_level( config_get( 'roadmap_update_threshold' ), $t_bug_data->project_id, $t_user_id ) ) { 806 $t_bug_data->target_version = isset( $p_issue['target_version'] ) ? $p_issue['target_version'] : ''; 807 } 808 809 810 # submit the issue 811 $t_is_success = $t_bug_data->update( /* update_extended */ true, /* bypass_email */ true ); 812 813 mci_issue_set_custom_fields( $p_issue_id, $p_issue['custom_fields'], true ); 814 if ( isset ( $p_issue['monitors'] ) ) 815 mci_issue_set_monitors( $p_issue_id , $t_user_id, $p_issue['monitors'] ); 816 817 if ( isset( $p_issue['notes'] ) && is_array( $p_issue['notes'] ) ) { 818 foreach ( $p_issue['notes'] as $t_note ) { 819 if ( isset( $t_note['view_state'] ) ) { 820 $t_view_state = $t_note['view_state']; 821 } else { 822 $t_view_state = config_get( 'default_bugnote_view_status' ); 823 } 824 825 if ( isset( $t_note['id'] ) && ( (int)$t_note['id'] > 0 ) ) { 826 $t_bugnote_id = (integer)$t_note['id']; 827 828 $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); 829 830 if ( bugnote_exists( $t_bugnote_id ) ) { 831 bugnote_set_text( $t_bugnote_id, $t_note['text'] ); 832 bugnote_set_view_state( $t_bugnote_id, $t_view_state_id == VS_PRIVATE ); 833 $t_eta_id = isset( $p_issue['eta'] ) ? mci_get_eta_id( $p_issue['eta'] ) : config_get('default_bug_eta'); 834 bugnote_date_update( $t_bugnote_id ); 835 if ( isset( $t_note['time_tracking'] ) ) 836 bugnote_set_time_tracking( $t_bugnote_id, mci_get_time_tracking_from_note( $p_issue_id, $t_note ) ); 837 } 838 } else { 839 $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); 840 841 $note_type = isset ( $t_note['note_type'] ) ? (int) $t_note['note_type'] : BUGNOTE; 842 $note_attr = isset ( $t_note['note_type'] ) ? $t_note['note_attr'] : ''; 843 844 bugnote_add( $p_issue_id, $t_note['text'], mci_get_time_tracking_from_note( $p_issue_id, $t_note ), $t_view_state_id == VS_PRIVATE, $note_type, $note_attr, $t_user_id, FALSE ); 845 } 846 } 847 } 848 849 return $t_is_success; 850 } 851 852 /** 853 * Delete the specified issue. 854 * 855 * @param string $p_username The name of the user trying to delete the issue. 856 * @param string $p_password The password of the user. 857 * @param integer $p_issue_id The id of the issue to delete. 858 * @return boolean True if the issue has been deleted successfully, false otherwise. 859 */ 860 function mc_issue_delete( $p_username, $p_password, $p_issue_id ) { 861 $t_user_id = mci_check_login( $p_username, $p_password ); 862 if( $t_user_id === false ) { 863 return mci_soap_fault_login_failed(); 864 } 865 866 if( !bug_exists( $p_issue_id ) ) { 867 return new soap_fault( 'Client', '', "Issue '$p_issue_id' does not exist."); 868 } 869 870 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 871 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 872 return mci_soap_fault_access_denied( $t_user_id ); 873 } 874 875 return bug_delete( $p_issue_id ); 876 } 877 878 /** 879 * Add a note to an existing issue. 880 * 881 * @param string $p_username The name of the user trying to add a note to an issue. 882 * @param string $p_password The password of the user. 883 * @param integer $p_issue_id The id of the issue to add the note to. 884 * @param IssueNoteData $p_note The note to add. 885 * @return integer The id of the added note. 886 */ 887 function mc_issue_note_add( $p_username, $p_password, $p_issue_id, $p_note ) { 888 $t_user_id = mci_check_login( $p_username, $p_password ); 889 if( $t_user_id === false ) { 890 return mci_soap_fault_login_failed(); 891 } 892 893 if( (integer) $p_issue_id < 1 ) { 894 return new soap_fault( 'Client', '', "Invalid issue id '$p_issue_id'" ); 895 } 896 897 if( !bug_exists( $p_issue_id ) ) { 898 return new soap_fault( 'Client', '', "Issue '$p_issue_id' does not exist." ); 899 } 900 901 if ( !isset( $p_note['text'] ) || is_blank( $p_note['text'] ) ) { 902 return new soap_fault( 'Client', '', "Issue note text must not be blank." ); 903 } 904 905 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 906 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 907 return mci_soap_fault_access_denied( $t_user_id ); 908 } 909 910 if( !access_has_bug_level( config_get( 'add_bugnote_threshold' ), $p_issue_id, $t_user_id ) ) { 911 return mci_soap_fault_access_denied( $t_user_id, "You do not have access rights to add notes to this issue" ); 912 } 913 914 if( bug_is_readonly( $p_issue_id ) ) { 915 return mci_soap_fault_access_denied( $t_user_id, "Issue '$p_issue_id' is readonly" ); 916 } 917 918 if( isset( $p_note['view_state'] ) ) { 919 $t_view_state = $p_note['view_state']; 920 } else { 921 $t_view_state = array( 922 'id' => config_get( 'default_bug_view_status' ), 923 ); 924 } 925 926 $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); 927 928 $note_type = isset ( $p_note['note_type'] ) ? (int) $p_note['note_type'] : BUGNOTE; 929 $note_attr = isset ( $p_note['note_type'] ) ? $p_note['note_attr'] : ''; 930 931 return bugnote_add( $p_issue_id, $p_note['text'], mci_get_time_tracking_from_note( $p_issue_id, $p_note ), $t_view_state_id == VS_PRIVATE, $note_type, $note_attr, $t_user_id ); 932 } 933 934 /** 935 * Delete a note given its id. 936 * 937 * @param string $p_username The name of the user trying to add a note to an issue. 938 * @param string $p_password The password of the user. 939 * @param integer $p_issue_note_id The id of the note to be deleted. 940 * @return true: success, false: failure 941 */ 942 function mc_issue_note_delete( $p_username, $p_password, $p_issue_note_id ) { 943 $t_user_id = mci_check_login( $p_username, $p_password ); 944 if( $t_user_id === false ) { 945 return mci_soap_fault_login_failed(); 946 } 947 948 if( (integer) $p_issue_note_id < 1 ) { 949 return new soap_fault( 'Client', '', "Invalid issue note id '$p_issue_note_id'."); 950 } 951 952 if( !bugnote_exists( $p_issue_note_id ) ) { 953 return new soap_fault( 'Client', '', "Issue note '$p_issue_note_id' does not exist."); 954 } 955 956 $t_issue_id = bugnote_get_field( $p_issue_note_id, 'bug_id' ); 957 $t_project_id = bug_get_field( $t_issue_id, 'project_id' ); 958 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 959 return mci_soap_fault_access_denied( $t_user_id ); 960 } 961 962 return bugnote_delete( $p_issue_note_id ); 963 } 964 965 /** 966 * Update a note 967 * 968 * @param string $p_username The name of the user trying to add a note to an issue. 969 * param string $p_password The password of the user. 970 * @param IssueNoteData $p_note The note to update. 971 * @return true on success, false on failure 972 */ 973 function mc_issue_note_update( $p_username, $p_password, $p_note ) { 974 $t_user_id = mci_check_login( $p_username, $p_password ); 975 976 if( $t_user_id === false ) { 977 return mci_soap_fault_login_failed(); 978 } 979 980 if ( !isset( $p_note['id'] ) || is_blank( $p_note['id'] ) ) { 981 return new soap_fault( 'Client', '', "Issue id must not be blank." ); 982 } 983 984 if ( !isset( $p_note['text'] ) || is_blank( $p_note['text'] ) ) { 985 return new soap_fault( 'Client', '', "Issue note text must not be blank." ); 986 } 987 988 $t_issue_note_id = $p_note['id']; 989 990 if( !bugnote_exists( $t_issue_note_id ) ) { 991 return new soap_fault( 'Server', '', "Issue note '$t_issue_note_id' does not exist." ); 992 } 993 994 $t_issue_id = bugnote_get_field( $t_issue_note_id, 'bug_id' ); 995 996 $t_project_id = bug_get_field( $t_issue_id, 'project_id' ); 997 998 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 999 return mci_soap_fault_access_denied( $t_user_id ); 1000 } 1001 1002 if( !access_has_bug_level( config_get( 'add_bugnote_threshold' ), $t_issue_id, $t_user_id ) ) { 1003 return mci_soap_fault_access_denied( $t_user_id, "You do not have access rights to add notes to this issue" ); 1004 } 1005 1006 if( bug_is_readonly( $t_issue_id ) ) { 1007 return mci_soap_fault_access_denied( $t_user_id, "Issue ' . $t_issue_id . ' is readonly" ); 1008 } 1009 1010 if( isset( $p_note['view_state'] )) { 1011 $t_view_state = $p_note['view_state']; 1012 $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); 1013 bugnote_set_view_state( $t_issue_note_id, $t_view_state_id ); 1014 } 1015 1016 bugnote_set_text( $t_issue_note_id, $p_note['text'] ); 1017 1018 return bugnote_date_update( $t_issue_note_id ); 1019 } 1020 1021 /** 1022 * Submit a new relationship. 1023 * 1024 * @param string $p_username The name of the user trying to add a note to an issue. 1025 * @param string $p_password The password of the user. 1026 * @param integer $p_issue_id The id of the issue of the source issue. 1027 * @param RelationshipData $p_relationship The relationship to add. 1028 * @return integer The id of the added relationship. 1029 */ 1030 function mc_issue_relationship_add( $p_username, $p_password, $p_issue_id, $p_relationship ) { 1031 $t_user_id = mci_check_login( $p_username, $p_password ); 1032 $t_dest_issue_id = $p_relationship['target_id']; 1033 $t_rel_type = $p_relationship['type']; 1034 1035 if( $t_user_id === false ) { 1036 return mci_soap_fault_login_failed(); 1037 } 1038 1039 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 1040 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 1041 return mci_soap_fault_access_denied( $t_user_id ); 1042 } 1043 1044 # user has access to update the bug... 1045 if( !access_has_bug_level( config_get( 'update_bug_threshold' ), $p_issue_id, $t_user_id ) ) { 1046 return mci_soap_fault_access_denied( $t_user_id, "Active user does not have access level required to add a relationship to this issue" ); 1047 } 1048 1049 # source and destination bugs are the same bug... 1050 if( $p_issue_id == $t_dest_issue_id ) { 1051 return new soap_fault( 'Client', '', "An issue can't be related to itself." ); 1052 } 1053 1054 # the related bug exists... 1055 if( !bug_exists( $t_dest_issue_id ) ) { 1056 return new soap_fault( 'Client', '', "Issue '$t_dest_issue_id' not found." ); 1057 } 1058 1059 # bug is not read-only... 1060 if( bug_is_readonly( $p_issue_id ) ) { 1061 return new mci_soap_fault_access_denied( $t_user_id, "Issue '$p_issue_id' is readonly" ); 1062 } 1063 1064 # user can access to the related bug at least as viewer... 1065 if( !access_has_bug_level( VIEWER, $t_dest_issue_id, $t_user_id ) ) { 1066 return mci_soap_fault_access_denied( $t_user_id, "The issue '$t_dest_issue_id' requires higher access level" ); 1067 } 1068 1069 $t_old_id_relationship = relationship_same_type_exists( $p_issue_id, $t_dest_issue_id, $t_rel_type['id'] ); 1070 1071 if( $t_old_id_relationship == 0 ) { 1072 relationship_add( $p_issue_id, $t_dest_issue_id, $t_rel_type['id'] ); 1073 1074 // The above function call into MantisBT does not seem to return a valid BugRelationshipData object. 1075 // So we call db_insert_id in order to find the id of the created relationship. 1076 $t_relationship_id = db_insert_id( db_get_table( 'bug_relationship' ) ); 1077 1078 # Add log line to the history (both bugs) 1079 history_log_event_special( $p_issue_id, BUG_ADD_RELATIONSHIP, $t_rel_type['id'], $t_dest_issue_id ); 1080 history_log_event_special( $t_dest_issue_id, BUG_ADD_RELATIONSHIP, relationship_get_complementary_type( $t_rel_type['id'] ), $p_issue_id ); 1081 1082 # update bug last updated for both bugs 1083 bug_update_date( $p_issue_id ); 1084 bug_update_date( $t_dest_issue_id ); 1085 1086 # send email notification to the users addressed by both the bugs 1087 email_relationship_added( $p_issue_id, $t_dest_issue_id, $t_rel_type['id'] ); 1088 email_relationship_added( $t_dest_issue_id, $p_issue_id, relationship_get_complementary_type( $t_rel_type['id'] ) ); 1089 1090 return $t_relationship_id; 1091 } else { 1092 return new soap_fault( 'Client', '', "Relationship already exists." ); 1093 } 1094 } 1095 1096 /** 1097 * Delete the relationship with the specified target id. 1098 * 1099 * @param string $p_username The name of the user trying to add a note to an issue. 1100 * @param string $p_password The password of the user. 1101 * @param integer $p_issue_id The id of the source issue for the relationship 1102 * @param integer $p_relationship_id The id of relationship to delete. 1103 * @return true: success, false: failure 1104 */ 1105 function mc_issue_relationship_delete( $p_username, $p_password, $p_issue_id, $p_relationship_id ) { 1106 $t_user_id = mci_check_login( $p_username, $p_password ); 1107 1108 if( $t_user_id === false ) { 1109 return mci_soap_fault_login_failed(); 1110 } 1111 1112 $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); 1113 if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { 1114 return mci_soap_fault_access_denied( $t_user_id ); 1115 } 1116 1117 # user has access to update the bug... 1118 if( !access_has_bug_level( config_get( 'update_bug_threshold' ), $p_issue_id, $t_user_id ) ) { 1119 return mci_soap_fault_access_denied( $t_user_id , "Active user does not have access level required to remove a relationship from this issue." ); 1120 } 1121 1122 # bug is not read-only... 1123 if( bug_is_readonly( $p_issue_id ) ) { 1124 return mci_soap_fault_access_denied( $t_user_id , "Issue '$p_issue_id' is readonly." ); 1125 } 1126 1127 # retrieve the destination bug of the relationship 1128 $t_dest_issue_id = relationship_get_linked_bug_id( $p_relationship_id, $p_issue_id ); 1129 1130 # user can access to the related bug at least as viewer, if it's exist... 1131 if( bug_exists( $t_dest_issue_id ) ) { 1132 if( !access_has_bug_level( VIEWER, $t_dest_issue_id, $t_user_id ) ) { 1133 return mci_soap_fault_access_denied( $t_user_id , "The issue '$t_dest_issue_id' requires higher access level." ); 1134 } 1135 } 1136 1137 $t_bug_relationship_data = relationship_get( $p_relationship_id ); 1138 $t_rel_type = $t_bug_relationship_data->type; 1139 1140 # delete relationship from the DB 1141 relationship_delete( $p_relationship_id ); 1142 1143 # update bug last updated 1144 bug_update_date( $p_issue_id ); 1145 bug_update_date ( $t_dest_issue_id ); 1146 1147 # set the rel_type for both bug and dest_bug based on $t_rel_type and on who is the dest bug 1148 if( $p_issue_id == $t_bug_relationship_data->src_bug_id ) { 1149 $t_bug_rel_type = $t_rel_type; 1150 $t_dest_bug_rel_type = relationship_get_complementary_type( $t_rel_type ); 1151 } else { 1152 $t_bug_rel_type = relationship_get_complementary_type( $t_rel_type ); 1153 $t_dest_bug_rel_type = $t_rel_type; 1154 } 1155 1156 # send email and update the history for the src issue 1157 history_log_event_special( $p_issue_id, BUG_DEL_RELATIONSHIP, $t_bug_rel_type, $t_dest_issue_id ); 1158 email_relationship_deleted( $p_issue_id, $t_dest_issue_id, $t_bug_rel_type ); 1159 1160 if( bug_exists( $t_dest_issue_id ) ) { 1161 1162 # send email and update the history for the dest issue 1163 history_log_event_special( $t_dest_issue_id, BUG_DEL_RELATIONSHIP, $t_dest_bug_rel_type, $p_issue_id ); 1164 email_relationship_deleted( $t_dest_issue_id, $p_issue_id, $t_dest_bug_rel_type ); 1165 } 1166 1167 return true; 1168 } 1169 1170 /** 1171 * Returns the date in iso8601 format, with proper timezone offset applied 1172 * 1173 * @param string $p_date the date in iso8601 format 1174 * @return int the timestamp 1175 */ 1176 function mci_iso8601_to_timestamp( $p_date ) { 1177 1178 // retrieve the offset, seems to be lost by nusoap 1179 $t_utc_date = new DateTime( $p_date, new DateTimeZone( 'UTC' ) ); 1180 $t_timezone = new DateTimeZone( date_default_timezone_get() ); 1181 $t_offset = $t_timezone->getOffset( $t_utc_date ); 1182 1183 $t_raw_timestamp = iso8601_to_timestamp( $p_date ); 1184 1185 return $t_raw_timestamp - $t_offset; 1186 1187 } 1188 1189 1190 /** 1191 * Returns an array for SOAP encoding from a BugData object 1192 * 1193 * @param BugData $p_issue_data 1194 * @param int $p_user_id 1195 * @param string $p_lang 1196 * @return array The issue as an array 1197 */ 1198 function mci_issue_data_as_array( $p_issue_data, $p_user_id, $p_lang ) { 1199 1200 $t_id = $p_issue_data->id; 1201 1202 $t_issue = array(); 1203 $t_issue['id'] = $t_id; 1204 $t_issue['view_state'] = mci_enum_get_array_by_id( $p_issue_data->view_state, 'view_state', $p_lang ); 1205 $t_issue['last_updated'] = timestamp_to_iso8601( $p_issue_data->last_updated ); 1206 1207 $t_issue['project'] = mci_project_as_array_by_id( $p_issue_data->project_id ); 1208 $t_issue['category'] = mci_get_category( $p_issue_data->category_id ); 1209 $t_issue['priority'] = mci_enum_get_array_by_id( $p_issue_data->priority, 'priority', $p_lang ); 1210 $t_issue['severity'] = mci_enum_get_array_by_id( $p_issue_data->severity, 'severity', $p_lang ); 1211 $t_issue['status'] = mci_enum_get_array_by_id( $p_issue_data->status, 'status', $p_lang ); 1212 1213 $t_issue['reporter'] = mci_account_get_array_by_id( $p_issue_data->reporter_id ); 1214 $t_issue['summary'] = $p_issue_data->summary; 1215 $t_issue['version'] = mci_null_if_empty( $p_issue_data->version ); 1216 $t_issue['build'] = mci_null_if_empty( $p_issue_data->build ); 1217 $t_issue['platform'] = mci_null_if_empty( $p_issue_data->platform ); 1218 $t_issue['os'] = mci_null_if_empty( $p_issue_data->os ); 1219 $t_issue['os_build'] = mci_null_if_empty( $p_issue_data->os_build ); 1220 $t_issue['reproducibility'] = mci_enum_get_array_by_id( $p_issue_data->reproducibility, 'reproducibility', $p_lang ); 1221 $t_issue['date_submitted'] = timestamp_to_iso8601( $p_issue_data->date_submitted ); 1222 $t_issue['sponsorship_total'] = $p_issue_data->sponsorship_total; 1223 1224 if( !empty( $p_issue_data->handler_id ) ) { 1225 $t_issue['handler'] = mci_account_get_array_by_id( $p_issue_data->handler_id ); 1226 } 1227 $t_issue['projection'] = mci_enum_get_array_by_id( $p_issue_data->projection, 'projection', $p_lang ); 1228 $t_issue['eta'] = mci_enum_get_array_by_id( $p_issue_data->eta, 'eta', $p_lang ); 1229 1230 $t_issue['resolution'] = mci_enum_get_array_by_id( $p_issue_data->resolution, 'resolution', $p_lang ); 1231 $t_issue['fixed_in_version'] = mci_null_if_empty( $p_issue_data->fixed_in_version ); 1232 $t_issue['target_version'] = mci_null_if_empty( $p_issue_data->target_version ); 1233 1234 $t_issue['description'] = bug_get_text_field( $t_id, 'description' ); 1235 1236 $t_steps_to_reproduce = bug_get_text_field( $t_id, 'steps_to_reproduce' ); 1237 $t_issue['steps_to_reproduce'] = mci_null_if_empty( $t_steps_to_reproduce ); 1238 1239 $t_additional_information = bug_get_text_field( $t_id, 'additional_information' ); 1240 $t_issue['additional_information'] = mci_null_if_empty( $t_additional_information ); 1241 1242 $t_issue['attachments'] = mci_issue_get_attachments( $p_issue_data->id ); 1243 $t_issue['relationships'] = mci_issue_get_relationships( $p_issue_data->id, $p_user_id ); 1244 $t_issue['notes'] = mci_issue_get_notes( $p_issue_data->id ); 1245 $t_issue['custom_fields'] = mci_issue_get_custom_fields( $p_issue_data->id ); 1246 1247 return $t_issue; 1248 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |