From 8030bed30bacb86d70c6281b03a31ddf2af72b9d Mon Sep 17 00:00:00 2001 From: kimd Date: Mon, 17 May 2010 22:03:38 +0200 Subject: [PATCH] Gallery: Sorting of files uploaded in zip archives (RFE 11517) --- docs/changelog/7.x.x.txt | 1 + lib/WebGUI/Asset/Wobject/GalleryAlbum.pm | 74 ++++++++++++++++-- lib/WebGUI/Help/Asset_GalleryAlbum.pm | 4 + lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm | 31 +++++++- t/Asset/Wobject/GalleryAlbum/addArchive.t | 72 ++++++++++++++--- .../gallery_archive_sorting_test.zip | Bin 0 -> 26467 bytes 6 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 t/supporting_collateral/gallery_archive_sorting_test.zip diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 0001a0852..584395f38 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,5 +1,6 @@ 7.9.5 - added #11502: Gallery: Allow specification of location when uploading ZIP archives + - added #11517: Gallery: Sorting of files uploaded in zip archives 7.9.4 - We're shipping underscore.js now for its suite of extremely handy utility diff --git a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm index 16a82ef49..9d600c6f7 100644 --- a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm +++ b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm @@ -11,20 +11,25 @@ package WebGUI::Asset::Wobject::GalleryAlbum; #------------------------------------------------------------------- use strict; -use Class::C3; use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject); + + +use Class::C3; use Carp qw( croak ); use File::Find; use File::Spec; use File::Temp qw{ tempdir }; +use Image::ExifTool qw( :Public ); use JSON; use Tie::IxHash; + use WebGUI::International; use WebGUI::Utility; use WebGUI::HTML; use WebGUI::ProgressBar; use WebGUI::Storage; +# Do not move this instruction! use Archive::Any; =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. +=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 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 $filename = shift; my $properties = shift; + my $sortBy = shift; my $outputSub = shift || sub {}; my $gallery = $self->getParent; my $session = $self->session; @@ -139,6 +151,33 @@ sub addArchive { find( { wanted => $wanted, }, $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) { my ($volume, $directory, $filename) = File::Spec->splitpath( $filePath ); @@ -989,10 +1028,10 @@ sub www_addArchive { value => ( $form->get("keywords") ), }); - $var->{ form_location } + $var->{ form_location } = WebGUI::Form::Text( $session, { - name => "location", - value => ( $form->get("location") ), + name => "location", + value => ( $form->get("location") ), }); $var->{ form_friendsOnly } @@ -1000,6 +1039,17 @@ sub www_addArchive { name => "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( $self->processTemplate($var, $self->getParent->get("templateIdAddArchive")) @@ -1017,27 +1067,39 @@ Process the form for adding an archive. sub www_addArchiveSave { 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; my $session = $self->session; my $form = $self->session->form; my $i18n = WebGUI::International->new( $session, 'Asset_GalleryAlbum' ); my $pb = WebGUI::ProgressBar->new($session); + + # Retrieve properties and sort order from form variables my $properties = { keywords => $form->get("keywords"), location => $form->get("location"), 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')); + + # Retrieve storage containing the uploaded archive my $storageId = $form->get("archive", "File"); my $storage = WebGUI::Storage->get( $session, $storageId ); if (!$storage) { 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; if ( my $error = $@ ) { return $pb->finish($self->getUrl('func=addArchive;error='.sprintf $i18n->get('addArchive error generic'), $error )); diff --git a/lib/WebGUI/Help/Asset_GalleryAlbum.pm b/lib/WebGUI/Help/Asset_GalleryAlbum.pm index 7c874ee04..e334118cc 100644 --- a/lib/WebGUI/Help/Asset_GalleryAlbum.pm +++ b/lib/WebGUI/Help/Asset_GalleryAlbum.pm @@ -258,6 +258,10 @@ our $HELP = { name => 'form_friendsOnly', description => 'helpvar form_friendsOnly', }, + { + name => 'form_sortBy', + description => 'helpvar form_sortBy', + }, ], }, diff --git a/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm b/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm index f033cfd18..895a39bb7 100644 --- a/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm +++ b/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm @@ -287,6 +287,11 @@ our $I18N = { message => 'Should the file be friends only?', lastUpdated => 0, }, + + 'helpvar form_sortBy' => { + message => 'Property according to which photos should be sorted.', + lastUpdated => 0, + }, 'helpvar url_yes' => { message => 'Confirm the delete of this Album.', @@ -466,9 +471,33 @@ our $I18N = { 'addArchive friendsOnly' => { message => 'Friends Only', 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' => { message => "Add Zip Archive", lastUpdated => 0, diff --git a/t/Asset/Wobject/GalleryAlbum/addArchive.t b/t/Asset/Wobject/GalleryAlbum/addArchive.t index cc565a862..afa56d598 100644 --- a/t/Asset/Wobject/GalleryAlbum/addArchive.t +++ b/t/Asset/Wobject/GalleryAlbum/addArchive.t @@ -25,7 +25,10 @@ use Test::Deep; my $session = WebGUI::Test->session; my $node = WebGUI::Asset->getImportNode($session); my $versionTag = WebGUI::VersionTag->getWorking($session); -$versionTag->set({name=>"Album Test"}); + +$versionTag->set({name=>"Add Archive to Album Test"}); +addToCleanup($versionTag); + my $gallery = $node->addChild({ className => "WebGUI::Asset::Wobject::Gallery", @@ -35,6 +38,7 @@ my $gallery groupIdEdit => 3, # Admins ownerUserId => 3, # Admin }); + my $album = $gallery->addChild({ className => "WebGUI::Asset::Wobject::GalleryAlbum", @@ -53,16 +57,21 @@ my $properties = { friendsOnly => "1", }; -$album->addArchive( WebGUI::Test->getTestCollateralPath('elephant_images.zip'), $properties ); $versionTag->commit; + #---------------------------------------------------------------------------- # Tests -plan tests => 8; +plan tests => 11; + #---------------------------------------------------------------------------- # Test the addArchive sub # 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 }); is( scalar @$images, 3, "addArchive() adds one asset per image" ); @@ -112,11 +121,56 @@ cmp_bag( "Photo assets are viewable by friends only" ); -#---------------------------------------------------------------------------- -# Test the www_addArchive page +# Empty gallery album +$versionTag->rollback; #---------------------------------------------------------------------------- -# Cleanup -END { - $versionTag->rollback; -} +# Test the sorting option of addArchive sub +# gallery_archive_sorting_test.zip contains four jpgs: photo1.jpg, photo2.jpg, photo3.jpg and photo4.jpg +# 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 diff --git a/t/supporting_collateral/gallery_archive_sorting_test.zip b/t/supporting_collateral/gallery_archive_sorting_test.zip new file mode 100644 index 0000000000000000000000000000000000000000..1ccc6deffbe28b4473e6a05c631ff4f82c041403 GIT binary patch literal 26467 zcmeF(Ly#yuz^LhVpSErDv~AnAZQHhO+qP}nw$1rw7JuEUd)HGlRcDdxvq~yY-pEM; zgCGL{0Q>=ft*zq<=OBHP!~g(j`for2U<25h**e)W(pcD;Dl0(%0AEVqNoLC2Njkeh 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 X^%sxm>aUZzaycL3