View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0013324 | mantisbt | api soap | public | 2011-09-19 03:59 | 2013-04-06 08:20 |
| Reporter | MarcoW | Assigned To | rombert | ||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | closed | Resolution | fixed | ||
| Product Version | 1.2.8 | ||||
| Target Version | 1.2.9 | Fixed in Version | 1.2.9 | ||
| Summary | 0013324: Adding or updating issue with mylyn causes error #13 | ||||
| Description | When adding or updating a issue with mylyn the error #13 is thrown. | ||||
| Additional Information | When changing the lines in core/bug_api.php like in the diff, it works. | ||||
| Tags | No tags attached. | ||||
| Attached Files | stacktrace.txt (11,563 bytes)
Error Type: APPLICATION ERROR #13,
Error Description:
Zugang verweigert.,
Stack Trace:
bug_api.php L168 trigger_error(<string>'13', <integer>256)
mc_issue_api.php L633 __set(<string>'target_version', <string>'')
UnknownFile L? mc_issue_add(<string>'hensen', <string>'passwd', <Array> { ['id'] => NULL, ['view_state'] => <Array> { ['id'] => 10, ['name'] => '�ffentlich' }, ['last_updated'] => '2011-09-16T13:00:52.126Z', ['project'] => <Array> { ['id'] => 5, ['name'] => 'MegaPlus / PZE Standardentwicklung' }, ['category'] => 'Abrechnung', ['priority'] => <Array> { ['id'] => 30, ['name'] => 'normal' }, ['severity'] => <Array> { ['id'] => 50, ['name'] => 'kleinerer Fehler' }, ['status'] => <Array> { ['id'] => 30, ['name'] => 'anerkannt' }, ['reporter'] => <Array> { ['id'] => 9, ['name'] => 'hensen', ['real_name'] => 'Andreas Hensen', ['email'] => 'Andreas.Hensen@mega-software.de' }, ['summary'] => 'schwerer Fehler', ['version'] => '', ['build'] => NULL, ['platform'] => NULL, ['os'] => NULL, ['os_build'] => NULL, ['reproducibility'] => <Array> { ['id'] => 70, ['name'] => 'nicht getestet' }, ['date_submitted'] => NULL, ['sponsorship_total'] => NULL, ['handler'] => <Array> { ['id'] => NULL, ['name'] => '', ['real_name'] => NULL, ['email'] => NULL }, ['projection'] => NULL, ['eta'] => NULL, ['resolution'] => <Array> { ['id'] => 10, ['name'] => 'offen' }, ['fixed_in_version'] => '', ['target_version'] => '', ['description'] => 'kaputt ', ['steps_to_reproduce'] => '', ['additional_information'] => '', ['attachments'] => NULL, ['relationships'] => NULL, ['notes'] => NULL, ['custom_fields'] => <Array> { [0] => <Array> { ['field'] => <Array> { ['id'] => 1, ['name'] => 'MMS Meldungsnummer' }, ['value'] => '' } }, ['due_date'] => NULL, ['monitors'] => <Array> { } })
nusoap.php L4087 call_user_func_array(<string>'mc_issue_add', <Array> { [0] => 'user', [1] => 'passwd', [2] => <Array> { ['id'] => NULL, ['view_state'] => <Array> { ['id'] => 10, ['name'] => '�ffentlich' }, ['last_updated'] => '2011-09-16T13:00:52.126Z', ['project'] => <Array> { ['id'] => 5, ['name'] => 'MegaPlus / PZE Standardentwicklung' }, ['category'] => 'Abrechnung', ['priority'] => <Array> { ['id'] => 30, ['name'] => 'normal' }, ['severity'] => <Array> { ['id'] => 50, ['name'] => 'kleinerer Fehler' }, ['status'] => <Array> { ['id'] => 30, ['name'] => 'anerkannt' }, ['reporter'] => <Array> { ['id'] => 9, ['name'] => 'hensen', ['real_name'] => 'Andreas Hensen', ['email'] => 'Andreas.Hensen@mega-software.de' }, ['summary'] => 'schwerer Fehler', ['version'] => '', ['build'] => NULL, ['platform'] => NULL, ['os'] => NULL, ['os_build'] => NULL, ['reproducibility'] => <Array> { ['id'] => 70, ['name'] => 'nicht getestet' }, ['date_submitted'] => NULL, ['sponsorship_total'] => NULL, ['handler'] => <Array> { ['id'] => NULL, ['name'] => '', ['real_name'] => NULL, ['email'] => NULL }, ['projection'] => NULL, ['eta'] => NULL, ['resolution'] => <Array> { ['id'] => 10, ['name'] => 'offen' }, ['fixed_in_version'] => '', ['target_version'] => '', ['description'] => 'kaputt ', ['steps_to_reproduce'] => '', ['additional_information'] => '', ['attachments'] => NULL, ['relationships'] => NULL, ['notes'] => NULL, ['custom_fields'] => <Array> { [0] => <Array> { ['field'] => <Array> { ['id'] => 1, ['name'] => 'MMS Meldungsnummer' }, ['value'] => '' } }, ['due_date'] => NULL, ['monitors'] => <Array> { } } })
nusoap.php L3718 invoke_method()
mantisconnect.php L1499 service(<string>'<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:mc_issue_add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://futureware.biz/mantisconnect"><username xsi:type="xsd:string">user</username><password xsi:type="xsd:string">passwd</password><issue href="#id0"/></ns1:mc_issue_add><multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:IssueData" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://futureware.biz/mantisconnect"><id xsi:type="xsd:integer" xsi:nil="true"/><view_state href="#id1"/><last_updated xsi:type="xsd:dateTime">2011-09-16T13:00:52.126Z</last_updated><project href="#id2"/><category xsi:type="xsd:string">Abrechnung</category><priority href="#id3"/><severity href="#id4"/><status href="#id5"/><reporter href="#id6"/><summary xsi:type="xsd:string">schwerer Fehler</summary><version xsi:type="xsd:string"></version><build xsi:type="xsd:string" xsi:nil="true"/><platform xsi:type="xsd:string" xsi:nil="true"/><os xsi:type="xsd:string" xsi:nil="true"/><os_build xsi:type="xsd:string" xsi:nil="true"/><reproducibility href="#id7"/><date_submitted xsi:type="xsd:dateTime" xsi:nil="true"/><sponsorship_total xsi:type="xsd:integer" xsi:nil="true"/><handler href="#id8"/><projection xsi:type="ns2:ObjectRef" xsi:nil="true"/><eta xsi:type="ns2:ObjectRef" xsi:nil="true"/><resolution href="#id9"/><fixed_in_version xsi:type="xsd:string"></fixed_in_version><target_version xsi:type="xsd:string"></target_version><description xsi:type="xsd:string">kaputt </description><steps_to_reproduce xsi:type="xsd:string"></steps_to_reproduce><additional_information xsi:type="xsd:string"></additional_information><attachments xsi:type="ns2:AttachmentData" xsi:nil="true"/><relationships xsi:type="ns2:RelationshipData" xsi:nil="true"/><notes xsi:type="ns2:IssueNoteData" xsi:nil="true"/><custom_fields soapenc:arrayType="ns2:CustomFieldValueForIssueData[1]" xsi:type="soapenc:Array"><custom_fields href="#id10"/></custom_fields><due_date xsi:type="xsd:dateTime" xsi:nil="true"/><monitors soapenc:arrayType="ns2:AccountData[0]" xsi:type="soapenc:Array"/></multiRef><multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:ObjectRef" xmlns:ns3="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id11"/><name xsi:type="xsd:string">MegaPlus / PZE Standardentwicklung</name></multiRef><multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:ObjectRef" xmlns:ns4="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id12"/><name xsi:type="xsd:string">öffentlich</name></multiRef><multiRef id="id5" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:ObjectRef" xmlns:ns5="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id13"/><name xsi:type="xsd:string">anerkannt</name></multiRef><multiRef id="id10" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns6:CustomFieldValueForIssueData" xmlns:ns6="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><field href="#id14"/><value xsi:type="xsd:string"></value></multiRef><multiRef id="id8" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns7:AccountData" xmlns:ns7="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id xsi:type="xsd:integer" xsi:nil="true"/><name xsi:type="xsd:string"></name><real_name xsi:type="xsd:string" xsi:nil="true"/><email xsi:type="xsd:string" xsi:nil="true"/></multiRef><multiRef id="id4" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns8:ObjectRef" xmlns:ns8="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id15"/><name xsi:type="xsd:string">kleinerer Fehler</name></multiRef><multiRef id="id3" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns9:ObjectRef" xmlns:ns9="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id16"/><name xsi:type="xsd:string">normal</name></multiRef><multiRef id="id7" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns10:ObjectRef" xmlns:ns10="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id17"/><name xsi:type="xsd:string">nicht getestet</name></multiRef><multiRef id="id9" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns11:ObjectRef" xmlns:ns11="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id12"/><name xsi:type="xsd:string">offen</name></multiRef><multiRef id="id6" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns12:AccountData" xmlns:ns12="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id18"/><name xsi:type="xsd:string">hensen</name><real_name xsi:type="xsd:string">Andreas Hensen</real_name><email xsi:type="xsd:string">Andreas.Hensen@mega-software.de</email></multiRef><multiRef id="id18" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">9</multiRef><multiRef id="id11" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">5</multiRef><multiRef id="id17" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">70</multiRef><multiRef id="id15" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">50</multiRef><multiRef id="id12" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">10</multiRef><multiRef id="id14" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns13:ObjectRef" xmlns:ns13="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><id href="#id19"/><name xsi:type="xsd:string">MMS Meldungsnummer</name></multiRef><multiRef id="id16" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">30</multiRef><multiRef id="id13" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">30</multiRef><multiRef id="id19" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:integer" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">1</multiRef></soapenv:Body></soapenv:Envelope>')
eclipse.buildId=I20110613-1736
java.version=1.6.0_26
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=de_DE
Framework arguments: -product org.eclipse.epp.package.cpp.product
Command-line arguments: -os win32 -ws win32 -arch x86 -product org.eclipse.epp.package.cpp.product
This is a continuation of log file E:\projects\eclipse_cdt_workspace\.metadata\.bak_0.log
Created Time: 2011-09-16 13:34:38.382 bug_api.php (58,546 bytes)
<?php
# MantisBT - a php based bugtracking system
# MantisBT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MantisBT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
/**
* Bug API
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
* @package CoreAPI
* @subpackage BugAPI
*/
/**
* requires history_api
*/
require_once( 'history_api.php' );
/**
* requires email_api
*/
require_once( 'email_api.php' );
/**
* requires bugnote_api
*/
require_once( 'bugnote_api.php' );
/**
* requires file_api
*/
require_once( 'file_api.php' );
/**
* requires string_api
*/
require_once( 'string_api.php' );
/**
* requires sponsorship_api
*/
require_once( 'sponsorship_api.php' );
/**
* requires twitter_api
*/
require_once( 'twitter_api.php' );
/**
* requires tag_api
*/
require_once( 'tag_api.php' );
/**
* requires relationship_api
*/
require_once( 'relationship_api.php' );
/**
* requires bug_revision_api
*/
require_once( 'bug_revision_api.php' );
/**
* Bug Data Structure Definition
* @package MantisBT
* @subpackage classes
*/
class BugData {
protected $id;
protected $project_id = null;
protected $reporter_id = 0;
protected $handler_id = 0;
protected $duplicate_id = 0;
protected $priority = NORMAL;
protected $severity = MINOR;
protected $reproducibility = 10;
protected $status = NEW_;
protected $resolution = OPEN;
protected $projection = 10;
protected $category_id = 1;
protected $date_submitted = '';
protected $last_updated = '';
protected $eta = 10;
protected $os = '';
protected $os_build = '';
protected $platform = '';
protected $version = '';
protected $fixed_in_version = '';
protected $target_version = '';
protected $build = '';
protected $view_state = VS_PUBLIC;
protected $summary = '';
protected $sponsorship_total = 0;
protected $sticky = 0;
protected $due_date = 0;
# omitted:
# var $bug_text_id
protected $profile_id;
# extended info
protected $description = '';
protected $steps_to_reproduce = '';
protected $additional_information = '';
# internal helper objects
private $_stats = null;
public $attachment_count = null;
public $bugnotes_count = null;
private $loading = false;
/**
* return number of file attachment's linked to current bug
* @return int
*/
public function get_attachment_count() {
if ( $this->attachment_count === null ) {
$this->attachment_count = file_bug_attachment_count( $this->id );
return $this->attachment_count;
} else {
return $this->attachment_count;
}
}
/**
* return number of bugnotes's linked to current bug
* @return int
*/
public function get_bugnotes_count() {
if ( $this->bugnotes_count === null ) {
$this->bugnotes_count = self::bug_get_bugnote_count();
return $this->bugnotes_count;
} else {
return $this->bugnotes_count;
}
}
/**
* @private
*/
public function __set($name, $value) {
switch ($name) {
// integer types
case 'id':
case 'project_id':
case 'reporter_id':
case 'handler_id':
case 'duplicate_id':
case 'priority':
case 'severity':
case 'reproducibility':
case 'status':
case 'resolution':
case 'projection':
case 'category_id':
$value = (int)$value;
break;
case 'target_version':
if ( !$this->loading ) {
# Only set target_version if user has access to do so
if( !access_has_project_level( config_get( 'roadmap_update_threshold' ) ) ) {
trigger_error( ERROR_ACCESS_DENIED, ERROR );
}
}
break;
case 'due_date':
if ( !is_numeric( $value ) ) {
$value = strtotime($value);
}
break;
}
$this->$name = $value;
}
/**
* @private
*/
public function __get($name) {
if( $this->is_extended_field($name) )
$this->fetch_extended_info();
return $this->{$name};
}
/**
* @private
*/
public function __isset($name) {
return isset( $this->{$name} );
}
/**
* fast-load database row into bugobject
* @param array $p_row
*/
public function loadrow( $p_row ) {
$this->loading = true;
foreach( $p_row as $var => $val ) {
$this->__set( $var, $p_row[$var] );
}
$this->loading = false;
}
/**
* Retrieves extended information for bug (e.g. bug description)
* @return null
*/
private function fetch_extended_info() {
if ( $this->description == '' ) {
$t_text = bug_text_cache_row($this->id);
$this->description = $t_text['description'];
$this->steps_to_reproduce = $t_text['steps_to_reproduce'];
$this->additional_information = $t_text['additional_information'];
}
}
/**
* Returns if the field is an extended field which needs fetch_extended_info()
* @return boolean
*/
private function is_extended_field( $p_field_name ) {
switch( $p_field_name ) {
case 'description':
case 'steps_to_reproduce':
case 'additional_information':
return true;
default:
return false;
}
}
/**
* Returns the number of bugnotes for the given bug_id
* @return int number of bugnotes
* @access private
* @uses database_api.php
*/
private function bug_get_bugnote_count() {
if( !access_has_project_level( config_get( 'private_bugnote_threshold' ), $this->project_id ) ) {
$t_restriction = 'AND view_state=' . VS_PUBLIC;
} else {
$t_restriction = '';
}
$t_bugnote_table = db_get_table( 'mantis_bugnote_table' );
$query = "SELECT COUNT(*)
FROM $t_bugnote_table
WHERE bug_id =" . db_param() . " $t_restriction";
$result = db_query_bound( $query, Array( $this->bug_id ) );
return db_result( $result );
}
/**
* validate current bug object for database insert/update
* triggers error on failure
* @param bool $p_update_extended
*/
function validate( $p_update_extended = true) {
# Summary cannot be blank
if( is_blank( $this->summary ) ) {
error_parameters( lang_get( 'summary' ) );
trigger_error( ERROR_EMPTY_FIELD, ERROR );
}
if( $p_update_extended ) {
# Description field cannot be empty
if( is_blank( $this->description ) ) {
error_parameters( lang_get( 'description' ) );
trigger_error( ERROR_EMPTY_FIELD, ERROR );
}
}
# Make sure a category is set
if( 0 == $this->category_id && !config_get( 'allow_no_category' ) ) {
error_parameters( lang_get( 'category' ) );
trigger_error( ERROR_EMPTY_FIELD, ERROR );
}
if( !is_blank( $this->duplicate_id ) && ( $this->duplicate_id != 0 ) && ( $this->id == $this->duplicate_id ) ) {
trigger_error( ERROR_BUG_DUPLICATE_SELF, ERROR );
# never returns
}
}
/**
* Insert a new bug into the database
* @return int integer representing the bug id that was created
* @access public
* @uses database_api.php
* @uses lang_api.php
*/
function create() {
self::validate( true );
# check due_date format
if( is_blank( $this->due_date ) ) {
$this_due_date = date_get_null();
}
$t_bug_table = db_get_table( 'mantis_bug_table' );
$t_bug_text_table = db_get_table( 'mantis_bug_text_table' );
$t_category_table = db_get_table( 'mantis_category_table' );
# Insert text information
$query = "INSERT INTO $t_bug_text_table
( description, steps_to_reproduce, additional_information )
VALUES
( " . db_param() . ',' . db_param() . ',' . db_param() . ')';
db_query_bound( $query, Array( $this->description, $this->steps_to_reproduce, $this->additional_information ) );
# Get the id of the text information we just inserted
# NOTE: this is guarranteed to be the correct one.
# The value LAST_INSERT_ID is stored on a per connection basis.
$t_text_id = db_insert_id( $t_bug_text_table );
# check to see if we want to assign this right off
$t_starting_status = config_get( 'bug_submit_status' );
$t_original_status = $this->status;
# if not assigned, check if it should auto-assigned.
if( 0 == $this->handler_id ) {
# if a default user is associated with the category and we know at this point
# that that the bug was not assigned to somebody, then assign it automatically.
$query = "SELECT user_id
FROM $t_category_table
WHERE id=" . db_param();
$result = db_query_bound( $query, array( $this->category_id ) );
if( db_num_rows( $result ) > 0 ) {
$this->handler_id = db_result( $result );
}
}
# Check if bug was pre-assigned or auto-assigned.
if( ( $this->handler_id != 0 ) && ( $this->status == $t_starting_status ) && ( ON == config_get( 'auto_set_status_to_assigned' ) ) ) {
$t_status = config_get( 'bug_assigned_status' );
} else {
$t_status = $this->status;
}
# Insert the rest of the data
$query = "INSERT INTO $t_bug_table
( project_id,reporter_id, handler_id,duplicate_id,
priority,severity, reproducibility,status,
resolution,projection, category_id,date_submitted,
last_updated,eta, bug_text_id,
os, os_build,platform, version,build,
profile_id, summary, view_state, sponsorship_total, sticky, fixed_in_version,
target_version, due_date
)
VALUES
( " . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
" . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ')';
db_query_bound( $query, Array( $this->project_id, $this->reporter_id, $this->handler_id, $this->duplicate_id, $this->priority, $this->severity, $this->reproducibility, $t_status, $this->resolution, $this->projection, $this->category_id, db_now(), db_now(), $this->eta, $t_text_id, $this->os, $this->os_build, $this->platform, $this->version, $this->build, $this->profile_id, $this->summary, $this->view_state, $this->sponsorship_total, $this->sticky, $this->fixed_in_version, $this->target_version, $this->due_date ) );
$this->id = db_insert_id( $t_bug_table );
# log new bug
history_log_event_special( $this->id, NEW_BUG );
# log changes, if any (compare happens in history_log_event_direct)
history_log_event_direct( $this->id, 'status', $t_original_status, $t_status );
history_log_event_direct( $this->id, 'handler_id', 0, $this->handler_id );
return $this->id;
}
/**
* Update a bug from the given data structure
* If the third parameter is true, also update the longer strings table
* @param bool p_update_extended
* @param bool p_bypass_email Default false, set to true to avoid generating emails (if sending elsewhere)
* @return bool (always true)
* @access public
*/
function update( $p_update_extended = false, $p_bypass_mail = false ) {
self::validate( $p_update_extended );
$c_bug_id = $this->id;
if( is_blank( $this->due_date ) ) {
$this->due_date = date_get_null();
}
$t_old_data = bug_get( $this->id, true );
$t_bug_table = db_get_table( 'mantis_bug_table' );
# Update all fields
# Ignore date_submitted and last_updated since they are pulled out
# as unix timestamps which could confuse the history log and they
# shouldn't get updated like this anyway. If you really need to change
# them use bug_set_field()
$query = "UPDATE $t_bug_table
SET project_id=" . db_param() . ', reporter_id=' . db_param() . ",
handler_id=" . db_param() . ', duplicate_id=' . db_param() . ",
priority=" . db_param() . ', severity=' . db_param() . ",
reproducibility=" . db_param() . ', status=' . db_param() . ",
resolution=" . db_param() . ', projection=' . db_param() . ",
category_id=" . db_param() . ', eta=' . db_param() . ",
os=" . db_param() . ', os_build=' . db_param() . ",
platform=" . db_param() . ', version=' . db_param() . ",
build=" . db_param() . ', fixed_in_version=' . db_param() . ',';
$t_fields = Array(
$this->project_id, $this->reporter_id,
$this->handler_id, $this->duplicate_id,
$this->priority, $this->severity,
$this->reproducibility, $this->status,
$this->resolution, $this->projection,
$this->category_id, $this->eta,
$this->os, $this->os_build,
$this->platform, $this->version,
$this->build, $this->fixed_in_version,
);
$t_roadmap_updated = false;
if( access_has_project_level( config_get( 'roadmap_update_threshold' ) ) ) {
$query .= "
target_version=" . db_param() . ",";
$t_fields[] = $this->target_version;
$t_roadmap_updated = true;
}
$query .= "
view_state=" . db_param() . ",
summary=" . db_param() . ",
sponsorship_total=" . db_param() . ",
sticky=" . db_param() . ",
due_date=" . db_param() . "
WHERE id=" . db_param();
$t_fields[] = $this->view_state;
$t_fields[] = $this->summary;
$t_fields[] = $this->sponsorship_total;
$t_fields[] = (bool)$this->sticky;
$t_fields[] = $this->due_date;
$t_fields[] = $this->id;
db_query_bound( $query, $t_fields );
bug_clear_cache( $this->id );
# log changes
history_log_event_direct( $c_bug_id, 'project_id', $t_old_data->project_id, $this->project_id );
history_log_event_direct( $c_bug_id, 'reporter_id', $t_old_data->reporter_id, $this->reporter_id );
history_log_event_direct( $c_bug_id, 'handler_id', $t_old_data->handler_id, $this->handler_id );
history_log_event_direct( $c_bug_id, 'priority', $t_old_data->priority, $this->priority );
history_log_event_direct( $c_bug_id, 'severity', $t_old_data->severity, $this->severity );
history_log_event_direct( $c_bug_id, 'reproducibility', $t_old_data->reproducibility, $this->reproducibility );
history_log_event_direct( $c_bug_id, 'status', $t_old_data->status, $this->status );
history_log_event_direct( $c_bug_id, 'resolution', $t_old_data->resolution, $this->resolution );
history_log_event_direct( $c_bug_id, 'projection', $t_old_data->projection, $this->projection );
history_log_event_direct( $c_bug_id, 'category', category_full_name( $t_old_data->category_id, false ), category_full_name( $this->category_id, false ) );
history_log_event_direct( $c_bug_id, 'eta', $t_old_data->eta, $this->eta );
history_log_event_direct( $c_bug_id, 'os', $t_old_data->os, $this->os );
history_log_event_direct( $c_bug_id, 'os_build', $t_old_data->os_build, $this->os_build );
history_log_event_direct( $c_bug_id, 'platform', $t_old_data->platform, $this->platform );
history_log_event_direct( $c_bug_id, 'version', $t_old_data->version, $this->version );
history_log_event_direct( $c_bug_id, 'build', $t_old_data->build, $this->build );
history_log_event_direct( $c_bug_id, 'fixed_in_version', $t_old_data->fixed_in_version, $this->fixed_in_version );
if( $t_roadmap_updated ) {
history_log_event_direct( $c_bug_id, 'target_version', $t_old_data->target_version, $this->target_version );
}
history_log_event_direct( $c_bug_id, 'view_state', $t_old_data->view_state, $this->view_state );
history_log_event_direct( $c_bug_id, 'summary', $t_old_data->summary, $this->summary );
history_log_event_direct( $c_bug_id, 'sponsorship_total', $t_old_data->sponsorship_total, $this->sponsorship_total );
history_log_event_direct( $c_bug_id, 'sticky', $t_old_data->sticky, $this->sticky );
history_log_event_direct( $c_bug_id, 'due_date', ( $t_old_data->due_date != date_get_null() ) ? $t_old_data->due_date : null, ( $this->due_date != date_get_null() ) ? $this->due_date : null );
# Update extended info if requested
if( $p_update_extended ) {
$t_bug_text_table = db_get_table( 'mantis_bug_text_table' );
$t_bug_text_id = bug_get_field( $c_bug_id, 'bug_text_id' );
$query = "UPDATE $t_bug_text_table
SET description=" . db_param() . ",
steps_to_reproduce=" . db_param() . ",
additional_information=" . db_param() . "
WHERE id=" . db_param();
db_query_bound( $query, Array( $this->description, $this->steps_to_reproduce, $this->additional_information, $t_bug_text_id ) );
bug_text_clear_cache( $c_bug_id );
$t_current_user = auth_get_current_user_id();
if( $t_old_data->description != $this->description ) {
if ( bug_revision_count( $c_bug_id, REV_DESCRIPTION ) < 1 ) {
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_DESCRIPTION, $t_old_data->description, 0, $t_old_data->last_updated );
}
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_DESCRIPTION, $this->description );
history_log_event_special( $c_bug_id, DESCRIPTION_UPDATED, $t_revision_id );
}
if( $t_old_data->steps_to_reproduce != $this->steps_to_reproduce ) {
if ( bug_revision_count( $c_bug_id, REV_STEPS_TO_REPRODUCE ) < 1 ) {
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_STEPS_TO_REPRODUCE, $t_old_data->steps_to_reproduce, 0, $t_old_data->last_updated );
}
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_STEPS_TO_REPRODUCE, $this->steps_to_reproduce );
history_log_event_special( $c_bug_id, STEP_TO_REPRODUCE_UPDATED, $t_revision_id );
}
if( $t_old_data->additional_information != $this->additional_information ) {
if ( bug_revision_count( $c_bug_id, REV_ADDITIONAL_INFO ) < 1 ) {
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_ADDITIONAL_INFO, $t_old_data->additional_information, 0, $t_old_data->last_updated );
}
$t_revision_id = bug_revision_add( $c_bug_id, $t_current_user, REV_ADDITIONAL_INFO, $this->additional_information );
history_log_event_special( $c_bug_id, ADDITIONAL_INFO_UPDATED, $t_revision_id );
}
}
# Update the last update date
bug_update_date( $c_bug_id );
# allow bypass if user is sending mail separately
if( false == $p_bypass_mail ) {
# bug assigned
if( $t_old_data->handler_id != $this->handler_id ) {
email_generic( $c_bug_id, 'owner', 'email_notification_title_for_action_bug_assigned' );
return true;
}
# status changed
if( $t_old_data->status != $this->status ) {
$t_status = MantisEnum::getLabel( config_get( 'status_enum_string' ), $this->status );
$t_status = str_replace( ' ', '_', $t_status );
email_generic( $c_bug_id, $t_status, 'email_notification_title_for_status_bug_' . $t_status );
return true;
}
# @todo handle priority change if it requires special handling
# generic update notification
email_generic( $c_bug_id, 'updated', 'email_notification_title_for_action_bug_updated' );
}
return true;
}
}
$g_cache_bug = array();
$g_cache_bug_text = array();
/**
* Cache a database result-set containing full contents of bug_table row.
* @param array p_bug_database_result database row containing all columns from mantis_bug_table
* @param array p_stats (optional) array representing bugnote stats
* @return array returns an array representing the bug row if bug exists
* @access public
*/
function bug_cache_database_result( $p_bug_database_result, $p_stats = null ) {
global $g_cache_bug;
if( !is_array( $p_bug_database_result ) || isset( $g_cache_bug[(int) $p_bug_database_result['id']] ) ) {
return $g_cache_bug[(int) $p_bug_database_result['id']];
}
return bug_add_to_cache( $p_bug_database_result, $p_stats );
}
/**
* Cache a bug row if necessary and return the cached copy
* @param array p_bug_id id of bug to cache from mantis_bug_table
* @param array p_trigger_errors set to true to trigger an error if the bug does not exist.
* @return bool|array returns an array representing the bug row if bug exists or false if bug does not exist
* @access public
* @uses database_api.php
*/
function bug_cache_row( $p_bug_id, $p_trigger_errors = true ) {
global $g_cache_bug;
if( isset( $g_cache_bug[$p_bug_id] ) ) {
return $g_cache_bug[$p_bug_id];
}
$c_bug_id = (int) $p_bug_id;
$t_bug_table = db_get_table( 'mantis_bug_table' );
$query = "SELECT *
FROM $t_bug_table
WHERE id=" . db_param();
$result = db_query_bound( $query, Array( $c_bug_id ) );
if( 0 == db_num_rows( $result ) ) {
$g_cache_bug[$c_bug_id] = false;
if( $p_trigger_errors ) {
error_parameters( $p_bug_id );
trigger_error( ERROR_BUG_NOT_FOUND, ERROR );
} else {
return false;
}
}
$row = db_fetch_array( $result );
return bug_add_to_cache( $row );
}
/**
* Cache a set of bugs
* @param array p_bug_id_array integer array representing bug ids to cache
* @return null
* @access public
* @uses database_api.php
*/
function bug_cache_array_rows( $p_bug_id_array ) {
global $g_cache_bug;
$c_bug_id_array = array();
foreach( $p_bug_id_array as $t_bug_id ) {
if( !isset( $g_cache_bug[(int) $t_bug_id] ) ) {
$c_bug_id_array[] = (int) $t_bug_id;
}
}
if( empty( $c_bug_id_array ) ) {
return;
}
$t_bug_table = db_get_table( 'mantis_bug_table' );
$query = "SELECT *
FROM $t_bug_table
WHERE id IN (" . implode( ',', $c_bug_id_array ) . ')';
$result = db_query_bound( $query );
while( $row = db_fetch_array( $result ) ) {
bug_add_to_cache( $row );
}
return;
}
/**
* Inject a bug into the bug cache
* @param array p_bug_row bug row to cache
* @param array p_stats bugnote stats to cache
* @return null
* @access private
*/
function bug_add_to_cache( $p_bug_row, $p_stats = null ) {
global $g_cache_bug;
$g_cache_bug[(int) $p_bug_row['id']] = $p_bug_row;
if( !is_null( $p_stats ) ) {
$g_cache_bug[(int) $p_bug_row['id']]['_stats'] = $p_stats;
}
return $g_cache_bug[(int) $p_bug_row['id']];
}
/**
* Clear a bug from the cache or all bugs if no bug id specified.
* @param int bug id to clear (optional)
* @return null
* @access public
*/
function bug_clear_cache( $p_bug_id = null ) {
global $g_cache_bug;
if( null === $p_bug_id ) {
$g_cache_bug = array();
} else {
unset( $g_cache_bug[(int) $p_bug_id] );
}
return true;
}
/**
* Cache a bug text row if necessary and return the cached copy
* @param int p_bug_id integer bug id to retrieve text for
* @param bool p_trigger_errors If the second parameter is true (default), trigger an error if bug text not found.
* @return bool|array returns false if not bug text found or array of bug text
* @access public
* @uses database_api.php
*/
function bug_text_cache_row( $p_bug_id, $p_trigger_errors = true ) {
global $g_cache_bug_text;
$c_bug_id = (int) $p_bug_id;
$t_bug_table = db_get_table( 'mantis_bug_table' );
$t_bug_text_table = db_get_table( 'mantis_bug_text_table' );
if( isset( $g_cache_bug_text[$c_bug_id] ) ) {
return $g_cache_bug_text[$c_bug_id];
}
$query = "SELECT bt.*
FROM $t_bug_text_table bt, $t_bug_table b
WHERE b.id=" . db_param() . " AND
b.bug_text_id = bt.id";
$result = db_query_bound( $query, Array( $c_bug_id ) );
if( 0 == db_num_rows( $result ) ) {
$g_cache_bug_text[$c_bug_id] = false;
if( $p_trigger_errors ) {
error_parameters( $p_bug_id );
trigger_error( ERROR_BUG_NOT_FOUND, ERROR );
} else {
return false;
}
}
$row = db_fetch_array( $result );
$g_cache_bug_text[$c_bug_id] = $row;
return $row;
}
/**
* Clear a bug's bug text from the cache or all bug text if no bug id specified.
* @param int bug id to clear (optional)
* @return null
* @access public
*/
function bug_text_clear_cache( $p_bug_id = null ) {
global $g_cache_bug_text;
if( null === $p_bug_id ) {
$g_cache_bug_text = array();
} else {
unset( $g_cache_bug_text[(int) $p_bug_id] );
}
return true;
}
/**
* Check if a bug exists
* @param int p_bug_id integer representing bug id
* @return bool true if bug exists, false otherwise
* @access public
*/
function bug_exists( $p_bug_id ) {
if( false == bug_cache_row( $p_bug_id, false ) ) {
return false;
} else {
return true;
}
}
/**
* Check if a bug exists. If it doesn't then trigger an error
* @param int p_bug_id integer representing bug id
* @return null
* @access public
*/
function bug_ensure_exists( $p_bug_id ) {
if( !bug_exists( $p_bug_id ) ) {
error_parameters( $p_bug_id );
trigger_error( ERROR_BUG_NOT_FOUND, ERROR );
}
}
/**
* check if the given user is the reporter of the bug
* @param int p_bug_id integer representing bug id
* @param int p_user_id integer reprenting a user id
* @return bool return true if the user is the reporter, false otherwise
* @access public
*/
function bug_is_user_reporter( $p_bug_id, $p_user_id ) {
if( bug_get_field( $p_bug_id, 'reporter_id' ) == $p_user_id ) {
return true;
} else {
return false;
}
}
/**
* check if the given user is the handler of the bug
* @param int p_bug_id integer representing bug id
* @param int p_user_id integer reprenting a user id
* @return bool return true if the user is the handler, false otherwise
* @access public
*/
function bug_is_user_handler( $p_bug_id, $p_user_id ) {
if( bug_get_field( $p_bug_id, 'handler_id' ) == $p_user_id ) {
return true;
} else {
return false;
}
}
/**
* Check if the bug is readonly and shouldn't be modified
* For a bug to be readonly the status has to be >= bug_readonly_status_threshold and
* current user access level < update_readonly_bug_threshold.
* @param int p_bug_id integer representing bug id
* @return bool
* @access public
* @uses access_api.php
* @uses config_api.php
*/
function bug_is_readonly( $p_bug_id ) {
$t_status = bug_get_field( $p_bug_id, 'status' );
if( $t_status < config_get( 'bug_readonly_status_threshold' ) ) {
return false;
}
if( access_has_bug_level( config_get( 'update_readonly_bug_threshold' ), $p_bug_id ) ) {
return false;
}
return true;
}
/**
* Check if a given bug is resolved
* @param int p_bug_id integer representing bug id
* @return bool true if bug is resolved, false otherwise
* @access public
* @uses config_api.php
*/
function bug_is_resolved( $p_bug_id ) {
$t_status = bug_get_field( $p_bug_id, 'status' );
return( $t_status >= config_get( 'bug_resolved_status_threshold' ) );
}
/**
* Check if a given bug is overdue
* @param int p_bug_id integer representing bug id
* @return bool true if bug is overdue, false otherwise
* @access public
* @uses database_api.php
*/
function bug_is_overdue( $p_bug_id ) {
$t_due_date = bug_get_field( $p_bug_id, 'due_date' );
if( !date_is_null( $t_due_date ) ) {
$t_now = db_now();
if( $t_now > $t_due_date ) {
if( !bug_is_resolved( $p_bug_id ) ) {
return true;
}
}
}
return false;
}
/**
* Validate workflow state to see if bug can be moved to requested state
* @param int p_bug_status current bug status
* @param int p_wanted_status new bug status
* @return bool
* @access public
* @uses config_api.php
* @uses utility_api.php
*/
function bug_check_workflow( $p_bug_status, $p_wanted_status ) {
$t_status_enum_workflow = config_get( 'status_enum_workflow' );
if( count( $t_status_enum_workflow ) < 1 ) {
# workflow not defined, use default enum
return true;
}
if ( $p_bug_status == $p_wanted_status ) {
# no change in state, allow the transition
return true;
}
# workflow defined - find allowed states
$t_allowed_states = $t_status_enum_workflow[$p_bug_status];
return MantisEnum::hasValue( $t_allowed_states, $p_wanted_status );
}
/**
* Copy a bug from one project to another. Also make copies of issue notes, attachments, history,
* email notifications etc.
* @todo Not managed FTP file upload
* @param array p_bug_id integer representing bug id
* @param int p_target_project_id
* @param bool p_copy_custom_fields
* @param bool p_copy_relationships
* @return int representing the new bugid
* @access public
*/
function bug_copy( $p_bug_id, $p_target_project_id = null, $p_copy_custom_fields = false, $p_copy_relationships = false, $p_copy_history = false, $p_copy_attachments = false, $p_copy_bugnotes = false, $p_copy_monitoring_users = false ) {
global $g_db;
$t_mantis_custom_field_string_table = db_get_table( 'mantis_custom_field_string_table' );
$t_mantis_bug_file_table = db_get_table( 'mantis_bug_file_table' );
$t_mantis_bugnote_table = db_get_table( 'mantis_bugnote_table' );
$t_mantis_bugnote_text_table = db_get_table( 'mantis_bugnote_text_table' );
$t_mantis_bug_history_table = db_get_table( 'mantis_bug_history_table' );
$t_mantis_db = $g_db;
$t_bug_id = db_prepare_int( $p_bug_id );
$t_target_project_id = db_prepare_int( $p_target_project_id );
$t_bug_data = bug_get( $t_bug_id, true );
# retrieve the project id associated with the bug
if(( $p_target_project_id == null ) || is_blank( $p_target_project_id ) ) {
$t_target_project_id = $t_bug_data->project_id;
}
$t_bug_data->project_id = $t_target_project_id;
$t_new_bug_id = $t_bug_data->create();
# MASC ATTENTION: IF THE SOURCE BUG HAS TO HANDLER THE bug_create FUNCTION CAN TRY TO AUTO-ASSIGN THE BUG
# WE FORCE HERE TO DUPLICATE THE SAME HANDLER OF THE SOURCE BUG
# @todo VB: Shouldn't we check if the handler in the source project is also a handler in the destination project?
bug_set_field( $t_new_bug_id, 'handler_id', $t_bug_data->handler_id );
bug_set_field( $t_new_bug_id, 'duplicate_id', $t_bug_data->duplicate_id );
bug_set_field( $t_new_bug_id, 'status', $t_bug_data->status );
bug_set_field( $t_new_bug_id, 'resolution', $t_bug_data->resolution );
bug_set_field( $t_new_bug_id, 'projection', $t_bug_data->projection );
bug_set_field( $t_new_bug_id, 'date_submitted', $t_bug_data->date_submitted );
bug_set_field( $t_new_bug_id, 'last_updated', $t_bug_data->last_updated );
bug_set_field( $t_new_bug_id, 'eta', $t_bug_data->eta );
bug_set_field( $t_new_bug_id, 'fixed_in_version', $t_bug_data->fixed_in_version );
bug_set_field( $t_new_bug_id, 'target_version', $t_bug_data->target_version );
bug_set_field( $t_new_bug_id, 'sponsorship_total', 0 );
bug_set_field( $t_new_bug_id, 'sticky', 0 );
bug_set_field( $t_new_bug_id, 'due_date', $t_bug_data->due_date );
# COPY CUSTOM FIELDS
if( $p_copy_custom_fields ) {
$query = "SELECT field_id, bug_id, value
FROM $t_mantis_custom_field_string_table
WHERE bug_id=" . db_param();
$result = db_query_bound( $query, Array( $t_bug_id ) );
$t_count = db_num_rows( $result );
for( $i = 0;$i < $t_count;$i++ ) {
$t_bug_custom = db_fetch_array( $result );
$c_field_id = db_prepare_int( $t_bug_custom['field_id'] );
$c_new_bug_id = db_prepare_int( $t_new_bug_id );
$c_value = $t_bug_custom['value'];
$query = "INSERT INTO $t_mantis_custom_field_string_table
( field_id, bug_id, value )
VALUES (" . db_param() . ', ' . db_param() . ', ' . db_param() . ')';
db_query_bound( $query, Array( $c_field_id, $c_new_bug_id, $c_value ) );
}
}
# Copy Relationships
if( $p_copy_relationships ) {
relationship_copy_all( $t_bug_id, $t_new_bug_id );
}
# Copy bugnotes
if( $p_copy_bugnotes ) {
$query = "SELECT *
FROM $t_mantis_bugnote_table
WHERE bug_id=" . db_param();
$result = db_query_bound( $query, Array( $t_bug_id ) );
$t_count = db_num_rows( $result );
for( $i = 0;$i < $t_count;$i++ ) {
$t_bug_note = db_fetch_array( $result );
$t_bugnote_text_id = $t_bug_note['bugnote_text_id'];
$query2 = "SELECT *
FROM $t_mantis_bugnote_text_table
WHERE id=" . db_param();
$result2 = db_query_bound( $query2, Array( $t_bugnote_text_id ) );
$t_count2 = db_num_rows( $result2 );
$t_bugnote_text_insert_id = -1;
if( $t_count2 > 0 ) {
$t_bugnote_text = db_fetch_array( $result2 );
$query2 = "INSERT INTO $t_mantis_bugnote_text_table
( note )
VALUES ( " . db_param() . ' )';
db_query_bound( $query2, Array( $t_bugnote_text['note'] ) );
$t_bugnote_text_insert_id = db_insert_id( $t_mantis_bugnote_text_table );
}
$query2 = "INSERT INTO $t_mantis_bugnote_table
( bug_id, reporter_id, bugnote_text_id, view_state, date_submitted, last_modified )
VALUES ( " . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ')';
db_query_bound( $query2, Array( $t_new_bug_id, $t_bug_note['reporter_id'], $t_bugnote_text_insert_id, $t_bug_note['view_state'], $t_bug_note['date_submitted'], $t_bug_note['last_modified'] ) );
}
}
# Copy attachments
if( $p_copy_attachments ) {
file_copy_attachments( $t_bug_id , $t_new_bug_id );
}
# Copy users monitoring bug
if( $p_copy_monitoring_users ) {
bug_monitor_copy( $t_bug_id, $t_new_bug_id );
}
# COPY HISTORY
history_delete( $t_new_bug_id ); # should history only be deleted inside the if statement below?
if( $p_copy_history ) {
$query = "SELECT *
FROM $t_mantis_bug_history_table
WHERE bug_id = " . db_param();
$result = db_query_bound( $query, Array( $t_bug_id ) );
$t_count = db_num_rows( $result );
for( $i = 0;$i < $t_count;$i++ ) {
$t_bug_history = db_fetch_array( $result );
$query = "INSERT INTO $t_mantis_bug_history_table
( user_id, bug_id, date_modified, field_name, old_value, new_value, type )
VALUES ( " . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . ",
" . db_param() . " );";
db_query_bound( $query, Array( $t_bug_history['user_id'], $t_new_bug_id, $t_bug_history['date_modified'], $t_bug_history['field_name'], $t_bug_history['old_value'], $t_bug_history['new_value'], $t_bug_history['type'] ) );
}
}
return $t_new_bug_id;
}
/**
* Moves an issue from a project to another.
* @todo Validate with sub-project / category inheritance scenarios.
* @todo Fix #11687: Bugs with attachments that are moved will lose attachments.
* @param int p_bug_id The bug to be moved.
* @param int p_target_project_id The target project to move the bug to.
* @access public
*/
function bug_move( $p_bug_id, $p_target_project_id ) {
// Move the issue to the new project.
bug_set_field( $p_bug_id, 'project_id', $p_target_project_id );
// Check if the category for the issue is global or not.
$t_category_id = bug_get_field( $p_bug_id, 'category_id' );
$t_category_project_id = category_get_field( $t_category_id, 'project_id' );
// If not global, then attempt mapping it to the new project.
if ( $t_category_project_id != ALL_PROJECTS && !project_hierarchy_inherit_parent( $p_target_project_id, $t_category_project_id ) ) {
// Map by name
$t_category_name = category_get_field( $t_category_id, 'name' );
$t_target_project_category_id = category_get_id_by_name( $t_category_name, $p_target_project_id, /* triggerErrors */ false );
if ( $t_target_project_category_id === false ) {
// Use default category after moves, since there is no match by name.
$t_target_project_category_id = config_get( 'default_category_for_moves' );
}
bug_set_field( $p_bug_id, 'category_id', $t_target_project_category_id );
}
}
/**
* allows bug deletion :
* delete the bug, bugtext, bugnote, and bugtexts selected
* @param array p_bug_id integer representing bug id
* @return bool (always true)
* @access public
*/
function bug_delete( $p_bug_id ) {
$c_bug_id = (int) $p_bug_id;
$t_bug_table = db_get_table( 'mantis_bug_table' );
$t_bug_text_table = db_get_table( 'mantis_bug_text_table' );
# call pre-deletion custom function
helper_call_custom_function( 'issue_delete_validate', array( $p_bug_id ) );
# log deletion of bug
history_log_event_special( $p_bug_id, BUG_DELETED, bug_format_id( $p_bug_id ) );
email_bug_deleted( $p_bug_id );
# call post-deletion custom function. We call this here to allow the custom function to access the details of the bug before
# they are deleted from the database given it's id. The other option would be to move this to the end of the function and
# provide it with bug data rather than an id, but this will break backward compatibility.
helper_call_custom_function( 'issue_delete_notify', array( $p_bug_id ) );
# Unmonitor bug for all users
bug_unmonitor( $p_bug_id, null );
# Delete custom fields
custom_field_delete_all_values( $p_bug_id );
# Delete bugnotes
bugnote_delete_all( $p_bug_id );
# Delete all sponsorships
sponsorship_delete( sponsorship_get_all_ids( $p_bug_id ) );
# MASC RELATIONSHIP
# we delete relationships even if the feature is currently off.
relationship_delete_all( $p_bug_id );
# MASC RELATIONSHIP
# Delete files
file_delete_attachments( $p_bug_id );
# Detach tags
tag_bug_detach_all( $p_bug_id, false );
# Delete the bug history
history_delete( $p_bug_id );
# Delete bug info revisions
bug_revision_delete( $p_bug_id );
# Delete the bugnote text
$t_bug_text_id = bug_get_field( $p_bug_id, 'bug_text_id' );
$query = "DELETE FROM $t_bug_text_table
WHERE id=" . db_param();
db_query_bound( $query, Array( $t_bug_text_id ) );
# Delete the bug entry
$query = "DELETE FROM $t_bug_table
WHERE id=" . db_param();
db_query_bound( $query, Array( $c_bug_id ) );
bug_clear_cache( $p_bug_id );
bug_text_clear_cache( $p_bug_id );
# db_query errors on failure so:
return true;
}
/**
* Delete all bugs associated with a project
* @param array p_project_id integer representing a projectid
* @return bool always true
* @access public
* @uses database_api.php
*/
function bug_delete_all( $p_project_id ) {
$c_project_id = (int) $p_project_id;
$t_bug_table = db_get_table( 'mantis_bug_table' );
$query = "SELECT id
FROM $t_bug_table
WHERE project_id=" . db_param();
$result = db_query_bound( $query, array( $c_project_id ) );
$bug_count = db_num_rows( $result );
for( $i = 0;$i < $bug_count;$i++ ) {
$row = db_fetch_array( $result );
bug_delete( $row['id'] );
}
# @todo should we check the return value of each bug_delete() and
# return false if any of them return false? Presumable bug_delete()
# will eventually trigger an error on failure so it won't matter...
return true;
}
/**
* Returns the extended record of the specified bug, this includes
* the bug text fields
* @todo include reporter name and handler name, the problem is that
* handler can be 0, in this case no corresponding name will be
* found. Use equivalent of (+) in Oracle.
* @param int p_bug_id integer representing bug id
* @return array
* @access public
*/
function bug_get_extended_row( $p_bug_id ) {
$t_base = bug_cache_row( $p_bug_id );
$t_text = bug_text_cache_row( $p_bug_id );
# merge $t_text first so that the 'id' key has the bug id not the bug text id
return array_merge( $t_text, $t_base );
}
/**
* Returns the record of the specified bug
* @param int p_bug_id integer representing bug id
* @return array
* @access public
*/
function bug_get_row( $p_bug_id ) {
return bug_cache_row( $p_bug_id );
}
/**
* Returns an object representing the specified bug
* @param int p_bug_id integer representing bug id
* @param bool p_get_extended included extended information (including bug_text)
* @return object BugData Object
* @access public
*/
function bug_get( $p_bug_id, $p_get_extended = false ) {
if( $p_get_extended ) {
$row = bug_get_extended_row( $p_bug_id );
} else {
$row = bug_get_row( $p_bug_id );
}
$t_bug_data = new BugData;
$t_bug_data->loadrow( $row );
return $t_bug_data;
}
function bug_row_to_object( $p_row ) {
$t_bug_data = new BugData;
$t_bug_data->loadrow( $p_row );
return $t_bug_data;
}
/**
* return the specified field of the given bug
* if the field does not exist, display a warning and return ''
* @param int p_bug_id integer representing bug id
* @param string p_fieldname field name
* @return string
* @access public
*/
function bug_get_field( $p_bug_id, $p_field_name ) {
$row = bug_get_row( $p_bug_id );
if( isset( $row[$p_field_name] ) ) {
return $row[$p_field_name];
} else {
error_parameters( $p_field_name );
trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
return '';
}
}
/**
* return the specified text field of the given bug
* if the field does not exist, display a warning and return ''
* @param int p_bug_id integer representing bug id
* @param string p_fieldname field name
* @return string
* @access public
*/
function bug_get_text_field( $p_bug_id, $p_field_name ) {
$row = bug_text_cache_row( $p_bug_id );
if( isset( $row[$p_field_name] ) ) {
return $row[$p_field_name];
} else {
error_parameters( $p_field_name );
trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
return '';
}
}
/**
* return the bug summary
* this is a wrapper for the custom function
* @param int p_bug_id integer representing bug id
* @param int p_context representing SUMMARY_CAPTION, SUMMARY_FIELD
* @return string
* @access public
* @uses helper_api.php
*/
function bug_format_summary( $p_bug_id, $p_context ) {
return helper_call_custom_function( 'format_issue_summary', array( $p_bug_id, $p_context ) );
}
/**
* return the timestamp for the most recent time at which a bugnote
* associated with the bug was modified
* @param int p_bug_id integer representing bug id
* @return bool|int false or timestamp in integer format representing newest bugnote timestamp
* @access public
* @uses database_api.php
*/
function bug_get_newest_bugnote_timestamp( $p_bug_id ) {
$c_bug_id = db_prepare_int( $p_bug_id );
$t_bugnote_table = db_get_table( 'mantis_bugnote_table' );
$query = "SELECT last_modified
FROM $t_bugnote_table
WHERE bug_id=" . db_param() . "
ORDER BY last_modified DESC";
$result = db_query_bound( $query, Array( $c_bug_id ), 1 );
$row = db_result( $result );
if( false === $row ) {
return false;
} else {
return $row;
}
}
/**
* return the timestamp for the most recent time at which a bugnote
* associated with the bug was modified and the total bugnote
* count in one db query
* @param int p_bug_id integer representing bug id
* @return object consisting of bugnote stats
* @access public
* @uses database_api.php
*/
function bug_get_bugnote_stats( $p_bug_id ) {
global $g_cache_bug;
$c_bug_id = db_prepare_int( $p_bug_id );
if( !is_null( $g_cache_bug[$c_bug_id]['_stats'] ) ) {
if( $g_cache_bug[$c_bug_id]['_stats'] === false ) {
return false;
} else {
$t_stats = $g_cache_bug[$c_bug_id]['_stats'];
}
return $t_stats;
}
$t_bugnote_table = db_get_table( 'mantis_bugnote_table' );
$query = "SELECT last_modified
FROM $t_bugnote_table
WHERE bug_id=" . db_param() . "
ORDER BY last_modified DESC";
$result = db_query_bound( $query, Array( $c_bug_id ) );
$row = db_fetch_array( $result );
if( false === $row ) {
return false;
}
$t_stats['last_modified'] = $row['last_modified'];
$t_stats['count'] = db_num_rows( $result );
return $t_stats;
}
/**
* Get array of attachments associated with the specified bug id. The array will be
* sorted in terms of date added (ASC). The array will include the following fields:
* id, title, diskfile, filename, filesize, file_type, date_added, user_id.
* @param int p_bug_id integer representing bug id
* @return array array of results or null
* @access public
* @uses database_api.php
* @uses file_api.php
*/
function bug_get_attachments( $p_bug_id ) {
$c_bug_id = db_prepare_int( $p_bug_id );
$t_bug_file_table = db_get_table( 'mantis_bug_file_table' );
$query = "SELECT id, title, diskfile, filename, filesize, file_type, date_added, user_id
FROM $t_bug_file_table
WHERE bug_id=" . db_param() . "
ORDER BY date_added";
$db_result = db_query_bound( $query, Array( $c_bug_id ) );
$num_files = db_num_rows( $db_result );
$t_result = array();
for( $i = 0;$i < $num_files;$i++ ) {
$t_result[] = db_fetch_array( $db_result );
}
return $t_result;
}
# ===================================
# Data Modification
# ===================================
/**
* Set the value of a bug field
* @param int p_bug_id integer representing bug id
* @param string p_field_name pre-defined field name
* @param any p_value value to set
* @return bool (always true)
* @access public
* @uses database_api.php
* @uses history_api.php
*/
function bug_set_field( $p_bug_id, $p_field_name, $p_value ) {
$c_bug_id = db_prepare_int( $p_bug_id );
$c_value = null;
switch( $p_field_name ) {
# bool
case 'sticky':
$c_value = $p_value;
break;
# int
case 'project_id':
case 'reporter_id':
case 'handler_id':
case 'duplicate_id':
case 'priority':
case 'severity':
case 'reproducibility':
case 'status':
case 'resolution':
case 'projection':
case 'category_id':
case 'eta':
case 'view_state':
case 'profile_id':
case 'sponsorship_total':
$c_value = (int) $p_value;
break;
# string
case 'os':
case 'os_build':
case 'platform':
case 'version':
case 'fixed_in_version':
case 'target_version':
case 'build':
case 'summary':
$c_value = $p_value;
break;
# dates
case 'last_updated':
case 'date_submitted':
case 'due_date':
if ( !is_numeric( $p_value ) ) {
trigger_error( ERROR_GENERIC, ERROR );
}
$c_value = $p_value;
break;
default:
trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
break;
}
$t_current_value = bug_get_field( $p_bug_id, $p_field_name );
# return if status is already set
if( $c_value == $t_current_value ) {
return true;
}
$t_bug_table = db_get_table( 'mantis_bug_table' );
# Update fields
$query = "UPDATE $t_bug_table
SET $p_field_name=" . db_param() . "
WHERE id=" . db_param();
db_query_bound( $query, Array( $c_value, $c_bug_id ) );
# updated the last_updated date
bug_update_date( $p_bug_id );
# log changes except for duplicate_id which is obsolete and should be removed in
# MantisBT 1.3.
switch( $p_field_name ) {
case 'duplicate_id':
break;
case 'category_id':
history_log_event_direct( $p_bug_id, 'category', category_full_name( $t_current_value, false ), category_full_name( $c_value, false ) );
break;
default:
history_log_event_direct( $p_bug_id, $p_field_name, $t_current_value, $c_value );
}
bug_clear_cache( $p_bug_id );
return true;
}
/**
* assign the bug to the given user
* @param array p_bug_id_array integer array representing bug ids to cache
* @return null
* @access public
* @uses database_api.php
*/
function bug_assign( $p_bug_id, $p_user_id, $p_bugnote_text = '', $p_bugnote_private = false ) {
$c_bug_id = db_prepare_int( $p_bug_id );
$c_user_id = db_prepare_int( $p_user_id );
if(( $c_user_id != NO_USER ) && !access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $p_user_id ) ) {
trigger_error( ERROR_USER_DOES_NOT_HAVE_REQ_ACCESS );
}
# extract current information into history variables
$h_status = bug_get_field( $p_bug_id, 'status' );
$h_handler_id = bug_get_field( $p_bug_id, 'handler_id' );
if(( ON == config_get( 'auto_set_status_to_assigned' ) ) && ( NO_USER != $p_user_id ) ) {
$t_ass_val = config_get( 'bug_assigned_status' );
} else {
$t_ass_val = $h_status;
}
$t_bug_table = db_get_table( 'mantis_bug_table' );
if(( $t_ass_val != $h_status ) || ( $p_user_id != $h_handler_id ) ) {
# get user id
$query = "UPDATE $t_bug_table
SET handler_id=" . db_param() . ", status=" . db_param() . "
WHERE id=" . db_param();
db_query_bound( $query, Array( $c_user_id, $t_ass_val, $c_bug_id ) );
# log changes
history_log_event_direct( $c_bug_id, 'status', $h_status, $t_ass_val );
history_log_event_direct( $c_bug_id, 'handler_id', $h_handler_id, $p_user_id );
# Add bugnote if supplied ignore false return
bugnote_add( $p_bug_id, $p_bugnote_text, 0, $p_bugnote_private, 0, '', NULL, FALSE );
# updated the last_updated date
bug_update_date( $p_bug_id );
bug_clear_cache( $p_bug_id );
# send assigned to email
email_assign( $p_bug_id );
}
return true;
}
/**
* close the given bug
* @param int p_bug_id
* @param string p_bugnote_text
* @param bool p_bugnote_private
* @param string p_time_tracking
* @return bool (always true)
* @access public
*/
function bug_close( $p_bug_id, $p_bugnote_text = '', $p_bugnote_private = false, $p_time_tracking = '0:00' ) {
$p_bugnote_text = trim( $p_bugnote_text );
# Add bugnote if supplied ignore a false return
# 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_closed_status_threshold' ) );
email_close( $p_bug_id );
email_relationship_child_closed( $p_bug_id );
return true;
}
/**
* resolve the given bug
* @return bool (alawys true)
* @access public
*/
function bug_resolve( $p_bug_id, $p_resolution, $p_fixed_in_version = '', $p_bugnote_text = '', $p_duplicate_id = null, $p_handler_id = null, $p_bugnote_private = false, $p_time_tracking = '0:00' ) {
$c_resolution = (int) $p_resolution;
$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 );
$t_duplicate = !is_blank( $p_duplicate_id ) && ( $p_duplicate_id != 0 );
if( $t_duplicate ) {
if( $p_bug_id == $p_duplicate_id ) {
trigger_error( ERROR_BUG_DUPLICATE_SELF, ERROR );
# never returns
}
# the related bug exists...
bug_ensure_exists( $p_duplicate_id );
# check if there is other relationship between the bugs...
$t_id_relationship = relationship_same_type_exists( $p_bug_id, $p_duplicate_id, BUG_DUPLICATE );
if( $t_id_relationship > 0 ) {
# Update the relationship
relationship_update( $t_id_relationship, $p_bug_id, $p_duplicate_id, BUG_DUPLICATE );
# Add log line to the history (both bugs)
history_log_event_special( $p_bug_id, BUG_REPLACE_RELATIONSHIP, BUG_DUPLICATE, $p_duplicate_id );
history_log_event_special( $p_duplicate_id, BUG_REPLACE_RELATIONSHIP, BUG_HAS_DUPLICATE, $p_bug_id );
} else if ( $t_id_relationship != -1 ) {
# Add the new relationship
relationship_add( $p_bug_id, $p_duplicate_id, BUG_DUPLICATE );
# Add log line to the history (both bugs)
history_log_event_special( $p_bug_id, BUG_ADD_RELATIONSHIP, BUG_DUPLICATE, $p_duplicate_id );
history_log_event_special( $p_duplicate_id, BUG_ADD_RELATIONSHIP, BUG_HAS_DUPLICATE, $p_bug_id );
} # else relationship is -1 - same type exists, do nothing
# Copy list of users monitoring the duplicate bug to the original bug
bug_monitor_copy( $p_bug_id, $p_duplicate_id );
bug_set_field( $p_bug_id, 'duplicate_id', (int) $p_duplicate_id );
}
bug_set_field( $p_bug_id, 'status', config_get( 'bug_resolved_status_threshold' ) );
bug_set_field( $p_bug_id, 'fixed_in_version', $p_fixed_in_version );
bug_set_field( $p_bug_id, 'resolution', $c_resolution );
# only set handler if specified explicitly or if bug was not assigned to a handler
if( null == $p_handler_id ) {
if( bug_get_field( $p_bug_id, 'handler_id' ) == 0 ) {
$p_handler_id = auth_get_current_user_id();
bug_set_field( $p_bug_id, 'handler_id', $p_handler_id );
}
} else {
bug_set_field( $p_bug_id, 'handler_id', $p_handler_id );
}
email_resolved( $p_bug_id );
email_relationship_child_resolved( $p_bug_id );
if( $c_resolution >= config_get( 'bug_resolution_fixed_threshold' ) &&
$c_resolution < config_get( 'bug_resolution_not_fixed_threshold' ) ) {
twitter_issue_resolved( $p_bug_id );
}
return true;
}
/**
* 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;
}
/**
* updates the last_updated field
* @param int p_bug_id integer representing bug ids
* @return bool (always true)
* @access public
* @uses database_api.php
*/
function bug_update_date( $p_bug_id ) {
$c_bug_id = (int) $p_bug_id;
$t_bug_table = db_get_table( 'mantis_bug_table' );
$query = "UPDATE $t_bug_table
SET last_updated= " . db_param() . "
WHERE id=" . db_param();
db_query_bound( $query, Array( db_now(), $c_bug_id ) );
bug_clear_cache( $c_bug_id );
return true;
}
/**
* enable monitoring of this bug for the user
* @param int p_bug_id integer representing bug ids
* @param int p_user_id integer representing user ids
* @return true if successful, false if unsuccessful
* @access public
* @uses database_api.php
* @uses history_api.php
* @uses user_api.php
*/
function bug_monitor( $p_bug_id, $p_user_id ) {
$c_bug_id = (int) $p_bug_id;
$c_user_id = (int) $p_user_id;
# Make sure we aren't already monitoring this bug
if( user_is_monitoring_bug( $c_user_id, $c_bug_id ) ) {
return true;
}
# Don't let the anonymous user monitor bugs
if ( user_is_anonymous( $c_user_id ) ) {
return false;
}
$t_bug_monitor_table = db_get_table( 'mantis_bug_monitor_table' );
# Insert monitoring record
$query = 'INSERT INTO ' . $t_bug_monitor_table . '( user_id, bug_id ) VALUES (' . db_param() . ',' . db_param() . ')';
db_query_bound( $query, Array( $c_user_id, $c_bug_id ) );
# log new monitoring action
history_log_event_special( $c_bug_id, BUG_MONITOR, $c_user_id );
# updated the last_updated date
bug_update_date( $p_bug_id );
email_monitor_added( $p_bug_id, $p_user_id );
return true;
}
/**
* Returns the list of users monitoring the specified bug
*
* @param int $p_bug_id
*/
function bug_get_monitors( $p_bug_id ) {
if ( ! access_has_bug_level( config_get( 'show_monitor_list_threshold' ), $p_bug_id ) ) {
return Array();
}
$c_bug_id = db_prepare_int( $p_bug_id );
$t_bug_monitor_table = db_get_table( 'mantis_bug_monitor_table' );
$t_user_table = db_get_table( 'mantis_user_table' );
# get the bugnote data
$query = "SELECT user_id, enabled
FROM $t_bug_monitor_table m, $t_user_table u
WHERE m.bug_id=" . db_param() . " AND m.user_id = u.id
ORDER BY u.realname, u.username";
$result = db_query_bound($query, Array( $c_bug_id ) );
$num_users = db_num_rows($result);
$t_users = array();
for ( $i = 0; $i < $num_users; $i++ ) {
$row = db_fetch_array( $result );
$t_users[$i] = $row['user_id'];
}
user_cache_array_rows( $t_users );
return $t_users;
}
/**
* Copy list of users monitoring a bug to the monitor list of a second bug
* @param int p_source_bug_id integer representing the bug ID of the source bug
* @param int p_dest_bug_id integer representing the bug ID of the destination bug
* @return bool (always true)
* @access public
* @uses database_api.php
* @uses history_api.php
* @uses user_api.php
*/
function bug_monitor_copy( $p_source_bug_id, $p_dest_bug_id ) {
$c_source_bug_id = (int)$p_source_bug_id;
$c_dest_bug_id = (int)$p_dest_bug_id;
$t_bug_monitor_table = db_get_table( 'mantis_bug_monitor_table' );
$query = 'SELECT user_id
FROM ' . $t_bug_monitor_table . '
WHERE bug_id = ' . db_param();
$result = db_query_bound( $query, Array( $c_source_bug_id ) );
$t_count = db_num_rows( $result );
for( $i = 0; $i < $t_count; $i++ ) {
$t_bug_monitor = db_fetch_array( $result );
if ( !user_is_monitoring_bug( $t_bug_monitor['user_id'], $c_dest_bug_id ) ) {
$query = 'INSERT INTO ' . $t_bug_monitor_table . ' ( user_id, bug_id )
VALUES ( ' . db_param() . ', ' . db_param() . ' )';
db_query_bound( $query, Array( $t_bug_monitor['user_id'], $c_dest_bug_id ) );
history_log_event_special( $c_dest_bug_id, BUG_MONITOR, $t_bug_monitor['user_id'] );
}
}
}
/**
* disable monitoring of this bug for the user
* if $p_user_id = null, then bug is unmonitored for all users.
* @param int p_bug_id integer representing bug ids
* @param int p_user_id integer representing user ids
* @return bool (always true)
* @access public
* @uses database_api.php
* @uses history_api.php
*/
function bug_unmonitor( $p_bug_id, $p_user_id ) {
$c_bug_id = (int) $p_bug_id;
$c_user_id = (int) $p_user_id;
$t_bug_monitor_table = db_get_table( 'mantis_bug_monitor_table' );
# Delete monitoring record
$query = 'DELETE FROM ' . $t_bug_monitor_table . ' WHERE bug_id = ' . db_param();
$db_query_params[] = $c_bug_id;
if( $p_user_id !== null ) {
$query .= " AND user_id = " . db_param();
$db_query_params[] = $c_user_id;
}
db_query_bound( $query, $db_query_params );
# log new un-monitor action
history_log_event_special( $c_bug_id, BUG_UNMONITOR, $c_user_id );
# updated the last_updated date
bug_update_date( $p_bug_id );
return true;
}
/**
* Pads the bug id with the appropriate number of zeros.
* @param int p_bug_id
* @return string
* @access public
* @uses config_api.php
*/
function bug_format_id( $p_bug_id ) {
$t_padding = config_get( 'display_bug_padding' );
$t_string = utf8_str_pad( $p_bug_id, $t_padding, '0', STR_PAD_LEFT );
return event_signal( 'EVENT_DISPLAY_BUG_ID', $t_string, array( $p_bug_id ) );
}
SOAP-API-Ensure-that-helpergetcurrentproject-resolve.patch (1,900 bytes)
From f8a11be3e8ba04c0e1d399793d4aad83f9dcf179 Fri, 23 Sep 2011 11:00:15 +0300
From: Robert Munteanu <robert.munteanu@gmail.com>
Date: Fri, 23 Sep 2011 10:56:40 +0300
Subject: [PATCH] SOAP API: Ensure that helper_get_current_project() resolves to the requested project
Fixes #13324: Adding or updating issue with mylyn causes error #13
diff --git a/api/soap/mc_issue_api.php b/api/soap/mc_issue_api.php
index e99cb0f..05d3f4c 100644
--- a/api/soap/mc_issue_api.php
+++ b/api/soap/mc_issue_api.php
@@ -508,6 +508,9 @@
* @return integer The id of the created issue.
*/
function mc_issue_add( $p_username, $p_password, $p_issue ) {
+
+ 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();
@@ -516,6 +519,7 @@
$t_project = $p_issue['project'];
$t_project_id = mci_get_project_id( $t_project );
+ $g_project_override = $t_project_id; // ensure that helper_get_current_project() calls resolve to this project id
if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) {
return mci_soap_fault_access_denied( $t_user_id );
@@ -682,6 +686,8 @@
* @return integer The id of the created issue.
*/
function mc_issue_update( $p_username, $p_password, $p_issue_id, $p_issue ) {
+ 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();
@@ -696,6 +702,8 @@
if( !mci_has_readwrite_access( $t_user_id, $t_project_id ) ) {
return mci_soap_fault_access_denied( $t_user_id );
}
+
+ $g_project_override = $t_project_id; // ensure that helper_get_current_project() calls resolve to this project id
$t_project_id = mci_get_project_id( $p_issue['project'] );
$t_reporter_id = isset( $p_issue['reporter'] ) ? mci_get_user_id( $p_issue['reporter'] ) : $t_user_id ; | ||||
|
What is the access level of the user? Do you have any security-related changes on your installation? |
|
|
The user is MANAGER globally. No its a standard installation. |
|
|
I've performed the following steps on a stock installation:
All tasks were completed without error. Also, the changes that you have linked to are not present in MantisBT 1.2.8 - no check for fixed_in_version is done. Either way, I don't see how this would affect a user with a global manager level, as it would not fail the handle_bug_threshold check. There's definitely something non-standard about your setup, so please provide some more information. |
|
|
ok, what information do you need? So this is the check and the line which causes the error. |
|
|
I see different checks. The commit you reference has removed a check for handle_bug_threshold when the fixed_in_version field is set. The error you see is triggered by setting the target_version, which checks for the roadmap_update_threshold . The question remains why a manager user can not update the target_version . Can you confirm that you can create the target version for an issue using the web interface? |
|
|
This is correct. Using the web interface the user can normally add the issue with target version or update the target version. |
|
|
Can you try the attached patch? This should make sure that the checks in bug_data check the correct project. This should work if the user has a manager role for the project, but not globally. Apply it to your installation and let me know if it works. |
|
|
This patch seems to work. No error response. |
|
|
Great, thanks for confirming. |
|
|
Marking as 'acknowledged' not resolved/closed to track that change gets ported to master-2.0.x branch |
|
|
MantisBT: master e7815ec1 2011-09-22 20:56 Details Diff |
SOAP API: Ensure that helper_get_current_project() resolves to the requested project Fixes 0013324: Adding or updating issue with mylyn causes error #13 |
Affected Issues 0013324 |
|
| mod - api/soap/mc_issue_api.php | Diff File | ||
|
MantisBT: master-1.2.x f8a11be3 2011-09-22 20:56 Details Diff |
SOAP API: Ensure that helper_get_current_project() resolves to the requested project Fixes 0013324: Adding or updating issue with mylyn causes error #13 |
Affected Issues 0013324 |
|
| mod - api/soap/mc_issue_api.php | Diff File | ||