View Issue Details

IDProjectCategoryView StatusLast Update
0008094mantisbtadministrationpublic2021-05-17 03:22
Reporterplofte Assigned Tovboctor  
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionfixed 
PlatformmantisOSlinuxOS Version1.1.0a3
Product Version1.1.0a3 
Fixed in Version1.1.0a4 
Summary0008094: Managing versions / release schedule accross multiple projects.
Description

I manage multiple projects and use the same release schedule across them all. I like to set up a version to match the release schedule for the "roadmap" and Change log features.

To make my life easier I would like to be able to "Copy Versions From" and "Copy Versions To" much like I do with categories.

Attached are the changes I made to mantis to accomplish this.

TagsNo tags attached.
Attached Files
manage_proj_ver_copy.php (1,681 bytes)   
<?php
	# Mantis - a php based bugtracking system
	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
	# Copyright (C) 2002 - 2004  Mantis Team   - mantisbt-dev@lists.sourceforge.net
	# This program is distributed under the terms and conditions of the GPL
	# See the README and LICENSE files for details

	# --------------------------------------------------------
	# $Id: manage_proj_ver_copy.php,v 1.21 2005/02/27 15:33:01 jlatour Exp $
	# --------------------------------------------------------
?>
<?php
	require_once( 'core.php' );

	$t_core_path = config_get( 'core_path' );

	require_once( $t_core_path.'version_api.php' );
?>
<?php
	$f_project_id		= gpc_get_int( 'project_id' );
	$f_other_project_id	= gpc_get_int( 'other_project_id' );
	$f_copy_from		= gpc_get_bool( 'copy_from' );
	$f_copy_to			= gpc_get_bool( 'copy_to' );

	access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );
	access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_other_project_id );

	if ( $f_copy_from ) {
	  $t_src_project_id = $f_other_project_id;
	  $t_dst_project_id = $f_project_id;
	} else if ( $f_copy_to ) {
	  $t_src_project_id = $f_project_id;
	  $t_dst_project_id = $f_other_project_id;
	} else {
		trigger_error( ERROR_VERSION_NO_ACTION, ERROR );
	}

	$rows = version_get_all_rows( $t_src_project_id );

	foreach ( $rows as $row ) {
		$t_version = $row['version'];

		if ( version_is_unique( $t_dst_project_id, $t_version ) ) {
			version_add( $t_dst_project_id, $t_version );
		}
	}

	print_header_redirect( 'manage_proj_edit_page.php?project_id=' . $f_project_id );
?>
manage_proj_ver_copy.php (1,681 bytes)   
manage_proj_edit_page.php (21,035 bytes)   
<?php
	# Mantis - a php based bugtracking system
	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
	# Copyright (C) 2002 - 2004  Mantis Team   - mantisbt-dev@lists.sourceforge.net
	# This program is distributed under the terms and conditions of the GPL
	# See the README and LICENSE files for details

	# --------------------------------------------------------
	# $Id: manage_proj_edit_page.php,v 1.98 2007/03/06 07:05:18 vboctor Exp $
	# --------------------------------------------------------
?>
<?php
	require_once( 'core.php' );

	$t_core_path = config_get( 'core_path' );

	require_once( $t_core_path . 'category_api.php' );
	require_once( $t_core_path . 'version_api.php' );
	require_once( $t_core_path . 'custom_field_api.php' );
	require_once( $t_core_path . 'icon_api.php' );
?>
<?php
	$f_project_id = gpc_get_int( 'project_id' );

	access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );

	$row = project_get_row( $f_project_id );
?>
<?php html_page_top1() ?>
<?php html_page_top2() ?>

<?php print_manage_menu( 'manage_proj_edit_page.php' ) ?>

<br />


<!-- PROJECT PROPERTIES -->
<div align="center">
<form method="post" action="manage_proj_update.php">
<table class="width75" cellspacing="1">

<!-- Title -->
<tr>
	<td class="form-title" colspan="2">
		<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
		<?php echo lang_get( 'edit_project_title' ) ?>
	</td>
</tr>

<!-- Name -->
<tr <?php echo helper_alternate_class() ?>>
	<td class="category" width="25%">
		<?php echo lang_get( 'project_name' ) ?>
	</td>
	<td width="75%">
		<input type="text" name="name" size="50" maxlength="128" value="<?php echo string_attribute( $row['name'] ) ?>" />
	</td>
</tr>

<!-- Status -->
<tr <?php echo helper_alternate_class() ?>>
	<td class="category">
		<?php echo lang_get( 'status' ) ?>
	</td>
	<td>
		<select name="status">
		<?php print_enum_string_option_list( 'project_status', $row['status'] ) ?>
		</select>
	</td>
</tr>

<!-- Enabled -->
<tr <?php echo helper_alternate_class() ?>>
	<td class="category">
		<?php echo lang_get( 'enabled' ) ?>
	</td>
	<td>
		<input type="checkbox" name="enabled" <?php check_checked( $row['enabled'], ON ); ?> />
	</td>
</tr>

<!-- View Status (public/private) -->
<tr <?php echo helper_alternate_class() ?>>
	<td class="category">
		<?php echo lang_get( 'view_status' ) ?>
	</td>
	<td>
		<select name="view_state">
			<?php print_enum_string_option_list( 'view_state', $row['view_state']) ?>
		</select>
	</td>
</tr>

<!-- File upload path (if uploading is enabled) -->
<?php if ( file_is_uploading_enabled() ) { ?>
<tr <?php echo helper_alternate_class() ?>>
	<td class="category">
		<?php echo lang_get( 'upload_file_path' ) ?>
	</td>
	<td>
		<input type="text" name="file_path" size="50" maxlength="250" value="<?php echo string_attribute( $row['file_path'] ) ?>" />
	</td>
</tr>
<?php } ?>

<!-- Description -->
<tr <?php echo helper_alternate_class() ?>>
	<td class="category">
		<?php echo lang_get( 'description' ) ?>
	</td>
	<td>
		<textarea name="description" cols="60" rows="5" wrap="virtual"><?php echo string_textarea( $row['description'] ) ?></textarea>
	</td>
</tr>

<!-- Submit Button -->
<tr>
	<td>&nbsp;</td>
	<td>
		<input type="submit" class="button" value="<?php echo lang_get( 'update_project_button' ) ?>" />
	</td>
</tr>
</table>
</form>
</div>

<br />

<!-- PROJECT DELETE -->
<?php
# You must have global permissions to delete projects
if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?>
<div class="border-center">
	<form method="post" action="manage_proj_delete.php">
		<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
		<input type="submit" class="button" value="<?php echo lang_get( 'delete_project_button' ) ?>" />
	</form>
</div>
<?php } ?>

<br />

<?php
	# reset the class counter
	helper_alternate_class( 0 );
?>

<!-- SUBPROJECTS -->
<div align="center">
<table class="width75" cellspacing="1">

<!-- Title -->
<tr>
	<td class="form-title" colspan="6">
		<?php echo lang_get( 'subprojects' ) ?>
                <?php
	                # Check the user's global access level before allowing project creation
	                if ( access_has_global_level ( config_get( 'create_project_threshold' ) ) ) {
	                        print_button( 'manage_proj_create_page.php?parent_id=' . $f_project_id, lang_get( 'create_new_subproject_link' ) );
	                }
                ?>
	</td>
</tr>

<!-- Subprojects -->
<?php
	$t_subproject_ids = current_user_get_accessible_subprojects( $f_project_id, /* show_disabled */ true );

	if ( Array() != $t_subproject_ids ) {
?>
<tr class="row-category">
	<td width="20%">
		<?php echo lang_get( 'name' ) ?>
	</td>
	<td width="10%">
		<?php echo lang_get( 'status' ) ?>
	</td>
	<td width="10%">
		<?php echo lang_get( 'enabled' ) ?>
	</td>
	<td width="10%">
		<?php echo lang_get( 'view_status' ) ?>
	</td>
	<td width="30%">
		<?php echo lang_get( 'description' ) ?>
	</td>
	<td width="20%">
		<?php echo lang_get( 'actions' ) ?>
	</td>
</tr>

<?php
		foreach ( $t_subproject_ids as $t_subproject_id ) {
			$t_subproject = project_get_row( $t_subproject_id );
?>
<tr <?php echo helper_alternate_class() ?>>
	<td>
		<a href="manage_proj_edit_page.php?project_id=<?php echo $t_subproject['id'] ?>"><?php echo string_display( $t_subproject['name'] ) ?></a>
	</td>
	<td>
		<?php echo get_enum_element( 'project_status', $t_subproject['status'] ) ?>
	</td>
	<td>
		<?php echo trans_bool( $t_subproject['enabled'] ) ?>
	</td>
	<td>
		<?php echo get_enum_element( 'project_view_state', $t_subproject['view_state'] ) ?>
	</td>
	<td>
		<?php echo string_display_links( $t_subproject['description'] ) ?>
	</td>
	<td class="center">
		<?php
				print_button( 'manage_proj_edit_page.php?project_id=' . $t_subproject['id'], lang_get( 'edit_link' ) );
				echo '&nbsp;';
				print_button( 'manage_proj_subproj_delete.php?project_id=' . $f_project_id . '&amp;subproject_id=' . $t_subproject['id'], lang_get( 'unlink_link' ) );
		?>
	</td>
</tr>
<?php
		} # End of foreach loop over subprojects
	} # End of hiding subproject listing if there are no subprojects
?>

<!-- Add subproject -->
<tr>
	<td class="left" colspan="2">
		<form method="post" action="manage_proj_subproj_add.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<select name="subproject_id">
<?php
	$t_all_subprojects = project_hierarchy_get_subprojects( $f_project_id, /* $p_show_disabled */ true );
	$t_all_subprojects[] = $f_project_id;
	$t_manage_access = config_get( 'manage_project_threshold' );

	$t_projects = project_get_all_rows();

	$t_projects = multi_sort( $t_projects, 'name', ASC );

	foreach ( $t_projects as $t_project ) {
		if ( in_array( $t_project['id'], $t_all_subprojects ) ||
            in_array( $f_project_id, project_hierarchy_get_all_subprojects( $t_project['id'] ) ) ||
            ! access_has_project_level( $t_manage_access, $t_project['id'] ) ) {
                continue;
		}
?>
				<option value="<?php echo $t_project['id'] ?>"><?php echo string_attribute( $t_project['name'] ) ?></option>
<?php
	} # End looping over projects
?>
			</select>
			<input type="submit" value="<?php echo lang_get('add_subproject'); ?>">
		</form>
	</td>
</tr>

</table>
</div>

<br />

<!-- PROJECT CATEGORIES -->
<a name="categories" />
<div align="center">
<table class="width75" cellspacing="1">

<!-- Title -->
<tr>
	<td class="form-title" colspan="3">
		<?php echo lang_get( 'categories' ) ?>
	</td>
</tr>
<?php
	$t_categories = category_get_all_rows( $f_project_id );

	if ( count( $t_categories ) > 0 ) {
?>
		<tr class="row-category">
			<td>
				<?php echo lang_get( 'category' ) ?>
			</td>
			<td>
				<?php echo lang_get( 'assign_to' ) ?>
			</td>
			<td class="center">
				<?php echo lang_get( 'actions' ) ?>
			</td>
		</tr>
<?php
	}

	foreach ( $t_categories as $t_category ) {
		$t_name = $t_category['category'];

		if ( NO_USER != $t_category['user_id'] && user_exists( $t_category['user_id'] )) {
			$t_user_name = user_get_name( $t_category['user_id'] );
		} else {
			$t_user_name = '';
		}
?>
<!-- Repeated Info Row -->
		<tr <?php echo helper_alternate_class() ?>>
			<td>
				<?php echo string_display( $t_name ) ?>
			</td>
			<td>
				<?php echo $t_user_name ?>
			</td>
			<td class="center">
				<?php
					$t_name = urlencode( $t_name );

					print_button( 'manage_proj_cat_edit_page.php?project_id=' . $f_project_id . '&amp;category=' . $t_name, lang_get( 'edit_link' ) );
					echo '&nbsp;';
					print_button( 'manage_proj_cat_delete.php?project_id=' . $f_project_id . '&amp;category=' . $t_name, lang_get( 'delete_link' ) );
				?>
			</td>
		</tr>
<?php
	} # end for loop
?>

<!-- Add Category Form -->
<tr>
	<td class="left" colspan="3">
		<form method="post" action="manage_proj_cat_add.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<input type="text" name="category" size="32" maxlength="64" />
			<input type="submit" class="button" value="<?php echo lang_get( 'add_category_button' ) ?>" />
		</form>
	</td>
</tr>

<!-- Copy Categories Form -->
<tr>
	<td class="left" colspan="3">
		<form method="post" action="manage_proj_cat_copy.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<select name="other_project_id">
				<?php print_project_option_list( null, false, $f_project_id ); ?>
			</select>
			<input type="submit" name="copy_from" class="button" value="<?php echo lang_get( 'copy_categories_from' ) ?>" />
			<input type="submit" name="copy_to" class="button" value="<?php echo lang_get( 'copy_categories_to' ) ?>" />
		</form>
	</td>
</tr>
</table>

<br />

<?php
	# reset the class counter
	helper_alternate_class( 0 );
?>

<!-- PROJECT VERSIONS -->
<a name="versions" />
<table class="width75" cellspacing="1">

<!-- Title -->
<tr>
	<td class="form-title" colspan="3">
		<?php echo lang_get( 'versions' ) ?>
	</td>
</tr>
<?php
	$t_versions = version_get_all_rows( $f_project_id );

	if ( count( $t_versions ) > 0 ) {
?>
		<tr class="row-category">
			<td>
				<?php echo lang_get( 'version' ) ?>
			</td>
			<td class="center">
				<?php echo lang_get( 'released' ) ?>
			</td>
			<td class="center">
				<?php echo lang_get( 'timestamp' ) ?>
			</td>
			<td class="center">
				<?php echo lang_get( 'actions' ) ?>
			</td>
		</tr>
<?php
	}

	foreach ( $t_versions as $t_version ) {
		$t_name = $t_version['version'];
		$t_released = $t_version['released'];
		$t_date_order = $t_version['date_order'];
		$t_date_formatted = string_format_complete_date( $t_version['date_order'] );
?>
<!-- Repeated Info Rows -->
		<tr <?php echo helper_alternate_class() ?>>
			<td>
				<?php echo string_display( $t_name ) ?>
			</td>
			<td class="center">
				<?php echo trans_bool( $t_released ) ?>
			</td>
			<td class="center">
				<?php echo $t_date_formatted ?>
			</td>
			<td class="center">
				<?php
					$t_version_id = version_get_id( $t_name, $f_project_id );

					print_button( 'manage_proj_ver_edit_page.php?version_id=' . $t_version_id, lang_get( 'edit_link' ) );
					echo '&nbsp;';
					print_button( 'manage_proj_ver_delete.php?version_id=' . $t_version_id, lang_get( 'delete_link' ) );
				?>
			</td>
		</tr>
<?php
	} # end for loop
?>

<!-- Version Add Form -->
<tr>
	<td class="left" colspan="3">
		<form method="post" action="manage_proj_ver_add.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<input type="text" name="version" size="32" maxlength="64" />
			<input type="submit" name="add_version" class="button" value="<?php echo lang_get( 'add_version_button' ) ?>" />
			<input type="submit" name="add_and_edit_version" class="button" value="<?php echo lang_get( 'add_and_edit_version_button' ) ?>" />
		</form>
	</td>
</tr>
<tr>
	<td class="left" colspan="3">
		<form method="post" action="manage_proj_ver_copy.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<select name="other_project_id">
				<?php print_project_option_list( null, false, $f_project_id ); ?>
			</select>
			<input type="submit" name="copy_from" class="button" value="<?php echo lang_get( 'copy_version_from' ) ?>" />
			<input type="submit" name="copy_to" class="button" value="<?php echo lang_get( 'copy_version_to' ) ?>" />
		</form>
	</td>
</tr>
</table>
</div>


<?php
	# reset the class counter
	helper_alternate_class( 0 );
?>

<!-- PROJECT CUSTOM FIELD -->
<a name="customfields" />

<?php
# You need either global permissions or project-specific permissions to link
#  custom fields
if ( access_has_project_level( config_get( 'custom_field_link_threshold' ), $f_project_id ) &&
	( count( custom_field_get_ids() ) > 0 ) ) {
?>
	<br />
	<div align="center">
	<table class="width75" cellspacing="1">
	<tr>
		<td class="form-title" colspan="3">
			<?php echo lang_get( 'custom_fields_setup' ) ?>
		</td>
	</tr>
	<?php
		$t_custom_fields = custom_field_get_linked_ids( $f_project_id );

		if ( count( $t_custom_fields ) > 0 ) {
	?>
			<tr class="row-category">
				<td width="50%">
					<?php echo lang_get( 'custom_field' ) ?>
				</td>
				<td width="25%">
					<?php echo lang_get( 'custom_field_sequence' ) ?>
				</td>
				<td class="center" width="25%">
					<?php echo lang_get( 'actions' ); ?>
				</td>
			</tr>
	<?php
		}

		foreach( $t_custom_fields as $t_field_id ) {
			$t_desc = custom_field_get_definition( $t_field_id );
	?>
			<tr <?php echo helper_alternate_class() ?>>
				<td>
					<?php echo string_display( $t_desc['name'] ) ?>
				</td>
				<td>
<form method="post" action="manage_proj_custom_field_update.php">
	<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
	<input type="hidden" name="field_id" value="<?php echo $t_field_id ?>" />
	<input type="text" name="sequence" value="<?php echo custom_field_get_sequence( $t_field_id, $f_project_id ) ?>" size="2" />
	<input type="submit" class="button-small" value="<?php echo lang_get( 'update' ) ?>" />
</form>
				</td>
				<td class="center">
				<?php
					# You need global permissions to edit custom field defs
					print_button( "manage_proj_custom_field_remove.php?field_id=$t_field_id&amp;project_id=$f_project_id", lang_get( 'remove_link' ) );
				?>
				</td>
			</tr>
	<?php
		} # end for loop
	?>
	<tr>
		<td class="left" colspan="3">
			<form method="post" action="manage_proj_custom_field_add_existing.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<select name="field_id">
				<?php
					$t_custom_fields = custom_field_get_ids();

					foreach( $t_custom_fields as $t_field_id )
					{
						if( !custom_field_is_linked( $t_field_id, $f_project_id ) ) {
							$t_desc = custom_field_get_definition( $t_field_id );
							echo "<option value=\"$t_field_id\">" . string_attribute( $t_desc['name'] ) . '</option>' ;
						}
					}
				?>
			</select>
			<input type="submit" class="button" value="<?php echo lang_get( 'add_existing_custom_field' ) ?>" />
			</form>
		</td>
	</tr>
	</table>
	</div>
<?php
}
?>


<!-- PROJECT VIEW STATUS -->
<br />
<div align="center">
	<table class="width75" cellspacing="1">
		<tr>
			<td class="center">
			<?php
				if ( VS_PUBLIC == project_get_field( $f_project_id, 'view_state' ) ) {
					echo lang_get( 'public_project_msg' );
				} else {
					echo lang_get( 'private_project_msg' );
				}
			?>
			</td>
		</tr>
	</table>
</div>


<!-- USER MANAGEMENT (ADD) -->
<?php
# We want to allow people with global permissions and people with high enough
#  permissions on the project we are editing
if ( access_has_project_level( config_get( 'project_user_threshold' ), $f_project_id ) ) {
?>
<br />
<div align="center">
	<table class="width75" cellspacing="1">
		<form method="post" action="manage_proj_user_add.php">
			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
			<tr>
				<td class="form-title" colspan="5">
					<?php echo lang_get( 'add_user_title' ) ?>
				</td>
			</tr>
			<tr class="row-1" valign="top">
				<td class="category">
					<?php echo lang_get( 'username' ) ?>
				</td>
				<td class="category">
					<?php echo lang_get( 'access_level' ) ?>
				</td>
				<td class="category">&nbsp;  </td>
			</tr>
			<tr class="row-1" valign="top">
				<td>
					<select name="user_id[]" multiple="multiple" size="10">
						<?php print_project_user_list_option_list( $f_project_id ) ?>
					</select>
				</td>
				<td>
					<select name="access_level">
						<?php # only access levels that are less than or equal current user access level for current project ?>
						<?php print_project_access_levels_option_list( config_get( 'default_new_account_access_level' ), $f_project_id ) ?>
					</select>
				</td>
				<td>
					<input type="submit" class="button" value="<?php echo lang_get( 'add_user_button' ) ?>" />
				</td>
			</tr>
		</form>
		<!-- Copy Users Form -->
		<form method="post" action="manage_proj_user_copy.php">
			<tr>
				<td class="left" colspan="3">
						<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
						<select name="other_project_id">
							<?php print_project_option_list( null, false, $f_project_id ); ?>
						</select>
						<input type="submit" name="copy_from" class="button" value="<?php echo lang_get( 'copy_users_from' ) ?>" />
						<input type="submit" name="copy_to" class="button" value="<?php echo lang_get( 'copy_users_to' ) ?>" />
				</td>
			</tr>
		</form>
	</table>
</div>
<?php
}
?>


<!-- LIST OF USERS -->
<br />
<div align="center">
	<table class="width75" cellspacing="1">
		<tr>
			<td class="form-title" colspan="4">
				<?php echo lang_get( 'manage_accounts_title' ) ?>
			</td>
		</tr>
		<tr class="row-category">
			<td>
				<?php echo lang_get( 'username' ) ?>
			</td>
			<td>
				<?php echo lang_get( 'email' ) ?>
			</td>
			<td>
				<?php echo lang_get( 'access_level' ) ?>
			</td>
			<td class="center">
				<?php echo lang_get( 'actions' ) ?>
			</td>
		</tr>
<?php
	$t_users = project_get_all_user_rows( $f_project_id );
	$t_display = array();
	$t_sort = array();
	foreach ( $t_users as $t_user ) {
		$t_user_name = string_attribute( $t_user['username'] );
		$t_sort_name = strtolower( $t_user_name );
		if ( ( isset( $t_user['realname'] ) ) && ( $t_user['realname'] > "" ) && ( ON == config_get( 'show_realname' ) ) ){
			$t_user_name = string_attribute( $t_user['realname'] ) . " (" . $t_user_name . ")";
			if ( ON == config_get( 'sort_by_last_name') ) {
				$t_sort_name_bits = split( ' ', strtolower( $t_user_name ), 2 );
				$t_sort_name = $t_sort_name_bits[1] . ', ' . $t_sort_name_bits[1];
			} else {
				$t_sort_name = strtolower( $t_user_name );
			}
		}
		$t_display[] = $t_user_name;
		$t_sort[] = $t_sort_name;
	}
	array_multisort( $t_sort, SORT_ASC, SORT_STRING, $t_users, $t_display );

	# reset the class counter
	helper_alternate_class( 0 );

	for ($i = 0; $i < count( $t_sort ); $i++ ) {
		$t_user = $t_users[$i];
?>
		<tr <?php echo helper_alternate_class() ?>>
			<td>
				<?php echo $t_display[$i] ?>
			</td>
			<td>
			<?php
				$t_email = user_get_email( $t_user['id'] );
				print_email_link( $t_email, $t_email );
			?>
			</td>
			<td>
				<?php echo get_enum_element( 'access_levels', $t_user['access_level'] ) ?>
			</td>
			<td class="center">
			<?php
				# You need global or project-specific permissions to remove users
				#  from this project
				if ( access_has_project_level( config_get( 'project_user_threshold' ), $f_project_id ) ) {
					if ( project_includes_user( $f_project_id, $t_user['id'] )  ) {
						print_button( 'manage_proj_user_remove.php?project_id=' . $f_project_id . '&amp;user_id=' . $t_user['id'], lang_get( 'remove_link' ) );
					}
				}
			?>
			</td>
		</tr>
<?php
	}  # end for
?>
	<tr>
	<td>&nbsp;  </td>
	<td>&nbsp;  </td>
	<td>&nbsp;  </td>
	<td class="center">
	<?php
		# You need global or project-specific permissions to remove users
		#  from this project
		if ( access_has_project_level( config_get( 'project_user_threshold' ), $f_project_id ) ) {
			print_button( 'manage_proj_user_remove.php?project_id=' . $f_project_id, lang_get( 'remove_all_link' ) );
		}
	?>
	</td>
	</tr>
	</table>
</div>

<?php html_page_bottom1( __FILE__ ) ?>
manage_proj_edit_page.php (21,035 bytes)   
version_api.php (13,302 bytes)   
<?php
	# Mantis - a php based bugtracking system
	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
	# Copyright (C) 2002 - 2004  Mantis Team   - mantisbt-dev@lists.sourceforge.net
	# This program is distributed under the terms and conditions of the GPL
	# See the README and LICENSE files for details

	# --------------------------------------------------------
	# $Id: version_api.php,v 1.23 2006/12/29 09:34:45 vboctor Exp $
	# --------------------------------------------------------

	### Version API ###

	#=========================================
	# Version Data Structure Definition
	#===================================
	class VersionData {
		var $id = 0;
		var $project_id = 0;
		var $version = '';
		var $description = '';
		var $released = 1;
		var $date_order = '';
	}

	#===================================
	# Boolean queries and ensures
	#===================================

	$g_cache_versions = array();

	# --------------------
	# Cache a version row if necessary and return the cached copy
	#  If the second parameter is true (default), trigger an error
	#  if the version can't be found.  If the second parameter is
	#  false, return false if the version can't be found.
	function version_cache_row( $p_version_id, $p_trigger_errors = true ) {
		global $g_cache_versions;

		$c_version_id = db_prepare_int( $p_version_id );
		$t_project_version_table = config_get( 'mantis_project_version_table' );

		if ( isset( $g_cache_versions[$c_version_id] ) ) {
			return $g_cache_versions[$c_version_id];
		}

		$query = "SELECT *
				  FROM $t_project_version_table
				  WHERE id='$c_version_id'";
		$result = db_query( $query );

		if ( 0 == db_num_rows( $result ) ) {
			$g_cache_versions[$c_version_id] = false;

			if ( $p_trigger_errors ) {
				error_parameters( $p_version_id );
				trigger_error( ERROR_VERSION_NOT_FOUND, ERROR );
			} else {
				return false;
			}
		}

		$row = db_fetch_array( $result );
		// $row['date_order'] = db_unixtimestamp( $row['date_order'] );
		$g_cache_versions[$c_version_id] = $row;

		return $row;
	}

	# --------------------
	# Check whether the version exists
	# $p_project_id : null will use the current project, otherwise the specified project
	# Returns true if the version exists, false otherwise
	function version_exists( $p_version_id ) {
		return version_cache_row( $p_version_id, false ) !== false;
	}

	# --------------------
	# Check whether the version name is unique
	# Returns true if the name is unique, false otherwise
	function version_is_unique( $p_version, $p_project_id = null ) {
		return version_get_id( $p_version, $p_project_id ) === false;
	}

	# --------------------
	# Check whether the version exists
	# Trigger an error if it does not
	function version_ensure_exists( $p_version_id ) {
		if ( !version_exists( $p_version_id ) ) {
			error_parameters( $p_version_id );
			trigger_error( ERROR_VERSION_NOT_FOUND, ERROR );
		}
	}

	# --------------------
	# Check whether the version is unique within a project
	# Trigger an error if it is not
	function version_ensure_unique( $p_version, $p_project_id = null ) {
		if ( !version_is_unique( $p_version, $p_project_id ) ) {
			trigger_error( ERROR_VERSION_DUPLICATE, ERROR );
		}
	}


	#===================================
	# Creation / Deletion / Updating
	#===================================

	# --------------------
	# Add a version to the project
	function version_add( $p_project_id, $p_version, $p_released = VERSION_RELEASED, $p_description = '', $p_date_order=null) {
		$c_project_id   = db_prepare_int( $p_project_id );
		$c_released     = db_prepare_int( $p_released );
		$c_version      = db_prepare_string( $p_version );
		$c_description  = db_prepare_string( $p_description );
		$c_date_order   = db_timestamp($p_date_order);

		version_ensure_unique( $p_version, $p_project_id );

		$t_project_version_table = config_get( 'mantis_project_version_table' );

		$query = "INSERT INTO $t_project_version_table
					( project_id, version, date_order, description, released )
				  VALUES
					( '$c_project_id', '$c_version', $c_date_order , '$c_description', '$c_released' )";
		db_query( $query );

		# db_query() errors on failure so:
		return true;
	}

	# --------------------
	# Update the definition of a version
	function version_update( $p_version_info ) {
		version_ensure_exists( $p_version_info->id );

		$t_old_version_name = version_get_field( $p_version_info->id, 'version' );

		# check for duplicates
		if ( ( strtolower( $t_old_version_name ) != strtolower( $p_version_info->version ) ) &&
			 !version_is_unique( $p_version_info->version, $p_version_info->project_id ) ) {
			trigger_error( ERROR_VERSION_DUPLICATE, ERROR );
		}

		$c_version_id   = db_prepare_int( $p_version_info->id );
		$c_version_name = db_prepare_string( $p_version_info->version );
		$c_old_version_name = db_prepare_string( $t_old_version_name );
		$c_description  = db_prepare_string( $p_version_info->description );
		$c_released     = db_prepare_int( $p_version_info->released );
		$c_date_order   = db_prepare_string( $p_version_info->date_order );
		$c_project_id	= db_prepare_int( $p_version_info->project_id );

		$t_project_version_table	= config_get( 'mantis_project_version_table' );
		$t_bug_table				= config_get( 'mantis_bug_table' );

		$query = "UPDATE $t_project_version_table
				  SET version='$c_version_name',
					description='$c_description',
					released='$c_released',
					date_order='$c_date_order'
				  WHERE id='$c_version_id'";
		db_query( $query );

		if ( $c_version_name != $c_old_version_name ) {
			$query = "UPDATE $t_bug_table
					  SET version='$c_version_name'
					  WHERE ( project_id='$c_project_id' ) AND ( version='$c_old_version_name' )";
			db_query( $query );

			$query = "UPDATE $t_bug_table
					  SET fixed_in_version='$c_version_name'
					  WHERE ( project_id='$c_project_id' ) AND ( fixed_in_version='$c_old_version_name' )";
			db_query( $query );

			$query = "UPDATE $t_bug_table
					  SET target_version='$c_version_name'
					  WHERE ( project_id='$c_project_id' ) AND ( target_version='$c_old_version_name' )";
			db_query( $query );

			# @@@ We should consider using ids instead of names for foreign keys.  The main advantage of using the names are:
			# 		- for history the version history entries will still be valid even if the version is deleted in the future. --  we can ban deleting referenced versions.
			#		- when an issue is copied or moved from one project to another, we can keep the last version with the issue even if it doesn't exist in the new project.  Also previous history entries remain valid.
			# @@@ We should update the history for version, fixed_in_version, and target_version.
			# @@@ We probably need to update the saved filters too?
		}

		# db_query() errors on failure so:
		return true;
	}

	# --------------------
	# Remove a version from the project
	function version_remove( $p_version_id, $p_new_version='' ) {
		$c_version_id	= db_prepare_int( $p_version_id );
		$c_new_version	= db_prepare_string( $p_new_version );

		version_ensure_exists( $p_version_id );

		$t_old_version = version_get_field( $p_version_id, 'version' );
		$t_project_id = version_get_field( $p_version_id, 'project_id' );

		$c_old_version = db_prepare_string( $t_old_version );
		$c_project_id = db_prepare_int( $t_project_id );

		$t_project_version_table	= config_get( 'mantis_project_version_table' );
		$t_bug_table				= config_get( 'mantis_bug_table' );

		$query = "DELETE FROM $t_project_version_table
				  WHERE id='$c_version_id'";
		db_query( $query );

		$query = "UPDATE $t_bug_table
				  SET version='$c_new_version'
				  WHERE project_id='$c_project_id' AND version='$c_old_version'";
		db_query( $query );

		$query = "UPDATE $t_bug_table
				  SET fixed_in_version='$c_new_version'
				  WHERE ( project_id='$c_project_id' ) AND ( fixed_in_version='$c_old_version' )";
		db_query( $query );

		# db_query() errors on failure so:
		return true;
	}

	# --------------------
	# Remove all versions associated with a project
	function version_remove_all( $p_project_id ) {
		$c_project_id = db_prepare_int( $p_project_id );

		$t_project_version_table	= config_get( 'mantis_project_version_table' );
		$t_bug_table				= config_get( 'mantis_bug_table' );

		$query = "DELETE FROM $t_project_version_table
	  			  WHERE project_id='$c_project_id'";

		db_query( $query );

		$query = "UPDATE $t_bug_table
				  SET version=''
				  WHERE project_id='$c_project_id'";
		db_query( $query );

		$query = "UPDATE $t_bug_table
				  SET fixed_in_version=''
				  WHERE project_id='$c_project_id'";
		db_query( $query );

		# db_query() errors on failure so:
		return true;
	}


	#===================================
	# Data Access
	#===================================

	# --------------------
	# Return all versions for the specified project
	function version_get_all_rows( $p_project_id, $p_released = null ) {
		$c_project_id = db_prepare_int( $p_project_id );

		if ( $p_released === null ) {
			$t_released_where = '';
		} else {
			$c_released = db_prepare_int( $p_released );
			$t_released_where = "AND ( released = $c_released )";
		}

		$t_project_version_table = config_get( 'mantis_project_version_table' );

		$query = "SELECT *
				  FROM $t_project_version_table
				  WHERE project_id='$c_project_id' $t_released_where
				  ORDER BY date_order ASC";
		$result = db_query( $query );
		$count = db_num_rows( $result );
		$rows = array();
		for ( $i = 0 ; $i < $count ; $i++ ) {
			$row = db_fetch_array( $result );
			$rows[] = $row;
		}
		return $rows;
	}
	
	# --------------------
	# Return all versions for the specified project, including subprojects
	function version_get_all_rows_with_subs( $p_project_id, $p_released = null ) {
		$t_project_where = helper_project_specific_where( $p_project_id );

		if ( $p_released === null ) {
			$t_released_where = '';
		} else {
			$c_released = db_prepare_int( $p_released );
			$t_released_where = "AND ( released = $c_released )";
		}

		$t_project_version_table = config_get( 'mantis_project_version_table' );

		$query = "SELECT *
				  FROM $t_project_version_table
				  WHERE $t_project_where $t_released_where
				  ORDER BY date_order ASC";
		$result = db_query( $query );
		$count = db_num_rows( $result );
		$rows = array();
		for ( $i = 0 ; $i < $count ; $i++ ) {
			$row = db_fetch_array( $result );
			$rows[] = $row;
		}
		return $rows;
	}	

	# --------------------
	# Get the version_id, given the project_id and $p_version_id
	# returns false if not found, otherwise returns the id.
	function version_get_id( $p_version, $p_project_id = null ) {
		$c_version       = db_prepare_string( $p_version );

		if ( $p_project_id === null ) {
			$c_project_id = helper_get_current_project();
		} else {
			$c_project_id = db_prepare_int( $p_project_id );
		}

		$t_project_version_table = config_get( 'mantis_project_version_table' );

		$query = "SELECT id
					FROM $t_project_version_table
					WHERE project_id='$c_project_id' AND
						version='$c_version'";

		$result = db_query( $query );

		if ( 0 == db_num_rows( $result ) ) {
			return false;
		} else {
			return db_result( $result );
		}
	}

	# --------------------
	# Get the specified field name for the specified version id.
	# triggers an error if version not found, otherwise returns the field value.
	function version_get_field( $p_version_id, $p_field_name ) {
		$row = version_cache_row( $p_version_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 '';
		}
	}

	# --------------------
	# get information about a version given its id
	function version_get( $p_version_id ) {
		$row = version_cache_row( $p_version_id );

		$t_version_data = new VersionData;
		$t_row_keys = array_keys( $row );
		$t_vars = get_object_vars( $t_version_data );

		# Check each variable in the class
		foreach ( $t_vars as $var => $val ) {
			# If we got a field from the DB with the same name
			if ( in_array( $var, $t_row_keys, true ) ) {
				# Store that value in the object
				$t_version_data->$var = $row[$var];
			}
		}

		return $t_version_data;
	}

	# --------------------
	# Return a copy of the version structure with all the instvars prepared for db insertion
	function version_prepare_db( $p_version_info ) {
		$p_version_info->id		= db_prepare_int( $p_version_info->id );
		$p_version_info->project_id	= db_prepare_int( $p_version_info->project_id );
		$p_version_info->version	= db_prepare_string( $p_version_info->version );
		$p_version_info->description	= db_prepare_string( $p_version_info->description );
		$p_version_info->released	= db_prepare_int( $p_version_info->released );
		$p_version_info->date_order	= db_prepare_string( $p_version_info->date_order );

		return $p_version_info;
	}
?>
version_api.php (13,302 bytes)   
8094.patch (3,697 bytes)   
Index: manage_proj_edit_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/manage_proj_edit_page.php,v
retrieving revision 1.98
diff -u -r1.98 manage_proj_edit_page.php
--- manage_proj_edit_page.php	6 Mar 2007 07:05:18 -0000	1.98
+++ manage_proj_edit_page.php	3 Jul 2007 03:07:35 -0000
@@ -427,6 +427,18 @@
 		</form>
 	</td>
 </tr>
+<tr>
+	<td class="left" colspan="3">
+		<form method="post" action="manage_proj_ver_copy.php">
+			<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" />
+			<select name="other_project_id">
+				<?php print_project_option_list( null, false, $f_project_id ); ?>
+			</select>
+			<input type="submit" name="copy_from" class="button" value="<?php echo lang_get( 'copy_versions_from' ) ?>" />
+			<input type="submit" name="copy_to" class="button" value="<?php echo lang_get( 'copy_versions_to' ) ?>" />
+		</form>
+	</td>
+</tr>
 </table>
 </div>
 
Index: core/version_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/version_api.php,v
retrieving revision 1.23
diff -u -r1.23 version_api.php
--- core/version_api.php	29 Dec 2006 09:34:45 -0000	1.23
+++ core/version_api.php	3 Jul 2007 03:40:08 -0000
@@ -1,7 +1,7 @@
 <?php
 	# Mantis - a php based bugtracking system
 	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
-	# Copyright (C) 2002 - 2004  Mantis Team   - mantisbt-dev@lists.sourceforge.net
+	# Copyright (C) 2002 - 2007  Mantis Team   - mantisbt-dev@lists.sourceforge.net
 	# This program is distributed under the terms and conditions of the GPL
 	# See the README and LICENSE files for details
 
@@ -108,12 +108,18 @@
 
 	# --------------------
 	# Add a version to the project
-	function version_add( $p_project_id, $p_version, $p_released = VERSION_RELEASED, $p_description = '' ) {
+	function version_add( $p_project_id, $p_version, $p_released = VERSION_RELEASED, $p_description = '', $p_date_order = null) {
 		$c_project_id   = db_prepare_int( $p_project_id );
 		$c_released     = db_prepare_int( $p_released );
 		$c_version      = db_prepare_string( $p_version );
 		$c_description  = db_prepare_string( $p_description );
 
+		if ( null === $p_date_order ) {
+			$c_date_order = db_now();
+		} else {
+			$c_date_order = db_timestamp( $p_date_order );
+		}
+
 		version_ensure_unique( $p_version, $p_project_id );
 
 		$t_project_version_table = config_get( 'mantis_project_version_table' );
@@ -121,7 +127,7 @@
 		$query = "INSERT INTO $t_project_version_table
 					( project_id, version, date_order, description, released )
 				  VALUES
-					( '$c_project_id', '$c_version', " . db_now() . ", '$c_description', '$c_released' )";
+					( '$c_project_id', '$c_version', " . $c_date_order . ", '$c_description', '$c_released' )";
 		db_query( $query );
 
 		# db_query() errors on failure so:
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.299
diff -u -r1.299 strings_english.txt
--- lang/strings_english.txt	2 Jul 2007 08:46:59 -0000	1.299
+++ lang/strings_english.txt	3 Jul 2007 03:08:04 -0000
@@ -62,6 +62,8 @@
 $s_copy_users = 'Copy Users';
 $s_copy_categories_from = 'Copy Categories From';
 $s_copy_categories_to = 'Copy Categories To';
+$s_copy_versions_from = 'Copy Versions From';
+$s_copy_versions_to = 'Copy Versions To';
 $s_copy_users_from = 'Copy Users From';
 $s_copy_users_to = 'Copy Users To';
 $s_bug_history = 'Issue History';
8094.patch (3,697 bytes)   

Relationships

related to 0021693 closeddregad Copy of Versions from one project to another project does not copy all fields 
related to 0028562 closeddregad Undefined constant ERROR_VERSION_NO_ACTION and missing matching error message 

Activities

vboctor

vboctor

2007-07-02 23:59

manager   ~0014846

I've attached 8094.patch which includes the final patch, the final patch contains the following fixes compared to the contributed one:

  1. It copies "release" and "description". I believe also the copying of the date_order didn't work.
  2. It fixed a problem when copying a set of versions that have some duplicate entries with the target project.
  3. Added the strings in the language file.

Related Changesets

MantisBT: master 658a236f

2007-07-02 23:57

vboctor


Details Diff
Fixed 0008094: Managing versions / release schedule accross multiple projects.

git-svn-id: http://mantisbt.svn.sourceforge.net/svnroot/mantisbt/trunk@4395 <a class="text" href="/?p=mantisbt.git;a=object;h=f5dc347c">f5dc347c</a>-c33d-0410-90a0-b07cc1902cb9
Affected Issues
0008094
mod - manage_proj_edit_page.php Diff File
mod - core/version_api.php Diff File
add - manage_proj_ver_copy.php Diff File
mod - lang/strings_english.txt Diff File