diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 266e67403..11a0e4e6b 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,5 +1,6 @@ 7.10.14 - fixed #12094: Cannot enter in Macros in URLs inside TinyMCE. + - rfe #12093: Remotely stored photos for Story assets 7.10.13 - added #12079: Carousel Auto Play diff --git a/docs/upgrades/packages-7.10.14/root_import_storymanager_editstory.wgpkg b/docs/upgrades/packages-7.10.14/root_import_storymanager_editstory.wgpkg new file mode 100644 index 000000000..5729a5db3 Binary files /dev/null and b/docs/upgrades/packages-7.10.14/root_import_storymanager_editstory.wgpkg differ diff --git a/lib/WebGUI/Asset/Story.pm b/lib/WebGUI/Asset/Story.pm index 4a854197d..5f7e46049 100644 --- a/lib/WebGUI/Asset/Story.pm +++ b/lib/WebGUI/Asset/Story.pm @@ -467,6 +467,10 @@ sub getEditForm { imgThumb => $filename ? $storage->getThumbnailUrl($filename) : '', imgUrl => $filename ? $storage->getUrl($filename) : '', imgFilename => $filename ? $filename : '', + imgRemoteUrlForm => WebGUI::Form::text($session, { + name => 'imgRemoteUrl'.$photoIndex, + value => $photo->{remoteUrl}, + }), newUploadForm => WebGUI::Form::file($session, { name => 'newPhoto' . $photoIndex, maxAttachments => 1, @@ -498,6 +502,9 @@ sub getEditForm { }; } push @{ $var->{ photo_form_loop } }, { + imgRemoteUrlForm => WebGUI::Form::text($session, { + name => 'imgRemoteUrl', + }), newUploadForm => WebGUI::Form::image($session, { name => 'newPhoto', maxAttachments => 1, @@ -635,16 +642,20 @@ sub processPropertiesFromFormPost { PHOTO: foreach my $photoIndex (1..$numberOfPhotos) { ##TODO: Deletion check and storage cleanup my $storageId = $photoData->[$photoIndex-1]->{storageId}; + my $storage = $storageId && WebGUI::Storage->get($session, $storageId); + my $remote = $form->process("imgRemoteUrl$photoIndex"); if ($form->process('deletePhoto'.$photoIndex, 'yesNo')) { - my $storage = WebGUI::Storage->get($session, $storageId); $storage->delete if $storage; splice @{ $photoData }, $photoIndex-1, 1; next PHOTO; } + ##Process photos with urls that replace existing photos + if ($remote) { + $storage->delete() if $storage; + } ##Process uploads that replace existing photos - if (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) { + elsif (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) { my $upload = WebGUI::Storage->get($session, $uploadId); - my $storage = WebGUI::Storage->get($session, $storageId); $storage->clear; my $filename = $upload->getFiles->[0]; $storage->addFileFromFilesystem($upload->getPath($filename)); @@ -655,31 +666,43 @@ sub processPropertiesFromFormPost { $upload->delete; } my $newPhoto = { - storageId => $storageId, caption => $form->process('imgCaption'.$photoIndex, 'text'), alt => $form->process('imgAlt' .$photoIndex, 'text'), title => $form->process('imgTitle' .$photoIndex, 'text'), byLine => $form->process('imgByline' .$photoIndex, 'text'), url => $form->process('imgUrl' .$photoIndex, 'url' ), }; + if ($remote) { + $newPhoto->{remoteUrl} = $remote; + } + else { + $newPhoto->{storageId} = $storageId; + } splice @{ $photoData }, $photoIndex-1, 1, $newPhoto; } my $newStorageId = $form->process('newPhoto', 'image'); - if ($newStorageId) { - my $newStorage = WebGUI::Storage->get($session, $newStorageId); - my $photoName = $newStorage->getFiles->[0]; - my ($width, $height) = $newStorage->getSizeInPixels($photoName); - if ($width > $self->getArchive->get('photoWidth')) { - $newStorage->resize($photoName, $self->getArchive->get('photoWidth')); - } - push @{ $photoData }, { + my $newRemote = $form->process('imgRemoteUrl'); + if ($newStorageId || $newRemote) { + my $newPhoto = { caption => $form->process('newImgCaption', 'text'), alt => $form->process('newImgAlt', 'text'), title => $form->process('newImgTitle', 'text'), byLine => $form->process('newImgByline', 'text'), url => $form->process('newImgUrl', 'url'), - storageId => $newStorageId, }; + if ($newRemote) { + $newPhoto->{remoteUrl} = $newRemote; + } + else { + my $newStorage = WebGUI::Storage->get($session, $newStorageId); + my $photoName = $newStorage->getFiles->[0]; + my ($width, $height) = $newStorage->getSizeInPixels($photoName); + if ($width > $self->getArchive->get('photoWidth')) { + $newStorage->resize($photoName, $self->getArchive->get('photoWidth')); + } + $newPhoto->{storageId} = $newStorageId; + } + push @{ $photoData }, $newPhoto; } $self->setPhotoData($photoData); $self->{_parent} = $archive; ##Restore archive, for URL and other calculations @@ -721,8 +744,9 @@ Remove the storage locations for this revision of the Asset. sub purgeRevision { my $self = shift; my $session = $self->session; - foreach my $photo ( @{ $self->getPhotoData} ) { - my $storage = WebGUI::Storage->get($session, $self-$photo->{storageId}); + PHOTO: foreach my $photo ( @{ $self->getPhotoData} ) { + my $id = $photo->{storageId} or next PHOTO; + my $storage = WebGUI::Storage->get($session, $id); $storage->delete if $storage; } return $self->next::method; @@ -934,11 +958,19 @@ sub viewTemplateVariables { $var->{photo_loop} = []; my $photoCounter = 0; PHOTO: foreach my $photo (@{ $photoData }) { - next PHOTO unless $photo->{storageId}; - my $storage = WebGUI::Storage->get($session, $photo->{storageId}); - my $file = $storage->getFiles->[0]; - next PHOTO unless $file; - my $imageUrl = $storage->getUrl($file); + my $imageUrl; + if (my $remote = $photo->{remoteUrl}) { + $imageUrl = $remote; + } + elsif (my $id = $photo->{storageId}) { + my $storage = WebGUI::Storage->get($session, $photo->{storageId}); + my $file = $storage->getFiles->[0]; + next PHOTO unless $file; + $imageUrl = $storage->getUrl($file); + } + else { + next PHOTO; + } push @{ $var->{photo_loop} }, { imageUrl => $imageUrl, imageCaption => $photo->{caption}, diff --git a/lib/WebGUI/Help/Asset_Story.pm b/lib/WebGUI/Help/Asset_Story.pm index 214747381..f6fd4d2b1 100644 --- a/lib/WebGUI/Help/Asset_Story.pm +++ b/lib/WebGUI/Help/Asset_Story.pm @@ -37,6 +37,7 @@ our $HELP = { { name => 'imgUrl', }, { name => 'imgFilename', }, { name => 'newUploadForm', }, + { name => 'imgRemoteUrlForm', }, { name => 'imgCaptionForm', }, { name => 'imgBylineForm', }, { name => 'imgAltForm', }, diff --git a/lib/WebGUI/i18n/English/Asset_Story.pm b/lib/WebGUI/i18n/English/Asset_Story.pm index 1b7e2ce79..628074062 100644 --- a/lib/WebGUI/i18n/English/Asset_Story.pm +++ b/lib/WebGUI/i18n/English/Asset_Story.pm @@ -292,6 +292,12 @@ our $I18N = { lastUpdated => 0, }, + 'imgRemoteUrlForm' => { + message => q|A form field to specify a remote url for a photo.|, + context => q|Template variable for edit form.|, + lastUpdated => 0, + }, + 'newUploadForm' => { message => q|A form field to upload an image.|, context => q|Template variable for edit form.|, @@ -334,6 +340,13 @@ our $I18N = { lastUpdated => 0, }, + 'photo remote url' => { + message => 'Photo Remote URL', + context => 'Label in the edit story form. Location of image (instead + of uploaded location)', + lastUpdated => 0, + }, + 'photo caption' => { message => q|Photo Caption|, context => q|Label in the edit story form. Short for Photograph Caption.|, diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index a973d2221..5bb42ba55 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -290,6 +290,11 @@ our $I18N = { lastUpdated => 1065356764 }, + 'or' => { + message => q|or|, + lastUpdated => 1053804577, + }, + '978' => { message => q|User added successfully.|, lastUpdated => 1053804577 diff --git a/t/Asset/Story.t b/t/Asset/Story.t index 92f939427..53e21b740 100644 --- a/t/Asset/Story.t +++ b/t/Asset/Story.t @@ -332,6 +332,14 @@ $story->setPhotoData([ title => '', url => 'http://www.lamp.com', }, + { + remoteUrl => 'http://www.plainblack.com/rockstar.jpg', + caption => 'Elvis', + byLine => 'The King', + alt => '(impersonator)', + title => 'Rockstar Support', + url => 'http://plainblack.com/services/support/rockstar-support', + }, ]); @@ -362,6 +370,15 @@ cmp_bag( is ($viewVariables->{updatedTimeEpoch}, $story->get('revisionDate'), 'viewTemplateVariables: updatedTimeEpoch'); +my $rockstarVar = { + imageUrl => 'http://www.plainblack.com/rockstar.jpg', + imageCaption => 'Elvis', + imageByline => 'The King', + imageAlt => '(impersonator)', + imageTitle => 'Rockstar Support', + imageLink => 'http://plainblack.com/services/support/rockstar-support', +}; + cmp_deeply( $viewVariables->{photo_loop}, [ @@ -381,6 +398,7 @@ cmp_deeply( imageTitle => '', imageLink => 'http://www.lamp.com', }, + $rockstarVar, ], 'viewTemplateVariables: photo_loop is okay' ); @@ -389,20 +407,14 @@ ok(! $viewVariables->{singlePhoto}, 'viewVariables: singlePhoto: there is more t ok( $viewVariables->{hasPhotos}, 'viewVariables: hasPhotos: it has photos'); ##Simulate someone deleting the file stored in the storage object. +$storage1->deleteFile('gooey.jpg'); $storage2->deleteFile('lamp.jpg'); $viewVariables = $story->viewTemplateVariables; cmp_deeply( $viewVariables->{photo_loop}, [ - { - imageUrl => re('gooey.jpg'), - imageCaption => 'Mascot for a popular CMS', - imageByline => 'Darcy Gibson', - imageAlt => 'Gooey', - imageTitle => 'Mascot', - imageLink => 'http://www.webgui.org', - }, + $rockstarVar, ], 'viewTemplateVariables: photo_loop: if the storage has no files, it is not shown' );