function addBugNote($p_bug_id, $p_user_id, $p_email, $p_privacy = true) { $t_note = $p_email['subject']; $t_note .= '<br>'; $t_note .= $p_email['message']; bugnote_add($p_bug_id, $t_note, '0:00', false, 0, '', $p_user_id, false); }
function custom_function_default_checkin($p_issue_id, $p_comment, $p_file, $p_new_version, $p_fixed) { if (bug_exists($p_issue_id)) { history_log_event_special($p_issue_id, CHECKIN, $p_file, $p_new_version); bugnote_add($p_issue_id, $p_comment, VS_PRIVATE == config_get('source_control_notes_view_status')); $t_status = config_get('source_control_set_status_to'); if (OFF != $t_status && $p_fixed) { bug_set_field($p_issue_id, 'status', $t_status); bug_set_field($p_issue_id, 'resolution', config_get('source_control_set_resolution_to')); } } }
# Add the relationship relationship_add($t_bug_id, $f_master_bug_id, $f_rel_type); # Add log line to the history (both issues) history_log_event_special($f_master_bug_id, BUG_ADD_RELATIONSHIP, relationship_get_complementary_type($f_rel_type), $t_bug_id); history_log_event_special($t_bug_id, BUG_ADD_RELATIONSHIP, $f_rel_type, $f_master_bug_id); # Send the email notification email_relationship_added($f_master_bug_id, $t_bug_id, relationship_get_complementary_type($f_rel_type)); # update relationship target bug last updated bug_update_date($t_bug_id); } # copy notes from parent if ($f_copy_notes_from_parent) { $t_parent_bugnotes = bugnote_get_all_bugnotes($f_master_bug_id); foreach ($t_parent_bugnotes as $t_parent_bugnote) { $t_private = $t_parent_bugnote->view_state == VS_PRIVATE; bugnote_add($t_bug_id, $t_parent_bugnote->note, $t_parent_bugnote->time_tracking, $t_private, $t_parent_bugnote->note_type, $t_parent_bugnote->note_attr, $t_parent_bugnote->reporter_id, false, 0, 0, false); # Note: we won't trigger mentions in the clone scenario. } } # copy attachments from parent if ($f_copy_attachments_from_parent) { file_copy_attachments($f_master_bug_id, $t_bug_id); } } helper_call_custom_function('issue_create_notify', array($t_bug_id)); # Allow plugins to post-process bug data with the new bug ID event_signal('EVENT_REPORT_BUG', array($t_bug_data, $t_bug_id)); email_bug_added($t_bug_id); # log status and resolution changes if they differ from the default if ($t_bug_data->status != config_get('bug_submit_status')) { history_log_event($t_bug_id, 'status', config_get('bug_submit_status'));
function createBugNote($p_story_id, $p_user_id, $p_note) { $id = bugnote_add($p_story_id, $p_note, null, false, 0, "", $p_user_id, null); return $id; }
# update relationship target bug last updated bug_update_date( $t_bug_id ); } # copy notes from parent if ( $f_copy_notes_from_parent ) { $t_parent_bugnotes = bugnote_get_all_bugnotes( $f_master_bug_id ); foreach ( $t_parent_bugnotes as $t_parent_bugnote ) { $t_private = $t_parent_bugnote->view_state == VS_PRIVATE; bugnote_add( $t_bug_id, $t_parent_bugnote->note, $t_parent_bugnote->time_tracking, $t_private, $t_parent_bugnote->note_type, $t_parent_bugnote->note_attr, $t_parent_bugnote->reporter_id, /* send_email */ FALSE , /* date submitted */ 0, /* date modified */ 0, /* log history */ FALSE); } } # copy attachments from parent if ( $f_copy_attachments_from_parent ) { file_copy_attachments( $f_master_bug_id, $t_bug_id ); } } helper_call_custom_function( 'issue_create_notify', array( $t_bug_id ) ); # Allow plugins to post-process bug data with the new bug ID event_signal( 'EVENT_REPORT_BUG', array( $t_bug_data, $t_bug_id ) );
# Allow a custom function to validate the proposed bug updates. Note that # custom functions are being deprecated in MantisBT. You should migrate to # the new plugin system instead. helper_call_custom_function('issue_update_validate', array($f_bug_id, $t_updated_bug, $t_bug_note->note)); # Allow plugins to validate/modify the update prior to it being committed. $t_updated_bug = event_signal('EVENT_UPDATE_BUG_DATA', $t_updated_bug, $t_existing_bug); # Commit the bug updates to the database. $t_text_field_update_required = $t_existing_bug->description !== $t_updated_bug->description || $t_existing_bug->additional_information !== $t_updated_bug->additional_information || $t_existing_bug->steps_to_reproduce !== $t_updated_bug->steps_to_reproduce; $t_updated_bug->update($t_text_field_update_required, true); # Update custom field values. foreach ($t_custom_fields_to_set as $t_custom_field_to_set) { custom_field_set_value($t_custom_field_to_set['id'], $f_bug_id, $t_custom_field_to_set['value']); } # Add a bug note if there is one. if ($t_bug_note->note || helper_duration_to_minutes($t_bug_note->time_tracking) > 0) { bugnote_add($f_bug_id, $t_bug_note->note, $t_bug_note->time_tracking, $t_bug_note->view_state == VS_PRIVATE, 0, '', null, false); } # Add a duplicate relationship if requested. if ($t_updated_bug->duplicate_id !== 0) { relationship_add($f_bug_id, $t_updated_bug->duplicate_id, BUG_DUPLICATE); history_log_event_special($f_bug_id, BUG_ADD_RELATIONSHIP, BUG_DUPLICATE, $t_updated_bug->duplicate_id); history_log_event_special($t_updated_bug->duplicate_id, BUG_ADD_RELATIONSHIP, BUG_HAS_DUPLICATE, $f_bug_id); if (user_exists($t_existing_bug->reporter_id)) { bug_monitor($f_bug_id, $t_existing_bug->reporter_id); } if (user_exists($t_existing_bug->handler_id)) { bug_monitor($f_bug_id, $t_existing_bug->handler_id); } bug_monitor_copy($f_bug_id, $t_updated_bug->duplicate_id); } event_signal('EVENT_UPDATE_BUG', array($t_existing_bug, $t_updated_bug));
/** * MantisBT Core API's */ require_once 'core.php'; require_once 'bug_api.php'; require_once 'bugnote_api.php'; form_security_validate('bugnote_add'); $f_bug_id = gpc_get_int('bug_id'); $f_private = gpc_get_bool('private'); $f_time_tracking = gpc_get_string('time_tracking', '0:00'); $f_bugnote_text = trim(gpc_get_string('bugnote_text', '')); $t_bug = bug_get($f_bug_id, true); if ($t_bug->project_id != helper_get_current_project()) { # in case the current project is not the same project of the bug we are viewing... # ... override the current project. This to avoid problems with categories and handlers lists etc. $g_project_override = $t_bug->project_id; } if (bug_is_readonly($f_bug_id)) { error_parameters($f_bug_id); trigger_error(ERROR_BUG_READ_ONLY_ACTION_DENIED, ERROR); } access_ensure_bug_level(config_get('add_bugnote_threshold'), $f_bug_id); // We always set the note time to BUGNOTE, and the API will overwrite it with TIME_TRACKING // if $f_time_tracking is not 0 and the time tracking feature is enabled. $t_bugnote_id = bugnote_add($f_bug_id, $f_bugnote_text, $f_time_tracking, $f_private, BUGNOTE); if (!$t_bugnote_id) { error_parameters(lang_get('bugnote')); trigger_error(ERROR_EMPTY_FIELD, ERROR); } form_security_purge('bugnote_add'); print_successful_redirect_to_bug($f_bug_id);
public function process(XMLreader $reader) { //print "\nImportIssue process()\n"; $t_project_id = helper_get_current_project(); // TODO: category_get_id_by_name could work by default on current project $userId = auth_get_current_user_id(); $t_custom_fields = array(); $t_bugnotes = array(); $t_attachments = array(); $depth = $reader->depth; while ($reader->read() && ($reader->depth > $depth || $reader->nodeType != XMLReader::END_ELEMENT)) { if ($reader->nodeType == XMLReader::ELEMENT) { switch ($reader->localName) { case 'reporter': $t_old_id = $reader->getAttribute('id'); $reader->read(); $this->newbug_->reporter_id = $this->get_user_id($reader->value, $userId); //echo "reporter: old id = $t_old_id - new id = {$this->newbug_->reporter_id}\n"; break; case 'handler': $t_old_id = $reader->getAttribute('id'); $reader->read(); $this->newbug_->handler_id = $this->get_user_id($reader->value, $userId); //echo "handler: old id = $t_old_id - new id = {$this->newbug_->handler_id}\n"; break; case 'category': $this->newbug_->category_id = $this->defaultCategory_; if (version_compare(MANTIS_VERSION, '1.2', '>') === true) { $reader->read(); if ($this->keepCategory_) { # Check for the category's existence in the current project # well as its parents (if any) $t_projects_hierarchy = project_hierarchy_inheritance($t_project_id); foreach ($t_projects_hierarchy as $t_project) { $t_category_id = category_get_id_by_name($reader->value, $t_project, false); if ($t_category_id !== false) { $this->newbug_->category_id = $t_category_id; break; } } } // echo "new id = {$this->newbug_->category_id}\n"; } break; case 'eta': case 'priority': case 'projection': case 'reproducibility': case 'resolution': case 'severity': case 'status': case 'view_state': $t_field = $reader->localName; $t_id = $reader->getAttribute('id'); $reader->read(); $t_value = $reader->value; // Here we assume ids have the same meaning in both installations // TODO add a check for customized values $this->newbug_->{$t_field} = $t_id; break; case 'id': $reader->read(); $this->old_id_ = $reader->value; break; case 'project': // ignore original value, use current project $this->newbug_->project_id = $t_project_id; break; case 'custom_fields': // store custom fields $i = -1; $depth_cf = $reader->depth; while ($reader->read() && ($reader->depth > $depth_cf || $reader->nodeType != XMLReader::END_ELEMENT)) { if ($reader->nodeType == XMLReader::ELEMENT) { if ($reader->localName == 'custom_field') { $t_custom_fields[++$i] = new stdClass(); } switch ($reader->localName) { default: $field = $reader->localName; $reader->read(); $t_custom_fields[$i]->{$field} = $reader->value; } } } break; case 'bugnotes': // store bug notes $i = -1; $depth_bn = $reader->depth; while ($reader->read() && ($reader->depth > $depth_bn || $reader->nodeType != XMLReader::END_ELEMENT)) { if ($reader->nodeType == XMLReader::ELEMENT) { if ($reader->localName == 'bugnote') { $t_bugnotes[++$i] = new stdClass(); } switch ($reader->localName) { case 'reporter': $t_old_id = $reader->getAttribute('id'); $reader->read(); $t_bugnotes[$i]->reporter_id = $this->get_user_id($reader->value, $userId); break; case 'view_state': $t_old_id = $reader->getAttribute('id'); $reader->read(); $t_bugnotes[$i]->private = $reader->value == VS_PRIVATE ? true : false; break; default: $field = $reader->localName; $reader->read(); $t_bugnotes[$i]->{$field} = $reader->value; } } } break; case 'attachments': // store attachments $i = -1; $depth_att = $reader->depth; while ($reader->read() && ($reader->depth > $depth_att || $reader->nodeType != XMLReader::END_ELEMENT)) { if ($reader->nodeType == XMLReader::ELEMENT) { if ($reader->localName == 'attachment') { $t_attachments[++$i] = new stdClass(); } switch ($reader->localName) { default: $field = $reader->localName; $reader->read(); $t_attachments[$i]->{$field} = $reader->value; } } } break; default: $field = $reader->localName; //echo "using default handler for field: $field\n"; $reader->read(); $this->newbug_->{$field} = $reader->value; } } } // now save the new bug $this->new_id_ = $this->newbug_->create(); // add custom fields if ($this->new_id_ > 0 && is_array($t_custom_fields) && count($t_custom_fields) > 0) { foreach ($t_custom_fields as $t_custom_field) { $t_custom_field_id = custom_field_get_id_from_name($t_custom_field->name); if (custom_field_ensure_exists($t_custom_field_id) && custom_field_is_linked($t_custom_field_id, $t_project_id)) { custom_field_set_value($t_custom_field->id, $this->new_id_, $t_custom_field->value); } else { error_parameters($t_custom_field->name, $t_custom_field_id); trigger_error(ERROR_CUSTOM_FIELD_NOT_LINKED_TO_PROJECT, ERROR); } } } // add bugnotes if ($this->new_id_ > 0 && is_array($t_bugnotes) && count($t_bugnotes) > 0) { foreach ($t_bugnotes as $t_bugnote) { bugnote_add($this->new_id_, $t_bugnote->note, $t_bugnote->time_tracking, $t_bugnote->private, $t_bugnote->note_type, $t_bugnote->note_attr, $t_bugnote->reporter_id, false, $t_bugnote->date_submitted, $t_bugnote->last_modified, true); } } // add attachments if ($this->new_id_ > 0 && is_array($t_attachments) && count($t_attachments) > 0) { foreach ($t_attachments as $t_attachment) { // Create a temporary file in the temporary files directory using sys_get_temp_dir() $temp_file_name = tempnam(sys_get_temp_dir(), 'MantisImport'); file_put_contents($temp_file_name, base64_decode($t_attachment->content)); $file_data = array('name' => $t_attachment->filename, 'type' => $t_attachment->file_type, 'tmp_name' => $temp_file_name, 'size' => filesize($temp_file_name), 'error' => UPLOAD_ERR_OK); // unfortunately we have no clue who has added the attachment (this could only be fetched from history -> feel free to implement this) // also I have no clue where description should come from... file_add($this->new_id_, $file_data, 'bug', $t_attachment->title, $p_desc = '', $p_user_id = null, $t_attachment->date_added, true); unlink($temp_file_name); } } //echo "\nnew bug: $this->new_id_\n"; }
# bug_close updates the status and bugnote and sends message bug_close($f_bug_id, $f_bugnote_text, $f_private, $f_time_tracking); $t_notify = false; $t_bug_note_set = true; break; case config_get('bug_reopen_status'): if ($t_old_bug_status >= $t_resolved) { bug_set_field($f_bug_id, 'handler_id', $t_bug_data->handler_id); # fix: update handler_id before calling bug_reopen # bug_reopen updates the status and bugnote and sends message bug_reopen($f_bug_id, $f_bugnote_text, $f_time_tracking, $f_private); $t_notify = false; $t_bug_note_set = true; // update bug data with fields that may be updated inside bug_resolve(), otherwise changes will be overwritten // in bug_update() call below. $t_bug_data->status = bug_get_field($f_bug_id, 'status'); $t_bug_data->resolution = bug_get_field($f_bug_id, 'resolution'); break; } # else fall through to default } } # Add a bugnote if there is one if (!$t_bug_note_set) { bugnote_add($f_bug_id, $f_bugnote_text, $f_time_tracking, $f_private, 0, '', NULL, FALSE); } # Update the bug entry, notify if we haven't done so already bug_update($f_bug_id, $t_bug_data, true, false == $t_notify); form_security_purge('bug_update'); helper_call_custom_function('issue_update_notify', array($f_bug_id)); print_successful_redirect_to_bug($f_bug_id);
public function post($request) { /** * Creates a new bugnote. * * Sets the location header and returns the main URL of the created resource, * as RFC2616 says we SHOULD. * * @param $request - The Request we're responding to */ $this->bug_id = BugnoteList::get_bug_id_from_url($request->url); if (!access_has_bug_level(config_get('add_bugnote_threshold'), $this->bug_id)) { throw new HTTPException(403, "Access denied to add bugnote"); } if (bug_is_readonly($this->bug_id)) { throw new HTTPException(500, "Cannot add a bugnote to a read-only bug"); } $new_note = new Bugnote(); $new_note->populate_from_repr($request->body); $bugnote_added = bugnote_add($this->bug_id, $new_note->mantis_data['note'], '0:00', $new_note->mantis_data['view_state'] == VS_PRIVATE); if ($bugnote_added) { $bugnote_added_url = Bugnote::get_url_from_mantis_id($bugnote_added); $this->rsrc_data = $bugnote_added_url; $resp = new Response(); $resp->headers[] = "location: {$bugnote_added_url}"; $resp->status = 201; $resp->body = json_encode($bugnote_added_url); return $resp; } else { throw new HTTPException(500, "Couldn't create bugnote"); } }
function copyUserStory($us_id, $status, $sprintname) { global $agilemantis_pb; global $agilemantis_tasks; global $agilemantis_sprint; $new_bug_id = bug_copy($us_id, null, true, true, false, true, true, true); $agilemantis_pb->doUserStoryToSprint($new_bug_id, $sprintname); relationship_add($new_bug_id, $us_id, 0); $task = $agilemantis_sprint->getSprintTasks($us_id); $agilemantis_sprint->sprint_id = $sprintname; $sprintinfo = $agilemantis_sprint->getSprintById(); $old_userstory = $agilemantis_pb->checkForUserStory($us_id); $agilemantis_pb->addStoryPoints($new_bug_id, $old_userstory['storypoints']); $agilemantis_pb->addBusinessValue($new_bug_id, $old_userstory['businessValue']); $agilemantis_pb->addRankingOrder($new_bug_id, $old_userstory['rankingorder']); $agilemantis_pb->addTechnical($new_bug_id, $old_userstory['technical']); $agilemantis_pb->addPresentable($new_bug_id, $old_userstory['presentable']); $agilemantis_pb->AddInReleaseDocu($new_bug_id, $old_userstory['inReleaseDocu']); $agilemantis_pb->AddPlannedWork($new_bug_id, $old_userstory['plannedWork']); history_delete($new_bug_id); $bugnote_text_new = plugin_lang_get('divide_userstories_from') . $agilemantis_pb->getUserName(auth_get_current_user_id()) . plugin_lang_get('divide_userstories_of') . ' #' . $us_id . plugin_lang_get('divide_userstories_splitted'); $bugnote_text_old = plugin_lang_get('divide_userstories_from') . $agilemantis_pb->getUserName(auth_get_current_user_id()) . plugin_lang_get('divide_userstories_from') . ', #' . $new_bug_id . plugin_lang_get('divide_userstories_splitted'); $agilemantis_sprint->sprint_id = $old_userstory['sprint']; $sprintinfo = $agilemantis_sprint->getSprintById(); $userstory_performed = false; $wmu = 0; $spmu = 0; if (!empty($task)) { foreach ($task as $key => $value) { if ($value['performed_capacity'] > 0 || $value['status'] >= 4) { $userstory_performed = true; } if ($value['status'] < 4) { $agilemantis_tasks->user_id = auth_get_current_user_id(); $agilemantis_tasks->name = $value['name']; $agilemantis_tasks->us_id = $value['us_id']; $agilemantis_tasks->description = $value['description']; $agilemantis_tasks->developer = $value['developer_id']; $agilemantis_tasks->status = 5; $agilemantis_tasks->capacity = $value['performed_capacity']; $agilemantis_tasks->planned_capacity = $value['planned_capacity']; $agilemantis_tasks->rest_capacity = 0; $agilemantis_tasks->id = $value['id']; $agilemantis_tasks->unit = $value['unit']; $agilemantis_tasks->editTask(); $agilemantis_tasks->saveDailyPerformance(0); $agilemantis_tasks->id = 0; $agilemantis_tasks->name = $value['name']; $agilemantis_tasks->us_id = $new_bug_id; $agilemantis_tasks->description = $value['description']; $agilemantis_tasks->status = $value['status']; if ($value['status'] == 3) { $agilemantis_tasks->status = 2; } $agilemantis_tasks->developer = $value['developer_id']; if ($agilemantis_sprint->getUnitId(plugin_config_get('gadiv_task_unit_mode')) != $sprintinfo['unit_planned_task']) { $agilemantis_tasks->planned_capacity = 0; $agilemantis_tasks->rest_capacity = 0; } else { $agilemantis_tasks->planned_capacity = $value['rest_capacity']; $agilemantis_tasks->rest_capacity = $value['rest_capacity']; } $agilemantis_tasks->addFinishedNote($value['us_id'], $value['id'], auth_get_current_user_id()); $agilemantis_tasks->editTask(); $agilemantis_tasks->id = 0; $agilemantis_tasks->updateTaskLog($value['id'], auth_get_current_user_id(), "closed"); $agilemantis_tasks->setTaskStatus($value['id'], 5); $wmu += $value['rest_capacity']; $new_storypoints += $value['performed_capacity']; } } } if ($sprintinfo['unit_planned_task'] == 3) { $spmu = $wmu; } else { $spmu = 0; } # collect all user story splitting information and write these into database $agilemantis_sprint->setSplittingInformation($us_id, $new_bug_id, $wmu, $spmu); if ($userstory_performed === true) { if ($sprintinfo['unit_planned_task'] < 3) { $agilemantis_pb->addStoryPoints($new_bug_id, ''); } elseif ($sprintinfo['unit_planned_task'] == 3) { $agilemantis_pb->addStoryPoints($new_bug_id, $old_userstory['storypoints'] - $new_storypoints); } $bugnote_text_new .= plugin_lang_get('divide_userstories_old_estimation') . " #" . $us_id . plugin_lang_get('divide_userstories_with') . $old_userstory['storypoints'] . " SP."; bugnote_add($new_bug_id, $bugnote_text_new); } # add bug note bugnote_add($us_id, $bugnote_text_old); $agilemantis_tasks->setUserStoryStatus($us_id, $status, auth_get_current_user_id()); $agilemantis_tasks->closeUserStory($us_id, $status, auth_get_current_user_id()); bug_update_date($us_id); }
} } $result = email_bug_reminder( $f_to, $f_bug_id, $f_body ); # Add reminder as bugnote if store reminders option is ON. if ( ON == config_get( 'store_reminders' ) ) { if ( count( $f_to ) > 50 ) { # too many recipients to log, truncate the list $t_to = array(); for ( $i=0; $i<50; $i++ ) { $t_to[] = $f_to[$i]; } $f_to = $t_to; } $t_attr = '|' . implode( '|', $f_to ) . '|'; bugnote_add( $f_bug_id, $f_body, 0, config_get( 'default_reminder_view_status' ) == VS_PRIVATE, REMINDER, $t_attr, NULL, FALSE ); } form_security_purge( 'bug_reminder' ); html_page_top( null, string_get_bug_view_url( $f_bug_id ) ); ?> <br /> <div> <?php echo lang_get( 'operation_successful' ).'<br />'; print_bracket_link( string_get_bug_view_url( $f_bug_id ), lang_get( 'proceed' ) ); ?> </div> <?php html_page_bottom();
/** * Add a note to an existing issue. * * @param string $p_username The name of the user trying to add a note to an issue. * @param string $p_password The password of the user. * @param integer $p_issue_id The id of the issue to add the note to. * @param IssueNoteData $p_note The note to add. * @return integer The id of the added note. */ function mc_issue_note_add($p_username, $p_password, $p_issue_id, $p_note) { $t_user_id = mci_check_login($p_username, $p_password); if ($t_user_id === false) { return new soap_fault('Client', '', 'Access Denied'); } if ((int) $p_issue_id < 1) { return new soap_fault('Client', '', "Invalid issue id '{$p_issue_id}'."); } if (!bug_exists($p_issue_id)) { return new soap_fault('Client', '', "Issue '{$p_issue_id}' does not exist"); } $t_project_id = bug_get_field($p_issue_id, 'project_id'); if (!mci_has_readwrite_access($t_user_id, $t_project_id)) { return new soap_fault('Client', '', 'Access Denied'); } if (!access_has_bug_level(config_get('add_bugnote_threshold'), $p_issue_id, $t_user_id)) { return new soap_fault('Client', '', "User '{$t_user_id}' does not have access right to add notes to this issue."); } if (bug_is_readonly($p_issue_id)) { return new soap_fault('Client', '', "Issue '{$p_issue_id}' is readonly."); } if (isset($p_note['view_state'])) { $t_view_state = $p_note['view_state']; } else { $t_view_state = array('id' => config_get('default_bug_view_status')); } $t_view_state_id = mci_get_enum_id_from_objectref('view_state', $t_view_state); return bugnote_add($p_issue_id, $p_note['text'], '0:00', $t_view_state_id == VS_PRIVATE, BUGNOTE, '', $t_user_id); }
/** * updates the status field * @return bool * @access public * @see bug_update.php */ function kanban_ajax_request_bug_update_status() { $p_bug_id = gpc_get_int('id'); $p_new_status = gpc_get_int('new_status'); $t_project_id = gpc_get_int('project_id'); $c_bug_id = (int) $p_bug_id; $f_new_status = (int) $p_new_status; $t_bug_data = bug_get($c_bug_id, true); $f_update_mode = gpc_get_bool('update_mode', FALSE); # set if called from generic update page if (!(access_has_bug_level(access_get_status_threshold($f_new_status, $t_project_id), $c_bug_id) || access_has_bug_level(config_get('update_bug_threshold'), $c_bug_id) || bug_get_field($c_bug_id, 'reporter_id') == auth_get_current_user_id() && (ON == config_get('allow_reporter_reopen') || ON == config_get('allow_reporter_close')))) { access_denied(); } # extract current extended information $t_old_bug_status = $t_bug_data->status; log_event(LOG_AJAX, "Old bug status {$t_old_bug_status} - trying update to new status {$f_new_status}..."); $t_bug_data->reporter_id = gpc_get_int('reporter_id', $t_bug_data->reporter_id); $t_bug_data->handler_id = gpc_get_int('handler_id', $t_bug_data->handler_id); $t_bug_data->duplicate_id = gpc_get_int('duplicate_id', $t_bug_data->duplicate_id); $t_bug_data->priority = gpc_get_int('priority', $t_bug_data->priority); $t_bug_data->severity = gpc_get_int('severity', $t_bug_data->severity); $t_bug_data->reproducibility = gpc_get_int('reproducibility', $t_bug_data->reproducibility); $t_bug_data->status = gpc_get_int('new_status', $t_bug_data->status); $t_bug_data->resolution = gpc_get_int('resolution', $t_bug_data->resolution); $t_bug_data->projection = gpc_get_int('projection', $t_bug_data->projection); $t_bug_data->category_id = gpc_get_int('category_id', $t_bug_data->category_id); $t_bug_data->eta = gpc_get_int('eta', $t_bug_data->eta); $t_bug_data->os = gpc_get_string('os', $t_bug_data->os); $t_bug_data->os_build = gpc_get_string('os_build', $t_bug_data->os_build); $t_bug_data->platform = gpc_get_string('platform', $t_bug_data->platform); $t_bug_data->version = gpc_get_string('version', $t_bug_data->version); $t_bug_data->build = gpc_get_string('build', $t_bug_data->build); $t_bug_data->fixed_in_version = gpc_get_string('fixed_in_version', $t_bug_data->fixed_in_version); $t_bug_data->view_state = gpc_get_int('view_state', $t_bug_data->view_state); $t_bug_data->summary = gpc_get_string('summary', $t_bug_data->summary); $t_due_date = gpc_get_string('due_date', null); if (access_has_project_level(config_get('roadmap_update_threshold'), $t_bug_data->project_id)) { $t_bug_data->target_version = gpc_get_string('target_version', $t_bug_data->target_version); } if ($t_due_date !== null) { if (is_blank($t_due_date)) { $t_bug_data->due_date = 1; } else { $t_bug_data->due_date = strtotime($t_due_date); } } $t_bug_data->description = gpc_get_string('description', $t_bug_data->description); $t_bug_data->steps_to_reproduce = gpc_get_string('steps_to_reproduce', $t_bug_data->steps_to_reproduce); $t_bug_data->additional_information = gpc_get_string('additional_information', $t_bug_data->additional_information); $f_private = gpc_get_bool('private'); $f_bugnote_text = gpc_get_string('bugnote_text', ''); $f_time_tracking = gpc_get_string('time_tracking', '0:00'); $f_close_now = gpc_get_string('close_now', false); # Handle auto-assigning if (config_get('bug_submit_status') == $t_bug_data->status && $t_bug_data->status == $t_old_bug_status && 0 != $t_bug_data->handler_id && ON == config_get('auto_set_status_to_assigned')) { $t_bug_data->status = config_get('bug_assigned_status'); } helper_call_custom_function('issue_update_validate', array($c_bug_id, $t_bug_data, $f_bugnote_text)); $t_resolved = config_get('bug_resolved_status_threshold'); $t_closed = config_get('bug_closed_status_threshold'); $t_custom_status_label = "update"; # default info to check if ($t_bug_data->status == $t_resolved) { $t_custom_status_label = "resolved"; } if ($t_bug_data->status == $t_closed) { $t_custom_status_label = "closed"; } $t_related_custom_field_ids = custom_field_get_linked_ids($t_bug_data->project_id); foreach ($t_related_custom_field_ids as $t_id) { $t_def = custom_field_get_definition($t_id); # Only update the field if it would have been display for editing if (!(!$f_update_mode && $t_def['require_' . $t_custom_status_label] || !$f_update_mode && $t_def['display_' . $t_custom_status_label] && in_array($t_custom_status_label, array("resolved", "closed")) || $f_update_mode && $t_def['display_update'] || $f_update_mode && $t_def['require_update'])) { continue; } # Do not set custom field value if user has no write access. if (!custom_field_has_write_access($t_id, $c_bug_id)) { continue; } if ($t_def['require_' . $t_custom_status_label] && !gpc_isset_custom_field($t_id, $t_def['type'])) { error_parameters(lang_get_defaulted(custom_field_get_field($t_id, 'name'))); trigger_error(ERROR_EMPTY_FIELD, ERROR); } # Only update the field if it is posted, # or if it is empty, and the current value isn't the default if (!gpc_isset_custom_field($t_id, $t_def['type']) && custom_field_get_value($t_id, $c_bug_id) == $t_def['default_value']) { continue; } if (!custom_field_set_value($t_id, $c_bug_id, gpc_get_custom_field("custom_field_{$t_id}", $t_def['type'], NULL))) { error_parameters(lang_get_defaulted(custom_field_get_field($t_id, 'name'))); log_event(LOG_AJAX, "Error setting new status: " . ERROR_CUSTOM_FIELD_INVALID_VALUE . "\nBugdata: " . print_r($t_bug_data, true) . " Line: " . __LINE__); trigger_error(ERROR_CUSTOM_FIELD_INVALID_VALUE, ERROR); } } $t_notify = true; $t_bug_note_set = false; if ($t_old_bug_status != $t_bug_data->status && FALSE == $f_update_mode) { # handle status transitions that come from pages other than bug_*update_page.php # this does the minimum to act on the bug and sends a specific message if ($t_bug_data->status >= $t_resolved && $t_bug_data->status < $t_closed && $t_old_bug_status < $t_resolved) { # bug_resolve updates the status, fixed_in_version, resolution, handler_id and bugnote and sends message bug_resolve($c_bug_id, $t_bug_data->resolution, $t_bug_data->fixed_in_version, $f_bugnote_text, $t_bug_data->duplicate_id, $t_bug_data->handler_id, $f_private, $f_time_tracking); $t_notify = false; $t_bug_note_set = true; if ($f_close_now) { bug_set_field($c_bug_id, 'status', $t_closed); } // update bug data with fields that may be updated inside bug_resolve(), otherwise changes will be overwritten // in bug_update() call below. $t_bug_data->handler_id = bug_get_field($c_bug_id, 'handler_id'); $t_bug_data->status = bug_get_field($c_bug_id, 'status'); } else { if ($t_bug_data->status >= $t_closed && $t_old_bug_status < $t_closed) { # bug_close updates the status and bugnote and sends message bug_close($c_bug_id, $f_bugnote_text, $f_private, $f_time_tracking); $t_notify = false; $t_bug_note_set = true; } else { if ($t_bug_data->status == config_get('bug_reopen_status') && $t_old_bug_status >= $t_resolved) { bug_set_field($c_bug_id, 'handler_id', $t_bug_data->handler_id); # fix: update handler_id before calling bug_reopen # bug_reopen updates the status and bugnote and sends message bug_reopen($c_bug_id, $f_bugnote_text, $f_time_tracking, $f_private); $t_notify = false; $t_bug_note_set = true; // update bug data with fields that may be updated inside bug_resolve(), otherwise changes will be overwritten // in bug_update() call below. $t_bug_data->status = bug_get_field($c_bug_id, 'status'); $t_bug_data->resolution = bug_get_field($c_bug_id, 'resolution'); } } } } # Plugin support $t_new_bug_data = event_signal('EVENT_UPDATE_BUG', $t_bug_data, $c_bug_id); if (!is_null($t_new_bug_data)) { $t_bug_data = $t_new_bug_data; } # Add a bugnote if there is one if (false == $t_bug_note_set) { bugnote_add($c_bug_id, $f_bugnote_text, $f_time_tracking, $f_private, 0, '', NULL, FALSE); } # Update the bug entry, notify if we haven't done so already $t_bug_data->update(true, false == $t_notify); helper_call_custom_function('issue_update_notify', array($c_bug_id)); return true; }
case CLOSED: # bug_close updates the status and bugnote and sends message bug_close($f_bug_id, $f_bugnote_text, $f_private); $t_notify = false; $t_bug_note_set = true; break; case config_get('bug_reopen_status'): if ($t_old_bug_status >= $t_resolved) { bug_set_field($f_bug_id, 'handler_id', $t_bug_data->handler_id); # fix: update handler_id before calling bug_reopen # bug_reopen updates the status and bugnote and sends message bug_reopen($f_bug_id, $f_bugnote_text, $f_private); $t_notify = false; $t_bug_note_set = true; // update bug data with fields that may be updated inside bug_resolve(), otherwise changes will be overwritten // in bug_update() call below. $t_bug_data->status = bug_get_field($f_bug_id, 'status'); $t_bug_data->resolution = bug_get_field($f_bug_id, 'resolution'); break; } # else fall through to default } } # Add a bugnote if there is one if (!is_blank($f_bugnote_text) && false == $t_bug_note_set) { bugnote_add($f_bug_id, $f_bugnote_text, $f_private); } # Update the bug entry, notify if we haven't done so already bug_update($f_bug_id, $t_bug_data, true, false == $t_notify); helper_call_custom_function('issue_update_notify', array($f_bug_id)); print_successful_redirect_to_bug($f_bug_id);
function save_bug($p_project_id, $p_user_id) { require 'ProfileAcraExt.php'; $t_project_id = $p_project_id; global $g_cache_current_user_id; $g_cache_current_user_id = $p_user_id; $t_bug_data = new BugData(); $t_bug_data->project_id = $t_project_id; $t_bug_data->reporter_id = $p_user_id; $t_bug_data->build = gpc_get_string('APP_VERSION_CODE', ''); $t_bug_data->platform = "Android"; $t_bug_data->os = gpc_get_string('ANDROID_VERSION', ''); //gpc_get_string( 'os', '' ); $t_os_build = gpc_get_string('BUILD', ''); if (preg_match('/DISPLAY\\s*=\\s*(.*)/', $t_os_build, $t_match)) { var_dump($t_match); $t_os_build = $t_match[1]; } else { $t_os_build = gpc_get_string('ANDROID_VERSION', ''); } $t_bug_data->os_build = $t_os_build; //gpc_get_string( 'os_build', '' ); $t_bug_data->version = gpc_get_string('APP_VERSION_NAME', ''); $t_bug_data->profile_id = profile_create_unique(ALL_USERS, $t_bug_data->platform, $t_bug_data->os, $t_bug_data->os_build, ""); $t_bug_data->handler_id = gpc_get_int('handler_id', 0); $t_bug_data->view_state = gpc_get_int('view_state', config_get('default_bug_view_status', 'VS_PRIVATE', 'acra_reporter')); $t_bug_data->category_id = $this->get_category_id($p_project_id); //gpc_get_int( 'category_id', 0 ); $t_bug_data->reproducibility = 10; //gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $t_bug_data->severity = CRASH; //gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $t_bug_data->priority = HIGH; //gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); $t_bug_data->projection = gpc_get_int('projection', config_get('default_bug_projection')); $t_bug_data->eta = gpc_get_int('eta', config_get('default_bug_eta')); $t_bug_data->resolution = OPEN; //gpc_get_string('resolution', config_get( 'default_bug_resolution' ) ); $t_bug_data->status = NEW_; //gpc_get_string( 'status', config_get( 'bug_submit_status' ) ); $t_bug_data->description = gpc_get_string('STACK_TRACE'); //gpc_get_string( 'description' ); $t_bug_data->summary = get_bug_summary_by_version(gpc_get_string('APP_VERSION_NAME', ''), $t_bug_data->description, $t_project_id); $t_bug_data->steps_to_reproduce = gpc_get_string('LOGCAT', ""); $t_bug_data->additional_information = gpc_get_string('CRASH_CONFIGURATION', ""); $t_bug_data->due_date = gpc_get_string('USER_CRASH_DATE', ''); if (is_blank($t_bug_data->due_date)) { $t_bug_data->due_date = date_get_null(); } $f_files = gpc_get_file('ufile', null); /** @todo (thraxisp) Note that this always returns a structure */ $f_report_stay = gpc_get_bool('report_stay', false); $f_copy_notes_from_parent = gpc_get_bool('copy_notes_from_parent', false); helper_call_custom_function('issue_create_validate', array($t_bug_data)); # Validate the custom fields before adding the bug. $t_related_custom_field_ids = custom_field_get_linked_ids($t_bug_data->project_id); foreach ($t_related_custom_field_ids as $t_id) { $t_def = custom_field_get_definition($t_id); # Produce an error if the field is required but wasn't posted if (!gpc_isset_custom_field($t_id, $t_def['type']) && $t_def['require_report']) { error_parameters(lang_get_defaulted(custom_field_get_field($t_id, 'name'))); trigger_error(ERROR_EMPTY_FIELD, ERROR); } if (!custom_field_validate($t_id, gpc_get_custom_field("custom_field_{$t_id}", $t_def['type'], NULL))) { error_parameters(lang_get_defaulted(custom_field_get_field($t_id, 'name'))); trigger_error(ERROR_CUSTOM_FIELD_INVALID_VALUE, ERROR); } } # Allow plugins to pre-process bug data $t_bug_data = event_signal('EVENT_REPORT_BUG_DATA', $t_bug_data); # Ensure that resolved bugs have a handler if ($t_bug_data->handler_id == NO_USER && $t_bug_data->status >= config_get('bug_resolved_status_threshold')) { $t_bug_data->handler_id = $this->get_user_id(); } # Create the bug $t_bug_id = $t_bug_data->create(); # Mark the added issue as visited so that it appears on the last visited list. last_visited_issue($t_bug_id); # Handle the file upload if ($f_files != null) { $t_files = helper_array_transpose($f_files); if ($t_files != null) { foreach ($t_files as $t_file) { if (!empty($t_file['name'])) { file_add($t_bug_id, $t_file, 'bug'); } } } } # Handle custom field submission foreach ($t_related_custom_field_ids as $t_id) { # Do not set custom field value if user has no write access if (!custom_field_has_write_access($t_id, $t_bug_id)) { continue; } $t_def = custom_field_get_definition($t_id); if (!custom_field_set_value($t_id, $t_bug_id, gpc_get_custom_field("custom_field_{$t_id}", $t_def['type'], $t_def['default_value']), false)) { error_parameters(lang_get_defaulted(custom_field_get_field($t_id, 'name'))); trigger_error(ERROR_CUSTOM_FIELD_INVALID_VALUE, ERROR); } } $f_master_bug_id = gpc_get_int('m_id', 0); $f_rel_type = gpc_get_int('rel_type', -1); if ($f_master_bug_id > 0) { # it's a child generation... let's create the relationship and add some lines in the history # update master bug last updated bug_update_date($f_master_bug_id); # Add log line to record the cloning action history_log_event_special($t_bug_id, BUG_CREATED_FROM, '', $f_master_bug_id); history_log_event_special($f_master_bug_id, BUG_CLONED_TO, '', $t_bug_id); if ($f_rel_type >= 0) { # Add the relationship relationship_add($t_bug_id, $f_master_bug_id, $f_rel_type); # Add log line to the history (both issues) history_log_event_special($f_master_bug_id, BUG_ADD_RELATIONSHIP, relationship_get_complementary_type($f_rel_type), $t_bug_id); history_log_event_special($t_bug_id, BUG_ADD_RELATIONSHIP, $f_rel_type, $f_master_bug_id); # update relationship target bug last updated bug_update_date($t_bug_id); # Send the email notification email_relationship_added($f_master_bug_id, $t_bug_id, relationship_get_complementary_type($f_rel_type)); } # copy notes from parent if ($f_copy_notes_from_parent) { $t_parent_bugnotes = bugnote_get_all_bugnotes($f_master_bug_id); foreach ($t_parent_bugnotes as $t_parent_bugnote) { $t_private = $t_parent_bugnote->view_state == VS_PRIVATE; bugnote_add($t_bug_id, $t_parent_bugnote->note, $t_parent_bugnote->time_tracking, $t_private, $t_parent_bugnote->note_type, $t_parent_bugnote->note_attr, $t_parent_bugnote->reporter_id, FALSE, FALSE); } } } helper_call_custom_function('issue_create_notify', array($t_bug_id)); # Allow plugins to post-process bug data with the new bug ID event_signal('EVENT_REPORT_BUG', array($t_bug_data, $t_bug_id)); email_new_bug($t_bug_id); // log status and resolution changes if they differ from the default if ($t_bug_data->status != config_get('bug_submit_status')) { history_log_event($t_bug_id, 'status', config_get('bug_submit_status')); } if ($t_bug_data->resolution != config_get('default_bug_resolution')) { history_log_event($t_bug_id, 'resolution', config_get('default_bug_resolution')); } return $t_bug_id; }
function bug_reopen($p_bug_id, $p_bugnote_text = '', $p_bugnote_private = false) { $p_bugnote_text = trim($p_bugnote_text); bug_set_field($p_bug_id, 'status', config_get('bug_reopen_status')); bug_set_field($p_bug_id, 'resolution', config_get('bug_reopen_resolution')); # Add bugnote if supplied if (!is_blank($p_bugnote_text)) { bugnote_add($p_bug_id, $p_bugnote_text, $p_bugnote_private); } email_reopen($p_bug_id); return true; }
/** * Add a note to an existing issue. * * @param string $p_username The name of the user trying to add a note to an issue. * @param string $p_password The password of the user. * @param integer $p_issue_id The id of the issue to add the note to. * @param stdClass $p_note The note to add. * @return integer The id of the added note. */ function mc_issue_note_add($p_username, $p_password, $p_issue_id, stdClass $p_note) { global $g_project_override; $t_user_id = mci_check_login($p_username, $p_password); if ($t_user_id === false) { return mci_soap_fault_login_failed(); } if ((int) $p_issue_id < 1) { return SoapObjectsFactory::newSoapFault('Client', 'Invalid issue id \'' . $p_issue_id . '\''); } if (!bug_exists($p_issue_id)) { return SoapObjectsFactory::newSoapFault('Client', 'Issue \'' . $p_issue_id . '\' does not exist.'); } $p_note = SoapObjectsFactory::unwrapObject($p_note); if (!isset($p_note['text']) || is_blank($p_note['text'])) { return SoapObjectsFactory::newSoapFault('Client', 'Issue note text must not be blank.'); } $t_project_id = bug_get_field($p_issue_id, 'project_id'); $g_project_override = $t_project_id; if (!mci_has_readwrite_access($t_user_id, $t_project_id)) { return mci_soap_fault_access_denied($t_user_id); } if (!access_has_bug_level(config_get('add_bugnote_threshold'), $p_issue_id, $t_user_id)) { return mci_soap_fault_access_denied($t_user_id, 'You do not have access rights to add notes to this issue'); } if (bug_is_readonly($p_issue_id)) { return mci_soap_fault_access_denied($t_user_id, 'Issue \'' . $p_issue_id . '\' is readonly'); } if (isset($p_note['view_state'])) { $t_view_state = $p_note['view_state']; } else { $t_view_state = array('id' => config_get('default_bug_view_status')); } # TODO: #17777: Add test case for mc_issue_add() and mc_issue_note_add() reporter override if (isset($p_note['reporter'])) { $t_reporter_id = mci_get_user_id($p_note['reporter']); if ($t_reporter_id != $t_user_id) { # Make sure that active user has access level required to specify a different reporter. $t_specify_reporter_access_level = config_get('webservice_specify_reporter_on_add_access_level_threshold'); if (!access_has_project_level($t_specify_reporter_access_level, $t_project_id, $t_user_id)) { return mci_soap_fault_access_denied($t_user_id, "Active user does not have access level required to specify a different issue note reporter"); } } } else { $t_reporter_id = $t_user_id; } $t_view_state_id = mci_get_enum_id_from_objectref('view_state', $t_view_state); $t_note_type = isset($p_note['note_type']) ? (int) $p_note['note_type'] : BUGNOTE; $t_note_attr = isset($p_note['note_type']) ? $p_note['note_attr'] : ''; log_event(LOG_WEBSERVICE, 'adding bugnote to issue \'' . $p_issue_id . '\''); 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, $t_note_type, $t_note_attr, $t_reporter_id); }
private function add_bug(&$p_email, $p_overwrite_project_id = FALSE) { $this->show_memory_usage('Start add bug'); //Merge References and In-Reply-To headers into one array $t_references = $p_email['References']; $t_references[] = $p_email['In-Reply-To']; if ($this->_mail_add_bugnotes) { $t_bug_id = $this->mail_is_a_bugnote($p_email['Subject'], $t_references); } else { $t_bug_id = FALSE; } if ($t_bug_id !== FALSE && !bug_is_readonly($t_bug_id)) { // @TODO@ Disabled for now until we find a good solution on how to handle the reporters possible lack of access permissions // access_ensure_bug_level( config_get( 'add_bugnote_threshold' ), $f_bug_id ); $t_description = $p_email['X-Mantis-Body']; $t_description = $this->identify_replies($t_description); $t_description = $this->strip_signature($t_description); $t_description = $this->add_additional_info('note', $p_email, $t_description); $t_project_id = bug_get_field($t_bug_id, 'project_id'); ERP_set_temporary_overwrite('project_override', $t_project_id); # Event integration # Core mantis event already exists within bugnote_add function $t_description = event_signal('EVENT_ERP_BUGNOTE_DATA', $t_description, $t_bug_id); if (bug_is_resolved($t_bug_id)) { # Reopen issue and add a bug note bug_reopen($t_bug_id, $t_description); } elseif (!is_blank($t_description)) { # Add a bug note bugnote_add($t_bug_id, $t_description); } } elseif ($this->_mail_add_bug_reports) { // @TODO@ Disabled for now until we find a good solution on how to handle the reporters possible lack of access permissions // access_ensure_project_level( config_get('report_bug_threshold' ) ); $f_master_bug_id = $t_bug_id !== FALSE && bug_is_readonly($t_bug_id) ? $t_bug_id : 0; $this->fix_empty_fields($p_email); $t_project_id = $p_overwrite_project_id === FALSE ? $this->_mailbox['project_id'] : $p_overwrite_project_id; ERP_set_temporary_overwrite('project_override', $t_project_id); $t_bug_data = new BugData(); $t_bug_data->build = ''; $t_bug_data->platform = ''; $t_bug_data->os = ''; $t_bug_data->os_build = ''; $t_bug_data->version = ''; $t_bug_data->profile_id = 0; $t_bug_data->handler_id = 0; $t_bug_data->view_state = (int) config_get('default_bug_view_status'); $t_bug_data->category_id = (int) $this->_mailbox['global_category_id']; $t_bug_data->reproducibility = (int) config_get('default_bug_reproducibility'); $t_bug_data->severity = (int) config_get('default_bug_severity'); $t_bug_data->priority = (int) ($this->_mail_use_bug_priority ? $p_email['Priority'] : config_get('default_bug_priority')); $t_bug_data->projection = (int) config_get('default_bug_projection'); $t_bug_data->eta = (int) config_get('default_bug_eta'); $t_bug_data->resolution = config_get('default_bug_resolution'); $t_bug_data->status = config_get('bug_submit_status'); $t_bug_data->summary = $p_email['Subject']; $t_description = $p_email['X-Mantis-Body']; $t_description = $this->strip_signature($t_description); $t_description = $this->add_additional_info('issue', $p_email, $t_description); $t_bug_data->description = $t_description; $t_bug_data->steps_to_reproduce = config_get('default_bug_steps_to_reproduce'); $t_bug_data->additional_information = config_get('default_bug_additional_info'); $t_bug_data->due_date = date_get_null(); $t_bug_data->project_id = $t_project_id; $t_bug_data->reporter_id = $p_email['Reporter_id']; // This function might do stuff that EmailReporting cannot handle. Disabled //helper_call_custom_function( 'issue_create_validate', array( $t_bug_data ) ); // @TODO@ Disabled for now but possibly needed for other future features # Validate the custom fields before adding the bug. /* $t_related_custom_field_ids = custom_field_get_linked_ids( $t_bug_data->project_id ); foreach( $t_related_custom_field_ids as $t_id ) { $t_def = custom_field_get_definition( $t_id ); # Produce an error if the field is required but wasn't posted if ( !gpc_isset_custom_field( $t_id, $t_def['type'] ) && ( $t_def['require_report'] || $t_def['type'] == CUSTOM_FIELD_TYPE_ENUM || $t_def['type'] == CUSTOM_FIELD_TYPE_LIST || $t_def['type'] == CUSTOM_FIELD_TYPE_MULTILIST || $t_def['type'] == CUSTOM_FIELD_TYPE_RADIO ) ) { error_parameters( lang_get_defaulted( custom_field_get_field( $t_id, 'name' ) ) ); trigger_error( ERROR_EMPTY_FIELD, ERROR ); } if ( !custom_field_validate( $t_id, gpc_get_custom_field( "custom_field_$t_id", $t_def['type'], NULL ) ) ) { error_parameters( lang_get_defaulted( custom_field_get_field( $t_id, 'name' ) ) ); trigger_error( ERROR_CUSTOM_FIELD_INVALID_VALUE, ERROR ); } }*/ # Allow plugins to pre-process bug data $t_bug_data = event_signal('EVENT_REPORT_BUG_DATA', $t_bug_data); $t_bug_data = event_signal('EVENT_ERP_REPORT_BUG_DATA', $t_bug_data); # Create the bug $t_bug_id = $t_bug_data->create(); // @TODO@ Disabled for now but possibly needed for other future features # Handle custom field submission /* foreach( $t_related_custom_field_ids as $t_id ) { # Do not set custom field value if user has no write access. if( !custom_field_has_write_access( $t_id, $t_bug_id ) ) { continue; } $t_def = custom_field_get_definition( $t_id ); if( !custom_field_set_value( $t_id, $t_bug_id, gpc_get_custom_field( "custom_field_$t_id", $t_def['type'], '' ), false ) ) { { error_parameters( lang_get_defaulted( custom_field_get_field( $t_id, 'name' ) ) ); trigger_error( ERROR_CUSTOM_FIELD_INVALID_VALUE, ERROR ); } }*/ // Lets link a readonly already existing bug to the newly created one if ($f_master_bug_id > 0) { $f_rel_type = BUG_RELATED; # update master bug last updated bug_update_date($f_master_bug_id); # Add the relationship relationship_add($t_bug_id, $f_master_bug_id, $f_rel_type); # Add log line to the history (both issues) history_log_event_special($f_master_bug_id, BUG_ADD_RELATIONSHIP, relationship_get_complementary_type($f_rel_type), $t_bug_id); history_log_event_special($t_bug_id, BUG_ADD_RELATIONSHIP, $f_rel_type, $f_master_bug_id); # Send the email notification email_relationship_added($f_master_bug_id, $t_bug_id, relationship_get_complementary_type($f_rel_type)); } helper_call_custom_function('issue_create_notify', array($t_bug_id)); # Allow plugins to post-process bug data with the new bug ID event_signal('EVENT_REPORT_BUG', array($t_bug_data, $t_bug_id)); email_new_bug($t_bug_id); } else { // Not allowed to add issues and not allowed / able to add notes. Need to stop processing $this->custom_error('Not allowed to create a new issue. Email ignored'); return; } $this->custom_error('Reporter: ' . $p_email['Reporter_id'] . ' - ' . $p_email['From_parsed']['email'] . ' --> Issue ID: #' . $t_bug_id, FALSE); $this->show_memory_usage('Finished add bug'); $this->show_memory_usage('Start processing attachments'); # Add files if ($this->_allow_file_upload) { if (count($p_email['X-Mantis-Parts']) > 0) { $t_rejected_files = NULL; while ($t_part = array_shift($p_email['X-Mantis-Parts'])) { $t_file_rejected = $this->add_file($t_bug_id, $t_part); if ($t_file_rejected !== TRUE) { $t_rejected_files .= $t_file_rejected; } } if ($t_rejected_files !== NULL) { $t_part = array('name' => 'Rejected files.txt', 'ctype' => 'text/plain', 'body' => 'List of rejected files' . "\n\n" . $t_rejected_files); $t_reject_rejected_files = $this->add_file($t_bug_id, $t_part); if ($t_reject_rejected_files !== TRUE) { $t_part['body'] .= $t_reject_rejected_files; $this->custom_error('Failed to add "' . $t_part['name'] . '" to the issue. See below for all errors.' . "\n" . $t_part['body']); } } } } //Add the users in Cc and To list in mail header $this->add_monitors($t_bug_id, $p_email); //Add the message-id to the database $this->add_msg_id($t_bug_id, $p_email['Message-ID']); ERP_set_temporary_overwrite('project_override', NULL); $this->show_memory_usage('Finished processing attachments'); }
$t_user_notes = db_query_bound($sql_notes, array($t_bug['bug_id'], $t_bug['date_modified'])); #Si pas de notes on en rajoute une if (db_num_rows($t_user_notes) < 1) { $t_bugnote_text = sprintf(plugin_lang_get('before_change_status_message'), $t_status_names[$change['from_status']], $change['reminder_days'], $t_status_names[$change['to_status']], $change['status_days'] - $change['reminder_days']); bugnote_add($t_bug['bug_id'], $t_bugnote_text, '0:02', false, BUGNOTE, '', $g_cron_current_user_id); } } } #### # 2ème étape : Changement automatique des statuts ### if ($change['project_id'] != 0) { $t_bug_status_pool = db_query_bound($sql_status, array($change['from_status'], $change['from_status'], $change['project_id'], $change['status_days'])); } else { $t_bug_status_pool = db_query_bound($sql_status_no_project, array($change['from_status'], $change['from_status'], $change['status_days'])); } while ($t_bug_status = db_fetch_array($t_bug_status_pool)) { #On regarde si ces bugs ont été commenté dans la période $t_user_notes_status = db_query_bound($sql_notes, array($t_bug_status['bug_id'], $t_bug_status['date_modif'])); #Si pas de notes on en rajoute une if (db_num_rows($t_user_notes_status) < 1) { #Rajout d'une note informative $t_bugnote_text_status = sprintf(plugin_lang_get('change_status_message'), $change['status_days']); bugnote_add($t_bug_status['bug_id'], $t_bugnote_text_status, '0:02', false, BUGNOTE, '', $g_cron_current_user_id); #Changement du status du bug $t_bug_model = bug_get($t_bug_status['bug_id']); $t_bug_model->status = $change['to_status']; $t_bug_model->update(); } } }
/** * Add a note to an existing issue. * * @param string $p_username The name of the user trying to add a note to an issue. * @param string $p_password The password of the user. * @param integer $p_issue_id The id of the issue to add the note to. * @param IssueNoteData $p_note The note to add. * @return integer The id of the added note. */ function mc_issue_note_add( $p_username, $p_password, $p_issue_id, $p_note ) { $t_user_id = mci_check_login( $p_username, $p_password ); if( $t_user_id === false ) { return mci_soap_fault_login_failed(); } if( (integer) $p_issue_id < 1 ) { return new soap_fault( 'Client', '', "Invalid issue id '$p_issue_id'" ); } if( !bug_exists( $p_issue_id ) ) { return new soap_fault( 'Client', '', "Issue '$p_issue_id' does not exist." ); } if ( !isset( $p_note['text'] ) || is_blank( $p_note['text'] ) ) { return new soap_fault( 'Client', '', "Issue note text must not be blank." ); } $t_project_id = bug_get_field( $p_issue_id, 'project_id' ); if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) { return mci_soap_fault_access_denied( $t_user_id ); } if( !access_has_bug_level( config_get( 'add_bugnote_threshold' ), $p_issue_id, $t_user_id ) ) { return mci_soap_fault_access_denied( $t_user_id, "You do not have access rights to add notes to this issue" ); } if( bug_is_readonly( $p_issue_id ) ) { return mci_soap_fault_access_denied( $t_user_id, "Issue '$p_issue_id' is readonly" ); } if( isset( $p_note['view_state'] ) ) { $t_view_state = $p_note['view_state']; } else { $t_view_state = array( 'id' => config_get( 'default_bug_view_status' ), ); } $t_view_state_id = mci_get_enum_id_from_objectref( 'view_state', $t_view_state ); $note_type = isset ( $p_note['note_type'] ) ? (int) $p_note['note_type'] : BUGNOTE; $note_attr = isset ( $p_note['note_type'] ) ? $p_note['note_attr'] : ''; 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 ); }
# Add the relationship relationship_add($t_bug_id, $f_master_bug_id, $f_rel_type); # Add log line to the history (both issues) history_log_event_special($f_master_bug_id, BUG_ADD_RELATIONSHIP, relationship_get_complementary_type($f_rel_type), $t_bug_id); history_log_event_special($t_bug_id, BUG_ADD_RELATIONSHIP, $f_rel_type, $f_master_bug_id); # update relationship target bug last updated bug_update_date($t_bug_id); # Send the email notification email_relationship_added($f_master_bug_id, $t_bug_id, relationship_get_complementary_type($f_rel_type)); } # copy notes from parent if ($f_copy_notes_from_parent) { $t_parent_bugnotes = bugnote_get_all_bugnotes($f_master_bug_id); foreach ($t_parent_bugnotes as $t_parent_bugnote) { $t_private = $t_parent_bugnote->view_state == VS_PRIVATE; bugnote_add($t_bug_id, $t_parent_bugnote->note, $t_parent_bugnote->time_tracking, $t_private, $t_parent_bugnote->note_type, $t_parent_bugnote->note_attr, $t_parent_bugnote->reporter_id, FALSE, FALSE); } } # copy attachments from parent if ($f_copy_attachments_from_parent) { file_copy_attachments($f_master_bug_id, $t_bug_id); } } helper_call_custom_function('issue_create_notify', array($t_bug_id)); # Allow plugins to post-process bug data with the new bug ID event_signal('EVENT_REPORT_BUG', array($t_bug_data, $t_bug_id)); email_new_bug($t_bug_id); // log status and resolution changes if they differ from the default if ($t_bug_data->status != config_get('bug_submit_status')) { history_log_event($t_bug_id, 'status', config_get('bug_submit_status')); }
/** * Executes the custom action on the specified bug id. * * @param $p_bug_id The bug id to execute the custom action on. * @returns true|array Action executed successfully., ( bug_id => reason for failure ) */ function action_add_note_process($p_bug_id) { $f_bugnote_text = gpc_get_string('bugnote_text'); $f_view_state = gpc_get_int('view_state'); bugnote_add($p_bug_id, $f_bugnote_text, '0:00', $f_view_state != VS_PUBLIC); return true; }
bug_set_field($t_bug_id, 'priority', $f_priority); email_bug_updated($t_bug_id); helper_call_custom_function('issue_update_notify', array($t_bug_id)); } else { $t_failed_ids[$t_bug_id] = lang_get('bug_actiongroup_access'); } break; case 'UP_STATUS': $f_status = gpc_get_int('status'); if (access_has_bug_level(access_get_status_threshold($f_status, $t_bug->project_id), $t_bug_id)) { if (true == bug_check_workflow($t_status, $f_status)) { # @todo we need to issue a helper_call_custom_function( 'issue_update_validate', array( $t_bug_id, $t_bug_data, $f_bugnote_text ) ); bug_set_field($t_bug_id, 'status', $f_status); # Add bugnote if supplied if (!is_blank($f_bug_notetext)) { bugnote_add($t_bug_id, $f_bug_notetext, null, $f_bug_noteprivate); # No need to call email_generic(), bugnote_add() does it } else { email_bug_updated($t_bug_id); } helper_call_custom_function('issue_update_notify', array($t_bug_id)); } else { $t_failed_ids[$t_bug_id] = lang_get('bug_actiongroup_status'); } } else { $t_failed_ids[$t_bug_id] = lang_get('bug_actiongroup_access'); } break; case 'UP_CATEGORY': $f_category_id = gpc_get_int('category'); if (access_has_bug_level(config_get('update_bug_threshold'), $t_bug_id)) {
/** * reopen the given bug * @param int p_bug_id * @param string p_bugnote_text * @param string p_time_tracking * @param bool p_bugnote_private * @return bool (always true) * @access public * @uses database_api.php * @uses email_api.php * @uses bugnote_api.php * @uses config_api.php */ function bug_reopen($p_bug_id, $p_bugnote_text = '', $p_time_tracking = '0:00', $p_bugnote_private = false) { $p_bugnote_text = trim($p_bugnote_text); # Add bugnote if supplied # Moved bugnote_add before bug_set_field calls in case time_tracking_no_note is off. # Error condition stopped execution but status had already been changed bugnote_add($p_bug_id, $p_bugnote_text, $p_time_tracking, $p_bugnote_private, 0, '', NULL, FALSE); bug_set_field($p_bug_id, 'status', config_get('bug_reopen_status')); bug_set_field($p_bug_id, 'resolution', config_get('bug_reopen_resolution')); email_reopen($p_bug_id); return true; }
/** * Given a set of changeset objects, parse the bug links * and save the changes. * @param array Changeset objects * @param object Repository object */ function Source_Process_Changesets($p_changesets, $p_repo = null) { global $g_cache_current_user_id; if (!is_array($p_changesets)) { return; } if (is_null($p_repo)) { $t_repos = SourceRepo::load_by_changesets($p_changesets); } else { $t_repos = array($p_repo->id => $p_repo); } $t_resolved_threshold = config_get('bug_resolved_status_threshold'); $t_fixed_threshold = config_get('bug_resolution_fixed_threshold'); $t_notfixed_threshold = config_get('bug_resolution_not_fixed_threshold'); # Link author and committer name/email to user accounts foreach ($p_changesets as $t_key => $t_changeset) { $p_changesets[$t_key] = Source_Parse_Users($t_changeset); } # Parse normal bug links foreach ($p_changesets as $t_changeset) { $t_changeset->bugs = Source_Parse_Buglinks($t_changeset->message); } # Parse fixed bug links $t_fixed_bugs = array(); # Find and associate resolve links with the changeset foreach ($p_changesets as $t_changeset) { $t_bugs = Source_Parse_Bugfixes($t_changeset->message); foreach ($t_bugs as $t_bug_id) { $t_fixed_bugs[$t_bug_id] = $t_changeset; } # Add the link to the normal set of buglinks $t_changeset->bugs = array_unique(array_merge($t_changeset->bugs, $t_bugs)); } # Save changeset data before processing their consequences foreach ($p_changesets as $t_changeset) { $t_changeset->repo = $p_repo; $t_changeset->save(); } # Precache information for resolved bugs bug_cache_array_rows(array_keys($t_fixed_bugs)); $t_current_user_id = $g_cache_current_user_id; $t_enable_resolving = config_get('plugin_Source_enable_resolving'); $t_enable_message = config_get('plugin_Source_enable_message'); $t_enable_mapping = config_get('plugin_Source_enable_mapping'); $t_bugfix_status = config_get('plugin_Source_bugfix_status'); $t_bugfix_status_pvm = config_get('plugin_Source_bugfix_status_pvm'); $t_resolution = config_get('plugin_Source_bugfix_resolution'); $t_handler = config_get('plugin_Source_bugfix_handler'); $t_message_template = str_replace(array('$1', '$2', '$3', '$4', '$5', '$6'), array('%1$s', '%2$s', '%3$s', '%4$s', '%5$s', '%6$s'), config_get('plugin_Source_bugfix_message')); $t_mappings = array(); # Start fixing and/or resolving issues foreach ($t_fixed_bugs as $t_bug_id => $t_changeset) { # make sure the bug exists before processing if (!bug_exists($t_bug_id)) { continue; } # fake the history entries as the committer/author user ID $t_user_id = null; if ($t_changeset->committer_id > 0) { $t_user_id = $t_changeset->committer_id; } else { if ($t_changeset->user_id > 0) { $t_user_id = $t_changeset->user_id; } } if (!is_null($t_user_id)) { $g_cache_current_user_id = $t_user_id; } else { if (!is_null($t_current_user_id)) { $g_cache_current_user_id = $t_current_user_id; } else { $g_cache_current_user_id = 0; } } # generate the branch mappings $t_version = ''; $t_pvm_version_id = 0; if ($t_enable_mapping) { $t_repo_id = $t_changeset->repo_id; if (!isset($t_mappings[$t_repo_id])) { $t_mappings[$t_repo_id] = SourceMapping::load_by_repo($t_repo_id); } if (isset($t_mappings[$t_repo_id][$t_changeset->branch])) { $t_mapping = $t_mappings[$t_repo_id][$t_changeset->branch]; if (Source_PVM()) { $t_pvm_version_id = $t_mapping->apply_pvm($t_bug_id); } else { $t_version = $t_mapping->apply($t_bug_id); } } } # generate a note message if ($t_enable_message) { $t_message = sprintf($t_message_template, $t_changeset->branch, $t_changeset->revision, $t_changeset->timestamp, $t_changeset->message, $t_repos[$t_changeset->repo_id]->name, $t_changeset->id); } else { $t_message = ''; } $t_bug = bug_get($t_bug_id); # Update the resolution, fixed-in version, and/or add a bugnote $t_update = false; if (Source_PVM()) { if ($t_bugfix_status_pvm > 0 && $t_pvm_version_id > 0) { $t_matrix = new ProductMatrix($t_bug_id); if (isset($t_matrix->status[$t_pvm_version_id])) { $t_matrix->status[$t_pvm_version_id] = $t_bugfix_status_pvm; $t_matrix->save(); } } } else { if ($t_bugfix_status > 0 && $t_bug->status != $t_bugfix_status) { $t_bug->status = $t_bugfix_status; $t_update = true; } else { if ($t_enable_resolving && $t_bugfix_status == -1 && $t_bug->status < $t_resolved_threshold) { $t_bug->status = $t_resolved_threshold; $t_update = true; } } if ($t_bug->resolution < $t_fixed_threshold || $t_bug->resolution >= $t_notfixed_threshold) { $t_bug->resolution = $t_resolution; $t_update = true; } if (is_blank($t_bug->fixed_in_version)) { $t_bug->fixed_in_version = $t_version; $t_update = true; } } if ($t_handler && !is_null($t_user_id)) { $t_bug->handler_id = $t_user_id; } $t_private = plugin_config_get('bugfix_message_view_status') == VS_PRIVATE; if ($t_update) { if ($t_message) { bugnote_add($t_bug_id, $t_message, '0:00', $t_private, 0, '', null, false); } $t_bug->update(); } else { if ($t_message) { bugnote_add($t_bug_id, $t_message, '0:00', $t_private); } } } # reset the user ID $g_cache_current_user_id = $t_current_user_id; # Allow other plugins to post-process commit data event_signal('EVENT_SOURCE_COMMITS', array($p_changesets)); event_signal('EVENT_SOURCE_FIXED', array($t_fixed_bugs)); }
# -------------------------------------------------------- # $Id: bugnote_add.php,v 1.48.2.1 2007-10-13 22:33:04 giallu Exp $ # -------------------------------------------------------- # Insert the bugnote into the database then redirect to the bug page require_once 'core.php'; $t_core_path = config_get('core_path'); require_once $t_core_path . 'bug_api.php'; require_once $t_core_path . 'bugnote_api.php'; # helper_ensure_post(); $f_bug_id = gpc_get_int('bug_id'); $f_private = gpc_get_bool('private'); $f_time_tracking = gpc_get_string('time_tracking', '0:00'); $f_bugnote_text = trim(gpc_get_string('bugnote_text', '')); if (bug_is_readonly($f_bug_id)) { error_parameters($f_bug_id); trigger_error(ERROR_BUG_READ_ONLY_ACTION_DENIED, ERROR); } access_ensure_bug_level(config_get('add_bugnote_threshold'), $f_bug_id); $t_bug = bug_get($f_bug_id, true); if ($t_bug->project_id != helper_get_current_project()) { # in case the current project is not the same project of the bug we are viewing... # ... override the current project. This to avoid problems with categories and handlers lists etc. $g_project_override = $t_bug->project_id; } # @@@ VB: Do we want to differentiate email notifications for normal notes from time tracking entries? $t_bugnote_added = bugnote_add($f_bug_id, $f_bugnote_text, $f_time_tracking, $f_private, $t_note_type); if (!$t_bugnote_added) { error_parameters(lang_get('bugnote')); trigger_error(ERROR_EMPTY_FIELD, ERROR); } print_successful_redirect_to_bug($f_bug_id);