From 3c1beba557d23ef496f6b26de7eee284e99450e1 Mon Sep 17 00:00:00 2001
From: unknown <Hoover@.greenops.com>
Date: Sun, 4 Apr 2010 11:44:01 -0500
Subject: [PATCH] Mantis #11687 - Disk based attachments get lost when a bug is moved across projects

---
 bug_actiongroup.php |    3 ++
 core/file_api.php   |   79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/bug_actiongroup.php b/bug_actiongroup.php
index 4e70bb1..aafb28e 100644
--- a/bug_actiongroup.php
+++ b/bug_actiongroup.php
@@ -53,6 +53,7 @@ require_api( 'config_api.php' );
 require_api( 'constant_inc.php' );
 require_api( 'custom_field_api.php' );
 require_api( 'event_api.php' );
+require_api( 'file_api.php' );
 require_api( 'form_api.php' );
 require_api( 'gpc_api.php' );
 require_api( 'helper_api.php' );
@@ -136,7 +137,9 @@ foreach( $f_bug_arr as $t_bug_id ) {
 		if ( access_has_bug_level( config_get( 'move_bug_threshold' ), $t_bug_id ) ) {
 			/** @todo we need to issue a helper_call_custom_function( 'issue_update_validate', array( $t_bug_id, $t_bug_data, $f_bugnote_text ) ); */
 			$f_project_id = gpc_get_int( 'project_id' );
+			$t_origional_bug_project = bug_get_field( $t_bug_id, 'project_id' );
 			bug_set_field( $t_bug_id, 'project_id', $f_project_id );
+			file_move_bug_attachments( $t_bug_id, $t_origional_bug_project, $f_project_id );
 			helper_call_custom_function( 'issue_update_notify', array( $t_bug_id ) );
 		} else {
 			$t_failed_ids[$t_bug_id] = lang_get( 'bug_actiongroup_access' );
diff --git a/core/file_api.php b/core/file_api.php
index 4ead250..1555ca8 100644
--- a/core/file_api.php
+++ b/core/file_api.php
@@ -870,3 +870,82 @@ function file_get_extension( $p_filename ) {
 	}
 	return $t_extension;
 }
+
+/**
+ * Move any attachements as needed when a bug is moved from project to project
+ *
+ * @param integer $p_bug_id the bug id
+ * @param integer $p_project_id_from the project id the bug was in
+ * @param integer $p_project_id_to the project id the bug was moved to
+ */
+function file_move_bug_attachments( $p_bug_id, $p_project_id_from, $p_project_id_to ) {
+	if ( $p_project_id_from == $p_project_id_to ) {
+		return true;
+	}
+
+	$t_method = config_get( 'file_upload_method' );
+
+	# Optimization here, as DB atachments don't need to be moved.
+	if ( file_bug_has_attachments($p_bug_id) == true && $t_method != DATABASE ){
+		$t_path_from = project_get_field( $p_project_id_from, 'file_path' );
+		if ( is_blank( $t_path_from ) ) {
+			$t_path_from = config_get( 'absolute_path_default_upload_folder' );
+		}
+		$t_path_to = project_get_field( $p_project_id_to, 'file_path' );
+		if ( is_blank( $t_path_to ) ) {
+			$t_path_to = config_get( 'absolute_path_default_upload_folder' );
+		}
+		if ( $t_path_from == $t_path_to ) {
+			return true;
+		}
+
+		$t_attachment_rows = bug_get_attachments( $p_bug_id );
+		$t_attachments_count = count( $t_attachment_rows );
+		$t_bug_file_table = db_get_table( 'bug_file' );
+		$c_bug_id = db_prepare_int( $p_bug_id );
+
+		# Initialize the update query to update a single row
+		$query_disk_attachment_update = "UPDATE $t_bug_file_table
+				  SET folder=" . db_param() . "
+				  WHERE bug_id=" . db_param() . "
+				  AND id =" . db_param();
+
+		file_ensure_valid_upload_path( $t_path_from );
+		file_ensure_valid_upload_path( $t_path_to );
+
+		for( $i = 0;$i < $t_attachments_count;$i++ ) {
+			$t_row = $t_attachment_rows[$i];
+			$t_basename = basename( $t_row['diskfile'] );
+
+			$t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename );
+			$t_disk_file_name_to = file_path_combine( $t_path_to, $t_basename );
+
+			switch( $t_method ) {
+				case FTP:
+				case DISK:
+					# In the case of FTP storage, it's my understanding that all the files are stored
+					# in a single folder, so we don't need to do anything with the remote ftp backup
+					if( !file_exists( $t_disk_file_name_to ) ) {
+						chmod( $t_disk_file_name_from, 0775 );
+						if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) {
+							if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) {
+								trigger_error( FILE_MOVE_FAILED, ERROR );
+							}
+							file_delete_local( $t_disk_file_name_from );
+						}
+						chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) );
+						db_query_bound( $query_disk_attachment_update, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) );
+					} else {
+						trigger_error( ERROR_FILE_DUPLICATE, ERROR );
+					}
+					break;
+				case DATABASE:
+					# Nothing to do with DB storage, but if we needed to update any meta data, we would remove the upper
+					# optimization, and then update here
+					break;
+				default:
+					trigger_error( ERROR_GENERIC, ERROR );
+			}
+		}
+	}
+}
-- 
1.7.0.2.msysgit.0

