Merge remote branch 'spunky/rfe11517'
This commit is contained in:
commit
96a52c5748
7 changed files with 225 additions and 23 deletions
|
|
@ -21,6 +21,8 @@
|
|||
- fixed #11563: Syndicated Content - descriptionFirstParagraph cuts off
|
||||
- fixed #11538: User invite mail: whitespace in message lost
|
||||
- fixed #11549: Shortcut Asset cannot override Page Layout
|
||||
- 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
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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 );
|
||||
|
|
@ -988,12 +1027,29 @@ sub www_addArchive {
|
|||
name => "keywords",
|
||||
value => ( $form->get("keywords") ),
|
||||
});
|
||||
|
||||
$var->{ form_location }
|
||||
= WebGUI::Form::Text( $session, {
|
||||
name => "location",
|
||||
value => ( $form->get("location") ),
|
||||
});
|
||||
|
||||
$var->{ form_friendsOnly }
|
||||
= WebGUI::Form::yesNo( $session, {
|
||||
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"))
|
||||
|
|
@ -1011,26 +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 ));
|
||||
|
|
|
|||
|
|
@ -250,10 +250,18 @@ our $HELP = {
|
|||
name => 'form_keywords',
|
||||
description => 'helpvar form_keywords',
|
||||
},
|
||||
{
|
||||
name => 'form_location',
|
||||
description => 'helpvar form_location',
|
||||
},
|
||||
{
|
||||
name => 'form_friendsOnly',
|
||||
description => 'helpvar form_friendsOnly',
|
||||
},
|
||||
{
|
||||
name => 'form_sortBy',
|
||||
description => 'helpvar form_sortBy',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -277,11 +277,21 @@ our $I18N = {
|
|||
message => 'The keywords for the files being uploaded.',
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'helpvar form_location' => {
|
||||
message => 'The location for the files being uploaded.',
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'helpvar form_friendsOnly' => {
|
||||
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.',
|
||||
|
|
@ -451,13 +461,43 @@ our $I18N = {
|
|||
lastUpdated => 0,
|
||||
context => 'Label for the "keywords" field of the Add Archive page',
|
||||
},
|
||||
|
||||
|
||||
'addArchive location' => {
|
||||
message => 'Location',
|
||||
lastUpdated => 0,
|
||||
context => 'Label for the "location" field of the Add Archive page',
|
||||
},
|
||||
|
||||
'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,
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
@ -46,48 +50,127 @@ my $album
|
|||
skipAutoCommitWorkflows => 1,
|
||||
});
|
||||
|
||||
$album->addArchive( WebGUI::Test->getTestCollateralPath('elephant_images.zip') );
|
||||
# Properties applied to every photo in the archive
|
||||
my $properties = {
|
||||
keywords => "something",
|
||||
location => "somewhere",
|
||||
friendsOnly => "1",
|
||||
};
|
||||
|
||||
$versionTag->commit;
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
plan tests => 5;
|
||||
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" );
|
||||
cmp_deeply(
|
||||
cmp_bag(
|
||||
[ map { $_->get("filename") } @$images ],
|
||||
bag( "Aana1.jpg", "Aana2.jpg", "Aana3.jpg" ),
|
||||
[ "Aana1.jpg", "Aana2.jpg", "Aana3.jpg" ],
|
||||
"Names of files attached to Photo assets match filenames in archive"
|
||||
);
|
||||
|
||||
cmp_deeply(
|
||||
cmp_bag(
|
||||
[ map { $_->get("title") } @$images ],
|
||||
bag( "Aana1", "Aana2", "Aana3" ),
|
||||
[ "Aana1", "Aana2", "Aana3" ],
|
||||
"Titles of Photo assets match filenames in archive excluding extensions"
|
||||
);
|
||||
|
||||
cmp_deeply(
|
||||
cmp_bag(
|
||||
[ map { $_->get("menuTitle") } @$images ],
|
||||
bag( "Aana1", "Aana2", "Aana3" ),
|
||||
[ "Aana1", "Aana2", "Aana3" ],
|
||||
"Menu titles of Photo assets match filenames in archive excluding extensions"
|
||||
);
|
||||
|
||||
cmp_deeply(
|
||||
cmp_bag(
|
||||
[ map { $_->get("url") } @$images ],
|
||||
bag(
|
||||
[
|
||||
$session->url->urlize( $album->getUrl . "/Aana1" ),
|
||||
$session->url->urlize( $album->getUrl . "/Aana2" ),
|
||||
$session->url->urlize( $album->getUrl . "/Aana3" ),
|
||||
),
|
||||
],
|
||||
"URLs of Photo assets match filenames in archive excluding extensions"
|
||||
);
|
||||
|
||||
cmp_bag(
|
||||
[ map { $_->get("keywords") } @$images ],
|
||||
[ "something", "something", "something" ],
|
||||
"Keywords of Photo assets match keywords in properties"
|
||||
);
|
||||
|
||||
cmp_bag(
|
||||
[ map { $_->get("location") } @$images ],
|
||||
[ "somewhere", "somewhere", "somewhere" ],
|
||||
"Location of Photo assets match keywords in properties"
|
||||
);
|
||||
|
||||
cmp_bag(
|
||||
[ map { $_->get("friendsOnly") } @$images ],
|
||||
[ "1", "1", "1" ],
|
||||
"Photo assets are viewable by friends only"
|
||||
);
|
||||
|
||||
# Empty gallery album
|
||||
$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
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Cleanup
|
||||
END {
|
||||
$versionTag->rollback;
|
||||
}
|
||||
|
|
|
|||
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