Skip to content

Commit

Permalink
Full rewrite the Move Attachments admin page
Browse files Browse the repository at this point in the history
The old move_db2disk.php program was completely outdated and did not
work properly.

This commit introduces completely new page, with dissociated page to
select which attachments to move, and action page to actually move the
files from DB to disk

Fixes #15496
  • Loading branch information
dregad committed Apr 16, 2013
1 parent 589af33 commit 6da8b23
Show file tree
Hide file tree
Showing 6 changed files with 406 additions and 202 deletions.
218 changes: 218 additions & 0 deletions admin/move_attachments.php
@@ -0,0 +1,218 @@
<?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/>.

/**
* This upgrade moves attachments from the database to the disk
* @package MantisBT
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2013 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
*/


/**
* MantisBT Core API's
*/
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

form_security_validate( 'move_attachments_project_select' );

access_ensure_global_level( config_get_global( 'admin_site_threshold' ) );


$f_file_type = gpc_get( 'type' );
$f_projects_to_disk = gpc_get( 'to_disk', null );


/**
* Moves attachments from the specified list of projects from database to disk
* @param string $p_type Attachment type ('bug' or 'project')
* @param array $p_projects List of projects to process
* @return array summary of moves per project
*/
function move_attachments_to_disk( $p_type, $p_projects ) {
if( empty( $p_projects ) ) {
return array();
}

# Build the SQL query based on attachment type
$t_file_table = db_get_table( "mantis_${p_type}_file_table" );
switch( $p_type ) {
case 'project':

$t_query = "SELECT f.*
FROM $t_file_table f
WHERE content <> ''
AND f.project_id = " . db_param() . "
ORDER BY f.filename";
break;

case 'bug':
$t_bug_table = db_get_table( 'mantis_bug_table' );

$t_query = "SELECT f.*
FROM $t_file_table f
JOIN $t_bug_table b ON b.id = f.bug_id
WHERE content <> ''
AND b.project_id = " . db_param() . "
ORDER BY f.bug_id, f.filename";
break;
}

# Process projects list
foreach( $p_projects as $t_project ) {
# Retrieve attachments for the project
$t_result = db_query_bound( $t_query, array( $t_project ) );

# Project upload path
$t_upload_path = project_get_upload_path( $t_project );
if( is_blank( $t_upload_path )
|| !file_exists( $t_upload_path )
|| !is_dir( $t_upload_path )
|| !is_writable( $t_upload_path )
) {
# Invalid path
$t_failures = db_num_rows( $t_result );
$t_data = "ERROR: Upload path '$t_upload_path' does not exist or is not writable";
} else {
# Process attachments
$t_failures = 0;
$t_data = array();

if( $p_type == 'project' ) {
$t_seed = config_get( 'document_files_prefix', null, ALL_USERS, $t_project ) . $t_project;
}

while( $t_row = db_fetch_array( $t_result ) ) {
if( $p_type == 'bug' ) {
$t_seed = $t_row['bug_id'] . $t_row['filename'];
}

$t_filename = $t_upload_path . file_generate_unique_name( $t_seed, $t_upload_path );

# write file to disk
if( file_put_contents( $t_filename, $t_row['content'] ) ) {
# successful, update database
# @todo do we want to check the size of data transfer matches here?
$t_update_query = "UPDATE $t_file_table
SET diskfile = " . db_param() . ",
folder = " . db_param() . ",
content = ''
WHERE id = " . db_param();
$t_update_result = db_query_bound(
$t_update_query,
array( $t_filename, $t_upload_path, $t_row['id'] )
);

if( !$t_update_result ) {
$t_status = 'Database update failed';
$t_failures++;
} else {
$t_status = "Moved to '$t_filename'";
}
} else {
$t_status = "Copy to '$t_file_name' failed";

This comment has been minimized.

Copy link
@atrol

atrol Apr 17, 2013

Member

Should be $t_filename
or $t_file_name at some other places

This comment has been minimized.

Copy link
@dregad

dregad Apr 17, 2013

Author Member

Thanks @atrol - fixed in cbc4037

$t_failures++;
}

# Add the file and status to the list of processed attachments
$t_file = array(
'id' => $t_row['id'],
'filename' => $t_row['filename'],
'status' => $t_status,
);
if( $p_type == 'bug' ) {
$t_file['bug_id'] = $t_row['bug_id'];
}
$t_data[] = $t_file;
}
}

$t_moved[] = array(
'name' => project_get_name( $t_project ),
'path' => $t_upload_path,
'rows' => db_num_rows( $t_result ),
'failed' => $t_failures,
'data' => $t_data,
);

}
return $t_moved;
}


$t_moved = move_attachments_to_disk( $f_file_type, $f_projects_to_disk );

form_security_purge( 'move_attachments_project_select' );

$t_redirect_url = 'system_utils.php';

# Page header, menu
html_page_top(
'MantisBT Administration - Moving Attachments',
empty( $t_result ) ? $t_redirect_url : null
);

?>

<div align="center">

<?php

# Display results
if( empty( $t_moved ) ) {
echo "<p>Nothing to do.</p>\n";
} else {
foreach( $t_moved as $t_row ) {
printf(
"<p class=\"bold\">Project '%s' : %d attachments %s.</p>\n",
$t_row['name'],
$t_row['rows'],
( 0 == $t_row['failed']
? 'moved successfully'
: 'to move, ' . $t_row['failed'] . ' failures')
);

if( is_array( $t_row['data'] ) ) {
# Display details of moved attachments
echo '<div><table class="width75">', "\n",
'<tr class="row-category">',
$f_file_type == 'bug' ? '<th>Bug ID</th>' : '',
'<th>File</th><th>Filename</th><th>Status</th>',
'</tr>';
foreach( $t_row['data'] as $t_data ) {
echo '<tr ' . helper_alternate_class() .'>';
if( $f_file_type == 'bug' ) {
printf( '<td>%s</td>', bug_format_id( $t_data['bug_id'] ) );
}
printf( '<td class="right">%s</td><td>%s</td><td>%s</td></tr>' . "\n",
$t_data['id'],
$t_data['filename'],
$t_data['status']
);
}
echo '</table><br /></div>';
} else {
# No data rows - display error message
echo '<p>' . $t_row['data'] . '</p>';
}
echo '<br />';
}
}

print_bracket_link( $t_redirect_url, 'Back to System Utilities' );

html_page_bottom();
160 changes: 160 additions & 0 deletions admin/move_attachments_page.php
@@ -0,0 +1,160 @@
<?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/>.

/**
* This upgrade moves attachments from the database to the disk
*
* @package MantisBT
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2013 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
*/


/**
* MantisBT Core API's
*/
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

access_ensure_global_level( config_get_global( 'admin_site_threshold' ) );

# Page header, menu
html_page_top( 'MantisBT Administration - Moving Attachments' );
echo '<div align="center"><p>';
print_bracket_link( helper_mantis_url( 'admin/system_utils.php' ), 'Back to System Utilities' );
echo '</p></div>';


# File type should be 'bug' (default) or 'project'
$f_file_type = gpc_get( 'type', 'bug' );

$t_bug_table = db_get_table( 'mantis_bug_table' );
$t_project_table = db_get_table( 'mantis_project_table' );

switch( $f_file_type ) {
case 'project':
$t_type = 'Project Files';
$t_file_table = db_get_table( 'mantis_project_file_table' );
$t_query = "SELECT p.id, p.name, COUNT(f.id) disk
FROM $t_file_table f
LEFT JOIN $t_project_table p ON p.id = f.project_id
WHERE content <> ''
GROUP BY p.id, p.name
ORDER BY p.name";
break;

case 'bug':
default:
$t_type = 'Attachments';
$t_file_table = db_get_table( 'mantis_bug_file_table' );
$t_query = "SELECT p.id, p.name, COUNT(f.id) disk
FROM $t_file_table f
JOIN $t_bug_table b ON b.id = f.bug_id
JOIN $t_project_table p ON p.id = b.project_id
WHERE content <> ''
GROUP BY p.id, p.name
ORDER BY p.name";
break;
}

# Move to disk: projects having non-empty attachments in the DB
$t_result = db_query_bound( $t_query );

# Build list, excluding projects having upload method other than DISK
$t_projects = array();
while( $t_row = db_fetch_array( $t_result ) ) {
$t_project_id = (int) $t_row['id'];
$t_upload_method = config_get( 'file_upload_method', null, ALL_USERS, $t_project_id );
if( $t_upload_method == DISK ) {
$t_projects[$t_project_id] = $t_row;
}
}

if( count( $t_projects ) == 0 ) {
# Nothing to do
echo '<div align="center"><p>No attachments need to be moved.</p></div>';
} else {
# Display name for All Projects
if( isset( $t_projects[ALL_PROJECTS] ) ) {
$t_projects[ALL_PROJECTS]['name'] = 'All Projects';
}

# Display table of projects for user selection

?>

<div align="center">

<form name="move_attachments_project_select" method="post" action="move_attachments.php">
<table class="width50">
<tr>
<td class="form-title" colspan="2">
<?php echo "$t_type to move"; ?>
</td>
</tr>

<tr class="row-category">
<th>Project name</th>
<th width="18%">Attachments</th>
<th width="7%">To Disk</th>
</tr>

<?php
# Printing rows of projects with attachments to move
foreach( $t_projects as $t_id => $t_project ) {
echo '<tr ' . helper_alternate_class() . '>';
printf(
'<td>%s</td><td class="center">%s</td><td class="center">'
. '<input type="checkbox" name="to_disk[]" value="%d" /></td>',
$t_project['name'],
$t_project['disk'],
$t_id
);
echo "</tr>\n";
}

if( ON == config_get( 'use_javascript' ) ) {
?>

<tr>
<td class="right" colspan="2">Select All</td>
<td class="center">
<input name="all_proj"
type="checkbox" value="all"
onclick="checkall('move_attachments_project_select', this.form.all_proj.checked)"
/>
</td>
</tr>

<?php
}
echo form_security_field( 'move_attachments_project_select' );
?>

</table>
<span class="center">
<br />
<input name="type" type="hidden" value="<?php echo $f_file_type ?>" />
<input type="submit" class="button" value="Move Attachments" />
</span>

</form>
</div>

<?php
}

html_page_bottom();

0 comments on commit 6da8b23

Please sign in to comment.