Gallery: Sorting of files uploaded in zip archives (RFE 11517)

This commit is contained in:
kimd 2010-05-17 22:03:38 +02:00
parent 95e9e52389
commit 8030bed30b
6 changed files with 166 additions and 16 deletions

View file

@ -1,5 +1,6 @@
7.9.5 7.9.5
- added #11502: Gallery: Allow specification of location when uploading ZIP archives - added #11502: Gallery: Allow specification of location when uploading ZIP archives
- added #11517: Gallery: Sorting of files uploaded in zip archives
7.9.4 7.9.4
- We're shipping underscore.js now for its suite of extremely handy utility - We're shipping underscore.js now for its suite of extremely handy utility

View file

@ -11,20 +11,25 @@ package WebGUI::Asset::Wobject::GalleryAlbum;
#------------------------------------------------------------------- #-------------------------------------------------------------------
use strict; use strict;
use Class::C3;
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject); use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
use Class::C3;
use Carp qw( croak ); use Carp qw( croak );
use File::Find; use File::Find;
use File::Spec; use File::Spec;
use File::Temp qw{ tempdir }; use File::Temp qw{ tempdir };
use Image::ExifTool qw( :Public );
use JSON; use JSON;
use Tie::IxHash; use Tie::IxHash;
use WebGUI::International; use WebGUI::International;
use WebGUI::Utility; use WebGUI::Utility;
use WebGUI::HTML; use WebGUI::HTML;
use WebGUI::ProgressBar; use WebGUI::ProgressBar;
use WebGUI::Storage; use WebGUI::Storage;
# Do not move this instruction!
use Archive::Any; use Archive::Any;
=head1 NAME =head1 NAME
@ -108,6 +113,12 @@ The name of the file archive to import.
A base set of properties to add to each file in the archive. A base set of properties to add to each file in the archive.
=head3 sortBy
Order in which files should be added to the gallery album. Legal values are
'name', 'date' and 'fileOrder'. If missing or invalid, files will be added as
ordered in the archive (default; corresponding to 'fileOrder').
=head3 $outputSub =head3 $outputSub
A callback to use for outputting data, most likely to a progress bar. It expects the A callback to use for outputting data, most likely to a progress bar. It expects the
@ -120,6 +131,7 @@ sub addArchive {
my $self = shift; my $self = shift;
my $filename = shift; my $filename = shift;
my $properties = shift; my $properties = shift;
my $sortBy = shift;
my $outputSub = shift || sub {}; my $outputSub = shift || sub {};
my $gallery = $self->getParent; my $gallery = $self->getParent;
my $session = $self->session; my $session = $self->session;
@ -139,6 +151,33 @@ sub addArchive {
find( { find( {
wanted => $wanted, wanted => $wanted,
}, $tempdirName ); }, $tempdirName );
# Sort files by date
if ($sortBy eq 'date') {
# Hash for storing last modified timestamps
my %mtimes;
my $exifTool = Image::ExifTool->new;
# Make ExifTool return epoch timestamps
$exifTool->Options('DateFormat', '%s');
# Iterate through all files
foreach my $file (@files) {
# Extract exif data from image
$exifTool->ExtractInfo( $file );
# Get last modified timestamp from exif data
$mtimes{$file} = $exifTool->GetValue('ModifyDate');
# Use last modified date of file as fallback
$mtimes{$file} = (stat($file))[9] unless $mtimes{$file};
}
# Sort files based on last modified timestamps
@files = sort { $mtimes{$a} <=> $mtimes{$b} } @files;
}
# Sort files by name
elsif ($sortBy eq 'name') {
@files = sort @files;
}
for my $filePath (@files) { for my $filePath (@files) {
my ($volume, $directory, $filename) = File::Spec->splitpath( $filePath ); my ($volume, $directory, $filename) = File::Spec->splitpath( $filePath );
@ -989,10 +1028,10 @@ sub www_addArchive {
value => ( $form->get("keywords") ), value => ( $form->get("keywords") ),
}); });
$var->{ form_location } $var->{ form_location }
= WebGUI::Form::Text( $session, { = WebGUI::Form::Text( $session, {
name => "location", name => "location",
value => ( $form->get("location") ), value => ( $form->get("location") ),
}); });
$var->{ form_friendsOnly } $var->{ form_friendsOnly }
@ -1000,6 +1039,17 @@ sub www_addArchive {
name => "friendsOnly", name => "friendsOnly",
value => ( $form->get("friendsOnly") ), value => ( $form->get("friendsOnly") ),
}); });
$var->{ form_sortBy }
= WebGUI::Form::RadioList( $session, {
name => "sortBy",
value => [ "name" ],
options => {
name => $i18n->get("addArchive sortBy name", 'Asset_GalleryAlbum'),
date => $i18n->get("addArchive sortBy date", 'Asset_GalleryAlbum'),
fileOrder => $i18n->get("addArchive sortBy fileOrder", 'Asset_GalleryAlbum'),
},
});
return $self->processStyle( return $self->processStyle(
$self->processTemplate($var, $self->getParent->get("templateIdAddArchive")) $self->processTemplate($var, $self->getParent->get("templateIdAddArchive"))
@ -1017,27 +1067,39 @@ Process the form for adding an archive.
sub www_addArchiveSave { sub www_addArchiveSave {
my $self = shift; my $self = shift;
# Return error message if the user viewing does not have permission to add files
return $self->session->privilege->insufficient unless $self->canAddFile; return $self->session->privilege->insufficient unless $self->canAddFile;
my $session = $self->session; my $session = $self->session;
my $form = $self->session->form; my $form = $self->session->form;
my $i18n = WebGUI::International->new( $session, 'Asset_GalleryAlbum' ); my $i18n = WebGUI::International->new( $session, 'Asset_GalleryAlbum' );
my $pb = WebGUI::ProgressBar->new($session); my $pb = WebGUI::ProgressBar->new($session);
# Retrieve properties and sort order from form variables
my $properties = { my $properties = {
keywords => $form->get("keywords"), keywords => $form->get("keywords"),
location => $form->get("location"), location => $form->get("location"),
friendsOnly => $form->get("friendsOnly"), friendsOnly => $form->get("friendsOnly"),
}; };
my $sortBy = $form->get("sortBy");
# Create progress bar to keep the connection alive
$pb->start($i18n->get('Uploading archive'), $session->url->extras('adminConsole/assets.gif')); $pb->start($i18n->get('Uploading archive'), $session->url->extras('adminConsole/assets.gif'));
# Retrieve storage containing the uploaded archive
my $storageId = $form->get("archive", "File"); my $storageId = $form->get("archive", "File");
my $storage = WebGUI::Storage->get( $session, $storageId ); my $storage = WebGUI::Storage->get( $session, $storageId );
if (!$storage) { if (!$storage) {
return $pb->finish($self->getUrl('func=addArchive;error='.$i18n->get('addArchive error too big'))); return $pb->finish($self->getUrl('func=addArchive;error='.$i18n->get('addArchive error too big')));
} }
my $filename = $storage->getPath( $storage->getFiles->[0] );
eval { $self->addArchive( $filename, $properties, sub{ $pb->update(sprintf $i18n->get(shift), @_); }); }; # Get the full path to the archive
my $filename = $storage->getPath( $storage->getFiles->[0] );
# Try to add files in archive as photos
eval { $self->addArchive( $filename, $properties, $sortBy, sub{ $pb->update(sprintf $i18n->get(shift), @_); }); };
# Delete storage containing archive
$storage->delete; $storage->delete;
if ( my $error = $@ ) { if ( my $error = $@ ) {
return $pb->finish($self->getUrl('func=addArchive;error='.sprintf $i18n->get('addArchive error generic'), $error )); return $pb->finish($self->getUrl('func=addArchive;error='.sprintf $i18n->get('addArchive error generic'), $error ));

View file

@ -258,6 +258,10 @@ our $HELP = {
name => 'form_friendsOnly', name => 'form_friendsOnly',
description => 'helpvar form_friendsOnly', description => 'helpvar form_friendsOnly',
}, },
{
name => 'form_sortBy',
description => 'helpvar form_sortBy',
},
], ],
}, },

View file

@ -287,6 +287,11 @@ our $I18N = {
message => 'Should the file be friends only?', message => 'Should the file be friends only?',
lastUpdated => 0, lastUpdated => 0,
}, },
'helpvar form_sortBy' => {
message => 'Property according to which photos should be sorted.',
lastUpdated => 0,
},
'helpvar url_yes' => { 'helpvar url_yes' => {
message => 'Confirm the delete of this Album.', message => 'Confirm the delete of this Album.',
@ -466,9 +471,33 @@ our $I18N = {
'addArchive friendsOnly' => { 'addArchive friendsOnly' => {
message => 'Friends Only', message => 'Friends Only',
lastUpdated => 0, lastUpdated => 0,
context => 'Label for the "friends only" field of the Add Archive page', context => 'Label for the "friendsOnly" field of the Add Archive page',
},
'addArchive sortBy' => {
message => 'Sort By',
lastUpdated => 0,
context => 'Label for the "sortBy" field of the Add Archive page',
}, },
'addArchive sortBy name' => {
message => 'Name',
lastUpdated => 0,
context => 'Label for the "Name" radio button',
},
'addArchive sortBy date' => {
message => 'Date',
lastUpdated => 0,
context => 'Label for the "Date" radio button',
},
'addArchive sortBy fileOrder' => {
message => 'File Order',
lastUpdated => 0,
context => 'Label for the "File Order" radio button',
},
'template addArchive title' => { 'template addArchive title' => {
message => "Add Zip Archive", message => "Add Zip Archive",
lastUpdated => 0, lastUpdated => 0,

View file

@ -25,7 +25,10 @@ use Test::Deep;
my $session = WebGUI::Test->session; my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode($session); my $node = WebGUI::Asset->getImportNode($session);
my $versionTag = WebGUI::VersionTag->getWorking($session); my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Album Test"});
$versionTag->set({name=>"Add Archive to Album Test"});
addToCleanup($versionTag);
my $gallery my $gallery
= $node->addChild({ = $node->addChild({
className => "WebGUI::Asset::Wobject::Gallery", className => "WebGUI::Asset::Wobject::Gallery",
@ -35,6 +38,7 @@ my $gallery
groupIdEdit => 3, # Admins groupIdEdit => 3, # Admins
ownerUserId => 3, # Admin ownerUserId => 3, # Admin
}); });
my $album my $album
= $gallery->addChild({ = $gallery->addChild({
className => "WebGUI::Asset::Wobject::GalleryAlbum", className => "WebGUI::Asset::Wobject::GalleryAlbum",
@ -53,16 +57,21 @@ my $properties = {
friendsOnly => "1", friendsOnly => "1",
}; };
$album->addArchive( WebGUI::Test->getTestCollateralPath('elephant_images.zip'), $properties );
$versionTag->commit; $versionTag->commit;
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Tests # Tests
plan tests => 8; plan tests => 11;
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Test the addArchive sub # Test the addArchive sub
# elephant_images.zip contains three jpgs: Aana1.jpg, Aana2.jpg, Aana3.jpg # elephant_images.zip contains three jpgs: Aana1.jpg, Aana2.jpg, Aana3.jpg
$versionTag = WebGUI::VersionTag->getWorking($session);
$album->addArchive( WebGUI::Test->getTestCollateralPath('elephant_images.zip'), $properties );
my $images = $album->getLineage(['descendants'], { returnObjects => 1 }); my $images = $album->getLineage(['descendants'], { returnObjects => 1 });
is( scalar @$images, 3, "addArchive() adds one asset per image" ); is( scalar @$images, 3, "addArchive() adds one asset per image" );
@ -112,11 +121,56 @@ cmp_bag(
"Photo assets are viewable by friends only" "Photo assets are viewable by friends only"
); );
#---------------------------------------------------------------------------- # Empty gallery album
# Test the www_addArchive page $versionTag->rollback;
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Cleanup # Test the sorting option of addArchive sub
END { # gallery_archive_sorting_test.zip contains four jpgs: photo1.jpg, photo2.jpg, photo3.jpg and photo4.jpg
$versionTag->rollback; # The following test covers sorting by date, name and file order (default).
}
$versionTag = WebGUI::VersionTag->getWorking($session);
# Add photos sorted by file order (default)
$album->addArchive( WebGUI::Test->getTestCollateralPath('gallery_archive_sorting_test.zip'), $properties, 'fileOrder' );
# Get all children
my $images = $album->getLineage(['descendants'], { returnObjects => 1 });
# Check order
cmp_deeply(
[ map { $_->get("filename") } @$images ],
[ "photo1.jpg", "photo2.jpg", "photo4.jpg", "photo3.jpg" ],
"Photos sorted by file order"
);
# Empty gallery album
$versionTag->rollback;
$versionTag = WebGUI::VersionTag->getWorking($session);
# Add photos sorted by date
$album->addArchive( WebGUI::Test->getTestCollateralPath('gallery_archive_sorting_test.zip'), $properties, 'date' );
# Get all children
my $images = $album->getLineage(['descendants'], { returnObjects => 1 });
# Check order
cmp_deeply(
[ map { $_->get("filename") } @$images ],
[ "photo4.jpg", "photo1.jpg", "photo3.jpg", "photo2.jpg" ],
"Photos sorted by date"
);
# Empty gallery album
$versionTag->rollback;
$versionTag = WebGUI::VersionTag->getWorking($session);
# Add photos sorted by name
$album->addArchive( WebGUI::Test->getTestCollateralPath('gallery_archive_sorting_test.zip'), $properties, 'name' );
# Get all children
my $images = $album->getLineage(['descendants'], { returnObjects => 1 });
# Check order
cmp_deeply(
[ map { $_->get("filename") } @$images ],
[ "photo1.jpg", "photo2.jpg", "photo3.jpg", "photo4.jpg" ],
"Photos sorted by name"
);
# Empty gallery album
$versionTag->rollback;
#----------------------------------------------------------------------------
# Test the www_addArchive page