Skip to content

Commit

Permalink
Implement IssueRelationshipAddCommand
Browse files Browse the repository at this point in the history
Fixes #23865
  • Loading branch information
vboctor committed Jan 28, 2018
1 parent 386328e commit b0bd801
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 51 deletions.
63 changes: 12 additions & 51 deletions bug_relationship_add.php
Expand Up @@ -24,81 +24,42 @@
* @link http://www.mantisbt.org
*
* @uses core.php
* @uses access_api.php
* @uses bug_api.php
* @uses config_api.php
* @uses constant_inc.php
* @uses email_api.php
* @uses error_api.php
* @uses form_api.php
* @uses gpc_api.php
* @uses helper_api.php
* @uses history_api.php
* @uses lang_api.php
* @uses print_api.php
* @uses relationship_api.php
*/

require_once( 'core.php' );
require_api( 'access_api.php' );
require_api( 'bug_api.php' );
require_api( 'config_api.php' );
require_api( 'constant_inc.php' );
require_api( 'email_api.php' );
require_api( 'error_api.php' );
require_api( 'form_api.php' );
require_api( 'gpc_api.php' );
require_api( 'helper_api.php' );
require_api( 'history_api.php' );
require_api( 'lang_api.php' );
require_api( 'print_api.php' );
require_api( 'relationship_api.php' );

form_security_validate( 'bug_relationship_add' );

$f_rel_type = gpc_get_int( 'rel_type' );
$f_src_bug_id = gpc_get_int( 'src_bug_id' );
$f_dest_bug_id_string = gpc_get_string( 'dest_bug_id' );

# user has access to update the bug...
access_ensure_bug_level( config_get( 'update_bug_threshold' ), $f_src_bug_id );
$t_dest_bug_id_string = str_replace( ',', '|', $f_dest_bug_id_string );
$t_dest_bug_id_array = explode( '|', $t_dest_bug_id_string );

$f_dest_bug_id_string = str_replace( ',', '|', $f_dest_bug_id_string );
foreach( $t_dest_bug_id_array as $t_dest_bug_id ) {
$t_data = array(
'query' => array( 'issue_id' => $f_src_bug_id ),
'payload' => array(
'type' => array( 'id' => $f_rel_type ),
'issue' => array( 'id' => $t_dest_bug_id )
)
);

$f_dest_bug_id_array = explode( '|', $f_dest_bug_id_string );

foreach( $f_dest_bug_id_array as $f_dest_bug_id ) {
$f_dest_bug_id = (int)$f_dest_bug_id;

# source and destination bugs are the same bug...
if( $f_src_bug_id == $f_dest_bug_id ) {
trigger_error( ERROR_RELATIONSHIP_SAME_BUG, ERROR );
}

# the related bug exists...
bug_ensure_exists( $f_dest_bug_id );
$t_dest_bug = bug_get( $f_dest_bug_id, true );

# bug is not read-only...
if( bug_is_readonly( $f_src_bug_id ) ) {
error_parameters( $f_src_bug_id );
trigger_error( ERROR_BUG_READ_ONLY_ACTION_DENIED, ERROR );
}

# user can access to the related bug at least as viewer...
if( !access_has_bug_level( config_get( 'view_bug_threshold', null, null, $t_dest_bug->project_id ), $f_dest_bug_id ) ) {
error_parameters( $f_dest_bug_id );
trigger_error( ERROR_RELATIONSHIP_ACCESS_LEVEL_TO_DEST_BUG_TOO_LOW, ERROR );
}

$t_bug = bug_get( $f_src_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;
}

relationship_upsert( $f_src_bug_id, $f_dest_bug_id, $f_rel_type );
$t_command = new IssueRelationshipAddCommand( $t_data );
$t_command->execute();
}

form_security_purge( 'bug_relationship_add' );
Expand Down
206 changes: 206 additions & 0 deletions core/commands/IssueRelationshipAddCommand.php
@@ -0,0 +1,206 @@
<?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/>.

require_api( 'authentication_api.php' );
require_api( 'bug_api.php' );
require_api( 'constant_inc.php' );
require_api( 'config_api.php' );
require_api( 'helper_api.php' );
require_api( 'user_api.php' );

use Mantis\Exceptions\ClientException;

/**
* A command that adds a relationship to an issue. If a relationship already
* exists with the target issue, it will be updated.
*
* Sample:
*
* {
* "query": { "issue_id": 1234 },
* "payload": {
* "issue": {
* "id": 1235
* },
* "type": {
* "id": 1,
* "name": "related-to"
* }
* }
* }
*
* Relation Type IDs: check "bug relationship constants" in core/constants_inc.php
*/
class IssueRelationshipAddCommand extends Command {
/**
* The relationship type id
*
* @var integer
*/
private $typeId;

/**
* The source issue
*
* @var BugData
*/
private $sourceIssue = null;

/**
* The target issue
*
* @var BugData
*/
private $targetIssue = null;

/**
* Constructor
*
* @param array $p_data The command data.
*/
function __construct( array $p_data ) {
parent::__construct( $p_data );
}

/**
* Validate the data.
*/
function validate() {
$t_type = $this->payload( 'type', array( 'id' => BUG_RELATED ) );
$this->typeId = $this->getRelationTypeId( $t_type );

$t_source_issue_id = helper_parse_issue_id( $this->query( 'issue_id' ) );
$t_target_issue_ref = $this->payload( 'issue' );

if( !isset( $t_target_issue_ref['id'] ) ) {
throw new ClientException(
'Invalid issue id',
ERROR_INVALID_FIELD_VALUE,
array( 'issue_id' )
);
}

$t_target_issue_id = helper_parse_issue_id( $t_target_issue_ref['id'], 'target_issue_id' );

$this->sourceIssue = bug_get( $t_source_issue_id, true );

$t_update_threshold = config_get( 'update_bug_threshold', null, null, $this->sourceIssue->project_id );

# Ensure user has access to update the source issue
if( !access_has_bug_level( $t_update_threshold, $t_source_issue_id ) ) {
throw new ClientException(
'Access denied to add relationship',
ERROR_ACCESS_DENIED
);
}

# Ensure that source and target issues are not the same
if( $t_source_issue_id == $t_target_issue_id ) {
throw new ClientException(
"Issue can't have relationship to itself",
ERROR_RELATIONSHIP_SAME_BUG
);
}

# Ensure that related issue exists and gets its information
$this->targetIssue = bug_get( $t_target_issue_id, true );

# Ensure source issue is not read-only
if( bug_is_readonly( $t_source_issue_id ) ) {
throw new ClientException(
sprintf( "Issue %d is read-only", $t_source_issue_id ),
ERROR_BUG_READ_ONLY_ACTION_DENIED,
array( $t_source_issue_id )
);
}

# Ensure that user can view target issue
$t_view_threshold = config_get( 'view_bug_threshold', null, null, $this->targetIssue->project_id );
if( !access_has_bug_level( $t_view_threshold, $t_target_issue_id ) ) {
throw new ClientException(
sprintf( "Issue %d is read-only", $t_target_issue_id ),
ERROR_RELATIONSHIP_ACCESS_LEVEL_TO_DEST_BUG_TOO_LOW,
array( $t_target_issue_id )
);
}
}

/**
* Process the command.
*
* @returns array Command response
*/
protected function process() {
if( $this->sourceIssue->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.
global $g_project_override;
$g_project_override = $this->sourceIssue->project_id;
}

# Create or update the relationship
$t_relationship_id = relationship_upsert( $this->sourceIssue->id, $this->targetIssue->id, $this->typeId );

return array( 'id' => $t_relationship_id );
}

/**
* Get relationship type id from relationship type reference.
*
* @param array The relationship type reference with id, name or both.
* @return integer relationship type id.
*/
private function getRelationTypeId( $p_relationship_type ) {
if( isset( $p_relationship_type['id'] ) ) {
$t_type_id = (int)$p_relationship_type['id'];
} else if( isset( $p_relationship_type['name'] ) ) {
global $g_relationships;
switch( $p_relationship_type['name'] ) {
case 'related-to':
$t_type_id = BUG_RELATED;
break;
case 'duplicate-of':
$t_type_id = BUG_DUPLICATE;
break;
case 'parent-of':
$t_type_id = BUG_DEPENDANT;
break;
case 'child-of':
$t_type_id = BUG_BLOCKS;
break;
case 'has-duplicate':
$t_type_id = BUG_HAS_DUPLICATE;
break;
default:
throw new ClientException(
sprintf( "Unknown relationship type '%s'", $p_relationship_type['name'] ),
ERROR_INVALID_FIELD_VALUE,
array( 'relationship_type' )
);
}
} else {
throw new ClientException(
'Invalid relationship type',
ERROR_INVALID_FIELD_VALUE,
array( 'relationship_type' )
);
}

return $t_type_id;
}
}

0 comments on commit b0bd801

Please sign in to comment.