From 387942e68d3c8a0a6631ddf86ecf78b3ca7e3b3c Mon Sep 17 00:00:00 2001 From: kimd Date: Tue, 25 May 2010 22:06:06 +0200 Subject: [PATCH] Added search by location to the Gallery (RFE 11504) --- docs/changelog/7.x.x.txt | 1 + ...ery-templates_default-gallery-search.wgpkg | Bin 0 -> 3284 bytes lib/WebGUI/Asset/File.pm | 1 + lib/WebGUI/Asset/File/GalleryFile/Photo.pm | 16 + lib/WebGUI/Asset/Wobject/Gallery.pm | 125 +++++-- lib/WebGUI/Help/Asset_Gallery.pm | 4 + lib/WebGUI/i18n/English/Asset_Gallery.pm | 11 + t/Asset/Wobject/Gallery/search.t | 318 ++++++++++++++++++ 8 files changed, 446 insertions(+), 30 deletions(-) create mode 100644 docs/upgrades/packages-7.9.6/root_import_gallery-templates_default-gallery-search.wgpkg create mode 100644 t/Asset/Wobject/Gallery/search.t diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 4aa41df86..b70054b86 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -14,6 +14,7 @@ - fixed #11589: Syndicated Content: Return raw text for sentence and word template variables - fixed #11573: user has no way of knowing what they are currently using - fixed #11603: Shelf, template variables for sub shelves + - added #11504: Allow search by location in the gallery 7.9.5 - Asset->www_copy now has a progress bar diff --git a/docs/upgrades/packages-7.9.6/root_import_gallery-templates_default-gallery-search.wgpkg b/docs/upgrades/packages-7.9.6/root_import_gallery-templates_default-gallery-search.wgpkg new file mode 100644 index 0000000000000000000000000000000000000000..0fd040d1f99e7842c21e542b4b055af68fff9e28 GIT binary patch literal 3284 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 STj2lI0{;V_7 literal 0 HcmV?d00001 diff --git a/lib/WebGUI/Asset/File.pm b/lib/WebGUI/Asset/File.pm index d1eca73bd..563d75180 100644 --- a/lib/WebGUI/Asset/File.pm +++ b/lib/WebGUI/Asset/File.pm @@ -379,6 +379,7 @@ sub indexContent { my $self = shift; my $indexer = $self->SUPER::indexContent; $indexer->addFile($self->getStorageLocation->getPath($self->get("filename"))); + return $indexer; } diff --git a/lib/WebGUI/Asset/File/GalleryFile/Photo.pm b/lib/WebGUI/Asset/File/GalleryFile/Photo.pm index 7f1af4da8..9bb51f134 100644 --- a/lib/WebGUI/Asset/File/GalleryFile/Photo.pm +++ b/lib/WebGUI/Asset/File/GalleryFile/Photo.pm @@ -372,6 +372,22 @@ sub getThumbnailUrl { ); } +#------------------------------------------------------------------- + +=head2 indexContent ( ) + +Indexing the content of the Photo. See WebGUI::Asset::indexContent() for +additonal details. + +=cut + +sub indexContent { + my $self = shift; + my $indexer = $self->SUPER::indexContent; + $indexer->addKeywords($self->get("location")); + return $indexer; +} + #---------------------------------------------------------------------------- =head2 makeResolutions ( [resolutions] ) diff --git a/lib/WebGUI/Asset/Wobject/Gallery.pm b/lib/WebGUI/Asset/Wobject/Gallery.pm index 1374dff07..3a3b059c0 100644 --- a/lib/WebGUI/Asset/Wobject/Gallery.pm +++ b/lib/WebGUI/Asset/Wobject/Gallery.pm @@ -13,12 +13,15 @@ package WebGUI::Asset::Wobject::Gallery; use strict; use Class::C3; use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject); + use JSON; use Tie::IxHash; +use WebGUI::HTML; use WebGUI::International; +use WebGUI::Search; use WebGUI::Utility; use XML::Simple; -use WebGUI::HTML; + =head1 NAME @@ -29,6 +32,7 @@ use WebGUI::HTML; =head1 DIAGNOSTICS =head1 METHODS +=cut #------------------------------------------------------------------- @@ -391,7 +395,13 @@ sub appendTemplateVarsSearchForm { name => "keywords", value => $form->get("keywords"), }); - + + $var->{ searchForm_location } + = WebGUI::Form::text( $session, { + name => "location", + value => $form->get("location"), + }); + # Search classes tie my %searchClassOptions, 'Tie::IxHash', ( 'WebGUI::Asset::File::GalleryFile::Photo' => $i18n->get("search class photo"), @@ -766,6 +776,7 @@ Other keys are valid, see C for details. sub getSearchPaginator { my $self = shift; my $rules = shift; + my $session = $self->session; $rules->{ lineage } = [ $self->get("lineage") ]; @@ -1344,45 +1355,61 @@ sub www_listAlbumsService { return JSON->new->pretty->encode($document); } + #---------------------------------------------------------------------------- -=head2 www_search ( ) +=head2 search ( ) -Search through the GalleryAlbums and files in this gallery. Show the form to -search and display the results if necessary. +Helper method for C containing all the search logic. Executes a +search depending on search form parameters. Returns undef if no search was +executed. Otherwise an array is returned containing the following elements: + +=head3 paginator + +A paginator object containing the search results. + +=head3 keywords + +Search keywords assembled from search form fields. =cut -sub www_search { +sub search { my $self = shift; my $session = $self->session; my $form = $session->form; my $db = $session->db; + my $columns; - my $var = $self->getTemplateVars; - # NOTE: Search form is added as part of getTemplateVars() - - # Get search results, if necessary. + # Check whether we have to do a search my $doSearch = ( - $form->get( 'basicSearch' ) || $form->get( 'keywords' ) - || $form->get( 'title' ) || $form->get( 'description' ) - || $form->get( 'userId' ) || $form->get( 'className' ) - || $form->get( 'creationDate_after' ) || $form->get( 'creationDate_before' ) + $form->get( 'basicSearch' ) || $form->get( 'keywords' ) + || $form->get( 'location' ) || $form->get( 'title' ) + || $form->get( 'description' ) || $form->get( 'userId' ) + || $form->get( 'className' ) || $form->get( 'creationDate_after' ) + || $form->get( 'creationDate_before' ) ); - if ( $doSearch ) { - # Keywords to search on - # Do not add a space to the + if ( $doSearch ) { + # Keywords to search on. my $keywords; - FORMVAR: foreach my $formVar (qw/ basicSearch keywords title description /) { + FORMVAR: foreach my $formVar (qw/ basicSearch keywords location title description /) { my $var = $form->get($formVar); next FORMVAR unless $var; $keywords = join ' ', $keywords, $var; } + # Remove leading whitespace + $keywords =~ s/^\s+//; # Build a where clause from the advanced options # Lineage search can capture gallery + # Note that adding criteria to the where clause alone will not work. If + # you want to cover additional properties you need to make sure that + # - the property is added to $keywords above + # - the property is included in index keywords by overriding the indexContent method of respective classes (usually Photo or GalleryFile) + # - the respective table is joined in (usually via joinClass parameter of getSearchPaginator) + # - the column containing the property is included in the query (usually via column parameter of getSearchPaginator) my $where = q{assetIndex.assetId <> '} . $self->getId . q{'}; if ( $form->get("title") ) { $where .= q{ AND assetData.title LIKE } @@ -1394,11 +1421,18 @@ sub www_search { . $db->quote( '%' . $form->get("description") . '%' ) ; } + if ( $form->get("location") && ( $form->get("className") eq 'WebGUI::Asset::File::GalleryFile::Photo' + || $form->get("className") eq '' ) ) { + $where .= q{ AND Photo.location LIKE } + . $db->quote( '%' . $form->get("location") . '%' ) + ; + push (@{$columns}, 'Photo.location'); + } if ( $form->get("userId") ) { $where .= q{ AND assetData.ownerUserId = } . $db->quote( $form->get("userId") ) ; - } + } my $oneYearAgo = WebGUI::DateTime->new( $session, time )->add( years => -1 )->epoch; my $dateAfter = $form->get("creationDate_after", "dateTime", $oneYearAgo); @@ -1412,45 +1446,76 @@ sub www_search { } # Classes - my $joinClass = [ + my $classes = [ 'WebGUI::Asset::Wobject::GalleryAlbum', 'WebGUI::Asset::File::GalleryFile::Photo', ]; if ( $form->get("className") ) { - $joinClass = [ $form->get('className') ]; + $classes = [ $form->get('className') ]; } - $where .= q{ AND assetIndex.className IN ( } . $db->quoteAndJoin( $joinClass ) . q{ ) }; - # Build a URL for the pagination my $url = $self->getUrl( 'func=search;' . 'basicSearch=' . $form->get('basicSearch') . ';' . 'keywords=' . $form->get('keywords') . ';' + . 'location=' . $form->get('location') . ';' . 'title=' . $form->get('title') . ';' . 'description=' . $form->get('description') . ';' . 'creationDate_after=' . $dateAfter . ';' . 'creationDate_before=' . $dateBefore . ';' . 'userId=' . $form->get("userId") . ';' ); - for my $class ( @$joinClass ) { + for my $class ( @$classes ) { $url .= 'className=' . $class . ';'; } - - my $p + + my $paginator = $self->getSearchPaginator( { url => $url, keywords => $keywords, where => $where, - joinClass => $joinClass, + classes => $classes, + joinClass => $classes, + columns => $columns, creationDate => $creationDate, - } ); + } ); + return ( $paginator, $keywords ); + } + + # Return undef to indicate that no search was executed + return undef; +} + + +#---------------------------------------------------------------------------- + +=head2 www_search ( ) + +Search through the GalleryAlbums and files in this gallery. Show the form to +search and display the results if necessary. + +=cut + +sub www_search { + my $self = shift; + my $session = $self->session; + + my $var = $self->getTemplateVars; + # NOTE: Search form is added as part of getTemplateVars() + + # Execute search and retrieve search result paginator and keywords + my ( $paginator, $keywords ) = $self->search; + + if( $paginator ) { + # Provide search keywords as template variable $var->{ keywords } = $keywords; - $p->appendTemplateVars( $var ); - for my $result ( @{ $p->getPageData } ) { + # Add search results + $paginator->appendTemplateVars( $var ); + for my $result ( @{ $paginator->getPageData } ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $result->{assetId} ); push @{ $var->{search_results} }, { %{ $asset->getTemplateVars }, diff --git a/lib/WebGUI/Help/Asset_Gallery.pm b/lib/WebGUI/Help/Asset_Gallery.pm index 4ef482f1e..05287dcab 100644 --- a/lib/WebGUI/Help/Asset_Gallery.pm +++ b/lib/WebGUI/Help/Asset_Gallery.pm @@ -29,6 +29,10 @@ our $HELP = { name => 'searchForm_keywords', description => 'helpvar searchForm_keywords', }, + { + name => 'searchForm_location', + description => 'helpvar searchForm_location', + }, { name => 'searchForm_className', description => 'helpvar searchForm_className', diff --git a/lib/WebGUI/i18n/English/Asset_Gallery.pm b/lib/WebGUI/i18n/English/Asset_Gallery.pm index e9ea7b5ab..af78f44ce 100644 --- a/lib/WebGUI/i18n/English/Asset_Gallery.pm +++ b/lib/WebGUI/i18n/English/Asset_Gallery.pm @@ -419,6 +419,11 @@ our $I18N = { message => 'Search by keyword.', lastUpdated => 0, }, + + 'helpvar searchForm_location' => { + message => 'Search by location.', + lastUpdated => 0, + }, 'helpvar searchForm_className' => { message => 'Search by class name.', @@ -616,6 +621,12 @@ our $I18N = { lastUpdated => 0, context => "Label for the 'Keywords' input for the search form. 'Tags' is used because Keywords may be confused with the generic, all-inclusive search box.", }, + + 'template search field location' => { + message => "Location", + lastUpdated => 0, + context => "Label for the 'Location' input for the search form.", + }, 'template search field className' => { message => "Search Type", diff --git a/t/Asset/Wobject/Gallery/search.t b/t/Asset/Wobject/Gallery/search.t new file mode 100644 index 000000000..b17b0d7c1 --- /dev/null +++ b/t/Asset/Wobject/Gallery/search.t @@ -0,0 +1,318 @@ +#------------------------------------------------------------------- +# 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"; + +# Test of the Gallery basic and advanced search. In non-live tests, the Gallery +# search is accessed via the "search" method. Form parameters are passed in via +# the pseudo request object of the test session. + +use Test::More; +use Test::Deep; + +use WebGUI::Test; # Must use this before any other WebGUI modules +use WebGUI::Asset::Wobject::Gallery; +use WebGUI::Asset::Wobject::GalleryAlbum; +use WebGUI::Asset::File::GalleryFile::Photo; +use WebGUI::DateTime; +use WebGUI::Session; + + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode($session); +my $versionTag = WebGUI::VersionTag->getWorking($session); + +$versionTag->set( { name=>"Gallery Search Test" } ); +addToCleanup( $versionTag ); + +# Create gallery and a single album +my $gallery + = $node->addChild({ + className => "WebGUI::Asset::Wobject::Gallery", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); + +my $album + = $gallery->addChild({ + className => "WebGUI::Asset::Wobject::GalleryAlbum", + title => "album", + synopsis => "synopsis2", + keywords => "group2", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); +my $albumId = $album->getId; + +# Populate album with different photos +my $photo1 + = $album->addChild({ + className => "WebGUI::Asset::File::GalleryFile::Photo", + title => "photo1", + synopsis => "synopsis1", + keywords => "group1", + location => "Heidelberg", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); +my $id1 = $photo1->getId; + +my $photo2 + = $album->addChild({ + className => "WebGUI::Asset::File::GalleryFile::Photo", + title => "photo2", + synopsis => "synopsis2", + keywords => "group1", + location => "Mannheim", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); +my $id2 = $photo2->getId; + +my $photo3 + = $album->addChild({ + className => "WebGUI::Asset::File::GalleryFile::Photo", + title => "photo3", + synopsis => "synopsis1", + keywords => "group2", + location => "Mannheim", + }, + undef, + undef, + { + skipAutoCommitWorkflows => 1, + }); +my $id3 = $photo3->getId; + +# Commit all changes +$versionTag->commit; + +# Make gallery default asset +$session->asset( $gallery ); + +# Define some general variables +my $result; + + +#---------------------------------------------------------------------------- +# Tests +plan tests => 32; + +#---------------------------------------------------------------------------- +# Basic search + +note( "Basic gallery search" ); + +# Search by title + +my $hits = search( { basicSearch => "album" } ); +# Basic search will behave differently from advanced search. The album and all +# photos of the album will be returned, since the name of the album is added to +# index keywords of photos. +cmp_bag( $hits, [ $albumId, $id1, $id2, $id3 ], "Search for album entitled 'album' (basic search)" ); + +my $hits = search( { basicSearch => "photo1" } ); +cmp_bag( $hits, [ $id1 ], "Search for photo entitled 'photo1' (basic search)" ); + +my $hits = search( { title => "photo4" } ); +cmp_bag( $hits, [ ], "Search for non-existing photo entitled 'photo4' (basic search)" ); + +# Search by keywords + +my $hits = search( { basicSearch => "group1" } ); +cmp_bag( $hits, [ $id1, $id2 ], "Search for albums/photos with keywords 'group1' (basic search)" ); + +my $hits = search( { basicSearch => "group2" } ); +cmp_bag( $hits, [ $albumId, $id3 ], "Search for albums/photos with keywords 'group2' (basic search)" ); + +# Search by description + +my $hits = search( { basicSearch => "synopsis1" } ); +cmp_bag( $hits, [ $id1, $id3 ], "Search for albums/photos with synopsis 'synopsis1' (basic search)" ); + +my $hits = search( { basicSearch => "synopsis2" } ); +cmp_bag( $hits, [ $albumId, $id2 ], "Search for albums/photos with synopsis 'synopsis2' (basic search)" ); + + +# Warning: Tried to use 'here' and 'there' as locations for the following test. +# For unknown reasons the test failed. It seems that these and possibly other +# keywords are either filtered out by MySQL and/or are reserved words. Needs to +# be checked!!! + +my $hits = search( { basicSearch => "Mannheim" } ); +cmp_bag( $hits, [ $id2, $id3 ], "Search for photos taken at location 'Mannheim' (basic search)" ); + +my $hits = search( { basicSearch => "Heidelberg" } ); +cmp_bag( $hits, [ $id1 ], "Search for photos taken at location 'Heidelberg' (basic search)" ); + +# Search by multiple criteria + +my $hits = search({ basicSearch => "group1 synopsis1" }); +cmp_bag( $hits, [ $id1 ], "Search for photo with keywords 'group1' and synopsis 'synopsis1' (basic search)" ); + +my $hits = search({ basicSearch => "group2 Mannheim" }); +cmp_bag( $hits, [ $id3 ], "Search for photo with keywords 'group2' and location 'Mannheim' (basic search)" ); + +my $hits = search({ basicSearch => "synopsis1 Mannheim" }); +cmp_bag( $hits, [ $id3 ], "Search for photo with synopsis 'synopsis1' and location 'Mannheim' (basic search)" ); + + +#---------------------------------------------------------------------------- +# Advanced search + +note( "Advanced gallery search" ); + +my $hits = search( { } ); +cmp_bag( $hits, [ ], "Empty search (advanced search)" ); + +# Search by class + +my $hits = search( { className => "WebGUI::Asset::File::GalleryFile::Photo" } ); +cmp_bag( $hits, [ $id1, $id2, $id3 ], "Search for all photos (advanced search)" ); + +my $hits = search( { className => "WebGUI::Asset::Wobject::GalleryAlbum" } ); +cmp_bag( $hits, [ $albumId ], "Search for all albums (advanced search)" ); + +# Search by date + +my $oneYearAgo = WebGUI::DateTime->new( $session, time )->add( years => -1 )->epoch; +my $hits + = search({ + creationDate_after => $oneYearAgo, + creationDate_before => time(), + }); +cmp_bag( $hits, [ $albumId, $id1, $id2, $id3 ], "Search by date, all included (advanced search)" ); + +my $hits + = search({ + creationDate_after => time() + 1, + creationDate_before => time() + 1, + }); +cmp_bag( $hits, [ ], "Search by date, all excluded (advanced search)" ); + +# Search by title + +my $hits = search( { title => "album" } ); +cmp_bag( $hits, [ $albumId ], "Search for album entitled 'album' (advanced search)" ); + +my $hits = search( { title => "photo1" } ); +cmp_bag( $hits, [ $id1 ], "Search for photo entitled 'photo1' (advanced search)" ); + +my $hits = search( { title => "photo4" } ); +cmp_bag( $hits, [ ], "Search for non-existing photo entitled 'photo4' (advanced search)" ); + +# Search by keywords + +my $hits = search( { keywords => "group1" } ); +cmp_bag( $hits, [ $id1, $id2 ], "Search for albums/photos with keywords 'group1' (advanced search)" ); + +my $hits = search( { keywords => "group2" } ); +cmp_bag( $hits, [ $albumId, $id3 ], "Search for albums/photos with keywords 'group2' (advanced search)" ); + +my $hits = search( { keywords => "group3" } ); +cmp_bag( $hits, [ ], "Search for non-existing albums/photos with keywords 'group3' (advanced search)" ); + +# Search by description + +my $hits = search( { description => "synopsis1" } ); +cmp_bag( $hits, [ $id1, $id3 ], "Search for albums/photos with synopsis 'synopsis1' (advanced search)" ); + +my $hits = search( { description => "synopsis2" } ); +cmp_bag( $hits, [ $albumId, $id2 ], "Search for albums/photos with synopsis 'synopsis2' (advanced search)" ); + +my $hits = search( { description => "synopsis3" } ); +cmp_bag( $hits, [ ], "Search for non-existing albums/photos with synopsis 'synopsis3' (advanced search)" ); + +# Search by location +# Warning: Tried to use 'here' and 'there' as locations for the following test. +# For unknown reasons the test failed. It seems that these and possibly other +# keywords are either filtered out by MySQL and/or are reserved words. Needs to +# be checked!!! + +my $hits = search( { location => "Mannheim" } ); +cmp_bag( $hits, [ $id2, $id3 ], "Search for photos taken at location 'Mannheim' (advanced search)" ); + +my $hits = search( { location => "Heidelberg" } ); +cmp_bag( $hits, [ $id1 ], "Search for photos taken at location 'Heidelberg' (advanced search)" ); + +my $hits = search( { location => "Frankfurt" } ); +cmp_bag( $hits, [ ], "Search for non-existing photos taken at location 'Frankfurt' (advanced search)" ); + +# Search by multiple criteria + +my $hits + = search({ + keywords => "group1", + description => "synopsis1", + }); +cmp_bag( $hits, [ $id1 ], "Search for photo with keywords 'group1' and synopsis 'synopsis1' (advanced search)" ); + +my $hits + = search({ + keywords => "group2", + location => "Mannheim", + }); +cmp_bag( $hits, [ $id3 ], "Search for photo with keywords 'group2' and location 'Mannheim' (advanced search)" ); + +my $hits + = search({ + description => "synopsis1", + location => "Mannheim", + }); +cmp_bag( $hits, [ $id3 ], "Search for photo with synopsis 'synopsis1' and location 'Mannheim' (advanced search)" ); + + +#---------------------------------------------------------------------------- +# search( formParams ) +# Execute a search for photos and albums in the test gallery. +# +# Accepts a hash ref as single parameter. All key/value pairs in the hash are +# added as form parameters to the pseudo request object before the search is +# executed. See the Gallery search method for valid form fields. +# +# Returns a reference pointing an array containg the asset Ids of all hits. + +sub search { + my $formParams = shift; + my $hits = []; + + # Setup the mock request object + $session->request->method( 'GET' ); + $session->request->setup_param( $formParams ); + + # Call gallery search function + my ( $paginator, $keywords ) = $gallery->search; + # Return ref to empty array if search could not be executed + return $hits unless $paginator; + + # Extract asset Ids from search results and compile array. + for ( my $i = 1; $i <= $paginator->getNumberOfPages; $i++ ) { + for my $result ( @{ $paginator->getPageData( $i ) } ) { + push @{ $hits }, $result->{ assetId }; + } + } + return $hits; +}