Gallery: Sorting of files uploaded in zip archives (RFE 11517)
This commit is contained in:
parent
95e9e52389
commit
8030bed30b
6 changed files with 166 additions and 16 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ));
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
BIN
t/supporting_collateral/gallery_archive_sorting_test.zip
Normal file
BIN
t/supporting_collateral/gallery_archive_sorting_test.zip
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue