diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 287e62ba5..9e655d863 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -11,6 +11,7 @@ - fixed #10189: pbworkflow000000000007 Hanging - fixed #11526: Wrong log error in file AssetClipboard.pm - fixed #11525: Paste assets inside CS + - added #620: Add buttons to the GalleryAlbum edit view so users can rotate photos by 90 deg (Bernd Kalbfuß-Zimmermann) 7.9.2 - added: Workflow to extend recurring Calendar events 2 years from the diff --git a/docs/upgrades/packages-7.9.3/root_import_gallery-templates_default-gallery-edit-album.wgpkg b/docs/upgrades/packages-7.9.3/root_import_gallery-templates_default-gallery-edit-album.wgpkg index 4fe5f417b..d086ccee2 100644 Binary files a/docs/upgrades/packages-7.9.3/root_import_gallery-templates_default-gallery-edit-album.wgpkg and b/docs/upgrades/packages-7.9.3/root_import_gallery-templates_default-gallery-edit-album.wgpkg differ diff --git a/lib/WebGUI/Asset/File/GalleryFile/Photo.pm b/lib/WebGUI/Asset/File/GalleryFile/Photo.pm index 9547b4784..3fa02ca54 100644 --- a/lib/WebGUI/Asset/File/GalleryFile/Photo.pm +++ b/lib/WebGUI/Asset/File/GalleryFile/Photo.pm @@ -390,6 +390,29 @@ sub processPropertiesFromFormPost { return undef; } + +#---------------------------------------------------------------------------- + +=head2 rotate ( angle ) + +Rotate the photo clockwise by the specified C (in degrees) including the +thumbnail and all resolutions. + +=cut + +sub rotate { + my $self = shift; + my $angle = shift; + my $storage = $self->getStorageLocation; + + # Rotate all files in the storage + foreach my $file (@{$storage->getFiles}) { + $storage->rotate($file, $angle); + } + # Re-create thumbnail + $self->generateThumbnail; +} + #---------------------------------------------------------------------------- =head2 setFile ( filename ) diff --git a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm index 0a33beb9a..9ef7f408a 100644 --- a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm +++ b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm @@ -23,6 +23,7 @@ use WebGUI::International; use WebGUI::Utility; use WebGUI::HTML; use WebGUI::ProgressBar; +use WebGUI::Storage; use Archive::Any; @@ -964,6 +965,7 @@ sub www_addArchive { $var->{ form_start } = WebGUI::Form::formHeader( $session, { action => $self->getUrl('func=addArchiveSave'), + name => 'name="galleryAlbumAddArchive"', }); $var->{ form_end } = WebGUI::Form::formFooter( $session ); @@ -1395,6 +1397,43 @@ sub www_edit { $session->errorHandler->error("Couldn't demote asset '$assetId' because we couldn't instantiate it."); } } + # Rotate to the left + elsif ( grep { $_ =~ /^rotateLeft-(.{22})$/ } $form->param ) { + my $assetId = ( grep { $_ =~ /^rotateLeft-(.{22})$/ } $form->param )[0]; + $assetId =~ s/^rotateLeft-//; + my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); + + if ( $asset ) { + # Add revision and create a new version tag by doing so + my $newRevision = $asset->addRevision; + # Rotate photo (i.e. all attached image files) by 90° CCW + $newRevision->rotate(-90); + # Auto-commit version tag + $newRevision->requestAutoCommit; + } + else { + $session->log->error("Couldn't rotate asset '$assetId' because we couldn't instantiate it."); + } + } + # Rotate to the right + elsif ( grep { $_ =~ /^rotateRight-(.{22})$/ } $form->param ) { + my $assetId = ( grep { $_ =~ /^rotateRight-(.{22})$/ } $form->param )[0]; + $assetId =~ s/^rotateRight-//; + my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); + + if ( $asset ) { + # Add revision and create a new version tag by doing so + my $newRevision = $asset->addRevision; + # Rotate photo (i.e. all attached image files) by 90° CW + $newRevision->rotate(90); + # Auto-commit version tag + $newRevision->requestAutoCommit; + } + else { + $session->log->error("Couldn't rotate asset '$assetId' because we couldn't instantiate it."); + } + } + # Delete the file elsif ( grep { $_ =~ /^delete-(.{22})$/ } $form->param ) { my $assetId = ( grep { $_ =~ /^delete-(.{22})$/ } $form->param )[0]; $assetId =~ s/^delete-//; @@ -1414,6 +1453,7 @@ sub www_edit { $var->{ form_start } = WebGUI::Form::formHeader( $session, { action => $self->getParent->getUrl('func=editSave;assetId=new;class='.__PACKAGE__), + extras => 'name="galleryAlbumAdd"', }) . WebGUI::Form::hidden( $session, { name => "ownerUserId", @@ -1432,6 +1472,7 @@ sub www_edit { $var->{ form_start } = WebGUI::Form::formHeader( $session, { action => $self->getUrl('func=edit'), + extras => 'name="galleryAlbumEdit"', }) . WebGUI::Form::hidden( $session, { name => "ownerUserId", @@ -1493,23 +1534,44 @@ sub www_edit { id => "assetIdThumbnail_$file->{ assetId }", } ); - # Raw HTML here to provide proper value for the image my $promoteLabel = $i18n->get( 'Move Up', 'Icon' ); $file->{ form_promote } - = qq{} - ; + = WebGUI::Form::submit( $session, { + name => "promote-$file->{assetId}", + value => $i18n->get( 'Move Up', 'Icon' ), + class => "promote", + }); my $demoteLabel = $i18n->get( 'Move Down', 'Icon' ); $file->{ form_demote } - = qq{} - ; + = WebGUI::Form::submit( $session, { + name => "demote-$file->{assetId}", + value => $i18n->get( 'Move Down', 'Icon' ), + class => "demote", + }); my $deleteConfirm = $i18n->get( 'template delete message', 'Asset_Photo' ); - my $deleteLabel = $i18n->get( 'Delete', 'Icon' ); $file->{ form_delete } - = qq{} - ; + = WebGUI::Form::submit( $session, { + name => "delete-$file->{assetId}", + value => $i18n->get( 'Delete', 'Icon' ), + class => "delete", + extras => "onclick=\"return confirm('$deleteConfirm')\"", + }); + + $file->{ form_rotateLeft } + = WebGUI::Form::submit( $session, { + name => "rotateLeft-$file->{assetId}", + value => $i18n->get( 'rotate left' ), + class => "rotateLeft", + }); + + $file->{ form_rotateRight } + = WebGUI::Form::submit( $session, { + name => "rotateRight-$file->{assetId}", + value => $i18n->get( 'rotate right' ), + class => "rotateRight", + }); $file->{ form_synopsis } = WebGUI::Form::HTMLArea( $session, { diff --git a/lib/WebGUI/Help/Asset_GalleryAlbum.pm b/lib/WebGUI/Help/Asset_GalleryAlbum.pm index b3c854269..b8a042a20 100644 --- a/lib/WebGUI/Help/Asset_GalleryAlbum.pm +++ b/lib/WebGUI/Help/Asset_GalleryAlbum.pm @@ -331,6 +331,14 @@ our $HELP = { name => 'form_demote', description => 'helpvar form_demote', }, + { + name => 'form_rotateLeft', + description => 'helpvar form_rotateLeft', + }, + { + name => 'form_rotateRight', + description => 'helpvar form_rotateRight', + }, { name => 'form_synopsis', description => 'helpvar form_synopsis', diff --git a/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm b/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm index 662b4847d..fd784e874 100644 --- a/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm +++ b/lib/WebGUI/i18n/English/Asset_GalleryAlbum.pm @@ -23,6 +23,18 @@ our $I18N = { context => "Label for Save button", }, + 'rotate left' => { + message => "90° CCW", + lastUpdated => 1270582436, + context => "Label for rotate left button", + }, + + 'rotate right' => { + message => "90° CW", + lastUpdated => 1270582436, + context => "Label for rotate right button", + }, + 'save message' => { message => 'Album settings saved.', lastUpdated => 0, @@ -38,12 +50,11 @@ our $I18N = { lastUpdated => 0, }, - 'delete message' => { message => 'Album has been deleted. Return to Gallery', lastUpdated => 0, }, - + 'help common title' => { message => 'Gallery Album Variables (Common)', lastUpdated => 0, @@ -524,6 +535,18 @@ our $I18N = { lastUpdated => 1213631346, context => q{Description of template variable}, }, + + 'helpvar form_rotateLeft' => { + message => q{A button to rotate the photo by 90° counter clockwise.}, + lastUpdated => 1270582436, + context => q{Description of template variable}, + }, + + 'helpvar form_rotateRight' => { + message => q{A button to rotate the photo by 90° clockwise.}, + lastUpdated => 1270582436, + context => q{Description of template variable}, + }, 'helpvar form_delete' => { message => q{A button to delete the image.}, diff --git a/t/Asset/File/GalleryFile/Photo/rotate.t b/t/Asset/File/GalleryFile/Photo/rotate.t new file mode 100644 index 000000000..b6a72f9c4 --- /dev/null +++ b/t/Asset/File/GalleryFile/Photo/rotate.t @@ -0,0 +1,109 @@ +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2009 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +use FindBin; +use strict; +use lib "$FindBin::Bin/../../../../lib"; + +# The goal of this test is to confirm correct rotation of all files attached +# to a Photo asset after calling the rotate method. +# We will only do a quick check by comparing dimensions of all attached files +# after rotation. Checks on individual pixels are alreay done in testing code +# for WebGUI::Storage + +use WebGUI::Test; +use WebGUI::Session; +use Test::More; +use Test::Deep; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode($session); +my $versionTag = WebGUI::VersionTag->getWorking($session); + +# Name version tag and make sure it gets cleaned up +$versionTag->set({name=>"Photo rotation test"}); +addToCleanup($versionTag); + +# Create gallery and a single album +my $gallery + = $node->addChild({ + className => "WebGUI::Asset::Wobject::Gallery", + imageResolutions => "1024x768", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); +my $album + = $gallery->addChild({ + className => "WebGUI::Asset::Wobject::GalleryAlbum", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); + +# Create single photo inside the album +my $photo + = $album->addChild({ + className => "WebGUI::Asset::File::GalleryFile::Photo", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); + +# Attach image file to photo asset (setFile also makes download versions) +$photo->setFile( WebGUI::Test->getTestCollateralPath("rotation_test.png") ); +my $storage = $photo->getStorageLocation; + +# Commit all changes +$versionTag->commit; + +#---------------------------------------------------------------------------- + +plan tests => 2; + +#---------------------------------------------------------------------------- + +# Save dimensions of images +my @oldDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @oldDims, [ $storage->getSizeInPixels($file) ] ) unless $file eq '.'; +} + +# Rotate photo (i.e. all attached images) by 90° CW +$photo->rotate(90); + +# Save new dimensions of images in reverse order +my @newDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @newDims, [ reverse($storage->getSizeInPixels($file)) ] ) unless $file eq '.'; +} + +# Compare dimensions +cmp_deeply( \@oldDims, \@newDims, "Check if all files were rotated by 90° CW" ); + +# Rotate photo (i.e. all attached images) by 90° CCW +$photo->rotate(-90); + +# Save new dimensions of images in original order +my @newerDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @newerDims, [ $storage->getSizeInPixels($file) ] ) unless $file eq '.'; +} + +# Compare dimensions +cmp_deeply( \@oldDims, \@newerDims, "Check if all files were rotated by 90° CCW" ); diff --git a/t/Asset/Wobject/GalleryAlbum/edit.t b/t/Asset/Wobject/GalleryAlbum/edit.t index b250ac53a..50982aa93 100644 --- a/t/Asset/Wobject/GalleryAlbum/edit.t +++ b/t/Asset/Wobject/GalleryAlbum/edit.t @@ -9,9 +9,10 @@ # http://www.plainblack.com info@plainblack.com #------------------------------------------------------------------ -# Test editing a GalleryAlbum from the web interface -# -# +# Test editing a GalleryAlbum from the web interface. Currently, it +# is tested whether... +# - users can add albums. +# - photos can be rotated. use FindBin; use strict; @@ -73,7 +74,7 @@ if ( !$mech->success ) { plan skip_all => "Cannot load URL '$baseUrl'. Will not test."; } -plan tests => 6; # Increment this number for each test you create +plan tests => 11; # Increment this number for each test you create #---------------------------------------------------------------------------- # Visitor user cannot add albums @@ -112,6 +113,65 @@ $mech->content_contains( my $album = WebGUI::Asset->newByDynamicClass( $session, $gallery->getAlbumIds->[0] ); cmp_deeply( $properties, subhashof( $album->get ), "Properties from edit form are set correctly" ); +#---------------------------------------------------------------------------- +# Photos can be rotated using the respective form buttons + +# Use album from previous test +my $album = $gallery->getFirstChild; + +# Add single photo to this album. No need to commit since auto-commit was +# enabled for the Gallery asset. +my $photo + = $album->addChild({ + className => "WebGUI::Asset::File::GalleryFile::Photo", + }); +my $photoId = $photo->getId; + +# Attach image file to photo asset (setFile also makes download versions) +$photo->setFile( WebGUI::Test->getTestCollateralPath("rotation_test.png") ); +my $storage = $photo->getStorageLocation; + +# Save dimensions of images +my @oldDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @oldDims, [ $storage->getSizeInPixels($file) ] ) unless $file eq '.'; +} + +# Rotate photo (i.e. all attached images) by 90° CW +$mech->get_ok( $baseUrl . $album->getUrl('func=edit'), 'Request GalleryAlbum edit screen' ); +# Select the proper form +$mech->form_name( 'galleryAlbumEdit' ); +# Try to click the "rotate right" button +$mech->submit_form_ok( { + button => 'rotateRight-' . $photoId, +}, 'Request rotation of photo by 90° CW' ); + +# Save new dimensions of images in reverse order +my @newDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @newDims, [ reverse($storage->getSizeInPixels($file)) ] ) unless $file eq '.'; +} + +# Compare dimensions +cmp_deeply( \@oldDims, \@newDims, "Check if all files were rotated by 90° CW" ); + +# Rotate photo (i.e. all attached images) by 90° CCW. No need to request the edit view since +# an updated view was returned after the last form submittal. +$mech->form_name( 'galleryAlbumEdit' ); +# Try to click the "rotate left" button +$mech->submit_form_ok( { + button => 'rotateLeft-' . $photoId, +}, 'Request rotation of photo by 90° CCW' ); + +# Save new dimensions of images in original order +my @newerDims; +foreach my $file ( @{$storage->getFiles('showAll') } ) { + push ( @newerDims, [ $storage->getSizeInPixels($file) ] ) unless $file eq '.'; +} + +# Compare dimensions +cmp_deeply( \@oldDims, \@newerDims, "Check if all files were rotated by 90° CCW" ); + #---------------------------------------------------------------------------- # getMechLogin( baseUrl, WebGUI::User, "identifier" ) # Returns a Test::WWW::Mechanize session after logging in the given user using diff --git a/t/Storage/Image.t b/t/Storage/Image.t index 4a04d5bcd..288f2de87 100644 --- a/t/Storage/Image.t +++ b/t/Storage/Image.t @@ -65,7 +65,7 @@ my $extensionTests = [ }, ]; -plan tests => 49 + scalar @{ $extensionTests }; # increment this value for each test you create +plan tests => 54 + scalar @{ $extensionTests }; # increment this value for each test you create my $session = WebGUI::Test->session; @@ -277,6 +277,40 @@ foreach my $testImage (@testImages) { $session->setting->set('maxImageSize', $origMaxImageSize ); +#################################################### +# +# rotate +# +#################################################### + +my $rotateTest = WebGUI::Storage->create( $session ); +WebGUI::Test->storagesToDelete($rotateTest); + +# Add test image to the storage +ok( $rotateTest->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath("rotation_test.png")), "Can add test image to storage" ); + +# Rotate test image by 90° CW +my $file = $rotateTest->getFiles->[0]; +$rotateTest->rotate($file, 90); +# Check dimensions +cmp_bag( [$rotateTest->getSizeInPixels( $file )], [2,3], "Check size of photo after rotating 90° CW" ); +# Check pixels +my $image = Image::Magick->new; +$image->Read( $rotateTest->getPath($file) ); +is( $image->GetPixel(x=>2, y=>0), 0, "Pixel at location [2,0] should be black" ); + +# Rotate test image by 90° CCW +my $file = $rotateTest->getFiles->[0]; +$rotateTest->rotate($file, -90); +# Check dimensions +cmp_bag( [$rotateTest->getSizeInPixels( $file )], [3,2], "Check size of photo after rotating 90° CCW" ); +# Check pixels +$image = Image::Magick->new; +$image->Read( $rotateTest->getPath($file) ); +is( $image->GetPixel(x=>0, y=>0), 0, "Pixel at location [0,0] should be black" ); + + + TODO: { local $TODO = "Methods that need to be tested"; ok(0, 'resize'); diff --git a/t/supporting_collateral/rotation_test.png b/t/supporting_collateral/rotation_test.png new file mode 100644 index 000000000..5861033a4 Binary files /dev/null and b/t/supporting_collateral/rotation_test.png differ