webgui/lib/WebGUI/Asset/Wobject/Gallery.pm
2010-06-14 11:30:36 -07:00

1629 lines
54 KiB
Perl

package WebGUI::Asset::Wobject::Gallery;
#-------------------------------------------------------------------
# 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 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;
=head1 NAME
=head1 DESCRIPTION
=head1 SYNOPSIS
=head1 DIAGNOSTICS
=head1 METHODS
=cut
#-------------------------------------------------------------------
=head2 definition ( )
=cut
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session, 'Asset_Gallery');
tie my %imageResolutionOptions, 'Tie::IxHash', (
'640' => '640',
'800' => '800',
'1024' => '1024',
'1260' => '1260',
'1440' => '1440',
'1600' => '1600',
'2880' => '2880',
);
tie my %viewDefaultOptions, 'Tie::IxHash', (
list => $i18n->get("viewDefault option list"),
album => $i18n->get("viewDefault option album"),
);
tie my %viewListOrderByOptions, 'Tie::IxHash', (
creationDate => $i18n->get("viewListOrderBy option creationDate"),
lineage => $i18n->get("viewListOrderBy option lineage"),
revisionDate => $i18n->get("viewListOrderBy option revisionDate"),
title => $i18n->get("viewListOrderBy option title"),
);
tie my %viewListOrderDirectionOptions, 'Tie::IxHash', (
ASC => $i18n->get("viewListOrderDirection option asc"),
DESC => $i18n->get("viewListOrderDirection option desc"),
);
tie my %imageDensityOptions, 'Tie::IxHash', (
72 => $i18n->get( "imageDensity option web" ),
300 => $i18n->get( "imageDensity option print" ),
);
tie my %properties, 'Tie::IxHash', (
groupIdAddComment => {
tab => "security",
fieldType => "group",
defaultValue => 2, # Registered Users
label => $i18n->get("groupIdAddComment label"),
hoverHelp => $i18n->get("groupIdAddComment description"),
},
groupIdAddFile => {
tab => "security",
fieldType => "group",
defaultValue => 2, # Registered Users
label => $i18n->get("groupIdAddFile label"),
hoverHelp => $i18n->get("groupIdAddFile description"),
},
imageResolutions => {
tab => "properties",
fieldType => "checkList",
defaultValue => join("\n", '800', '1024', '1200', '1600', '2880'),
options => \%imageResolutionOptions,
label => $i18n->get("imageResolutions label"),
hoverHelp => $i18n->get("imageResolutions description"),
},
imageViewSize => {
tab => "properties",
fieldType => "integer",
defaultValue => 700,
label => $i18n->get("imageViewSize label"),
hoverHelp => $i18n->get("imageViewSize description"),
},
imageThumbnailSize => {
tab => "properties",
fieldType => "integer",
defaultValue => 300,
label => $i18n->get("imageThumbnailSize label"),
hoverHelp => $i18n->get("imageThumbnailSize description"),
},
imageDensity => {
tab => "properties",
fieldType => "selectBox",
options => \%imageDensityOptions,
defaultValue => 72,
label => $i18n->get( "imageDensity label" ),
hoverHelp => $i18n->get( "imageDensity description" ),
},
maxSpacePerUser => {
tab => "properties",
fieldType => "integer",
defaultValue => 0,
label => $i18n->get("maxSpacePerUser label"),
hoverHelp => $i18n->get("maxSpacePerUser description"),
},
richEditIdAlbum => {
tab => "properties",
fieldType => "selectRichEditor",
defaultValue => "PBrichedit000000000001", # Content Managers editor
label => $i18n->get("richEditIdAlbum label"),
hoverHelp => $i18n->get("richEditIdAlbum description"),
},
richEditIdFile => {
tab => "properties",
fieldType => "selectRichEditor",
defaultValue => "PBrichedit000000000002", # Forum Rich editor
label => $i18n->get("richEditIdFile label"),
hoverHelp => $i18n->get("richEditIdFile description"),
},
richEditIdComment => {
tab => "properties",
fieldType => "selectRichEditor",
defaultValue => "PBrichedit000000000002", # Forum Rich Editor
label => $i18n->get("richEditIdFileComment label"),
hoverHelp => $i18n->get("richEditIdFileComment description"),
},
templateIdAddArchive => {
tab => "display",
fieldType => "template",
defaultValue => "i0X4Q3tBWUb_thsVbsYz9xQ",
namespace => "GalleryAlbum/AddArchive",
label => $i18n->get("templateIdAddArchive label"),
hoverHelp => $i18n->get("templateIdAddArchive description"),
},
templateIdDeleteAlbum => {
tab => "display",
fieldType => "template",
defaultValue => "UTNFeV7B_aSCRmmaFCq4Vw",
namespace => "GalleryAlbum/Delete",
label => $i18n->get("templateIdDeleteAlbum label"),
hoverHelp => $i18n->get("templateIdDeleteAlbum description"),
},
templateIdDeleteFile => {
tab => "display",
fieldType => "template",
defaultValue => "zcX-wIUct0S_np14xxOA-A",
namespace => "GalleryFile/Delete",
label => $i18n->get("templateIdDeleteFile label"),
hoverHelp => $i18n->get("templateIdDeleteFile description"),
},
templateIdEditAlbum => {
tab => "display",
fieldType => "template",
defaultValue => "6X-7Twabn5KKO_AbgK3PEw",
namespace => "GalleryAlbum/Edit",
label => $i18n->get("templateIdEditAlbum label"),
hoverHelp => $i18n->get("templateIdEditAlbum description"),
},
templateIdEditComment => {
tab => "display",
fieldType => "template",
defaultValue => "OxJWQgnGsgyGohP2L3zJPQ",
namespace => "GalleryFile/EditComment",
label => $i18n->get("templateIdEditComment label"),
hoverHelp => $i18n->get("templateIdEditComment description"),
},
templateIdEditFile => {
tab => "display",
fieldType => "template",
defaultValue => "7JCTAiu1U_bT9ldr655Blw",
namespace => "GalleryFile/Edit",
label => $i18n->get("templateIdEditFile label"),
hoverHelp => $i18n->get("templateIdEditFile description"),
},
templateIdListAlbums => {
tab => "display",
fieldType => "template",
defaultValue => "azCqD0IjdQSlM3ar29k5Sg",
namespace => "Gallery/ListAlbums",
label => $i18n->get("templateIdListAlbums label"),
hoverHelp => $i18n->get("templateIdListAlbums description"),
},
templateIdListAlbumsRss => {
tab => "display",
fieldType => "template",
defaultValue => "ilu5BrM-VGaOsec9Lm7M6Q",
namespace => "Gallery/ListAlbumsRss",
label => $i18n->get("templateIdListAlbumsRss label"),
hoverHelp => $i18n->get("templateIdListAlbumsRss description"),
},
templateIdListFilesForUser => {
tab => "display",
fieldType => "template",
defaultValue => "OkphOEdaSGTXnFGhK4GT5A",
namespace => "Gallery/ListFilesForUser",
label => $i18n->get("templateIdListFilesForUser label"),
hoverHelp => $i18n->get("templateIdListFilesForUser description"),
},
templateIdListFilesForUserRss => {
tab => "display",
fieldType => "template",
defaultValue => "-ANLpoTEP-n4POAdRxCzRw",
namespace => "Gallery/ListFilesForUserRss",
label => $i18n->get("templateIdListFilesForUserRss label"),
hoverHelp => $i18n->get("templateIdListFilesForUserRss description"),
},
templateIdMakeShortcut => {
tab => "display",
fieldType => "template",
defaultValue => "m3IbBavqzuKDd2PGGhKPlA",
namespace => "GalleryFile/MakeShortcut",
label => $i18n->get("templateIdMakeShortcut label"),
hoverHelp => $i18n->get("templateIdMakeShortcut description"),
},
templateIdSearch => {
tab => "display",
fieldType => "template",
defaultValue => "jME5BEDYVDlBZ8jIQA9-jQ",
namespace => "Gallery/Search",
label => $i18n->get("templateIdSearch label"),
hoverHelp => $i18n->get("templateIdSearch description"),
},
templateIdViewSlideshow => {
tab => "display",
fieldType => "template",
defaultValue => "KAMdiUdJykjN02CPHpyZOw",
namespace => "GalleryAlbum/ViewSlideshow",
label => $i18n->get("templateIdViewSlideshow label"),
hoverHelp => $i18n->get("templateIdViewSlideshow description"),
},
templateIdViewThumbnails => {
tab => "display",
fieldType => "template",
defaultValue => "q5O62aH4pjUXsrQR3Pq4lw",
namespace => "GalleryAlbum/ViewThumbnails",
label => $i18n->get("templateIdViewThumbnails label"),
hoverHelp => $i18n->get("templateIdViewThumbnails description"),
},
templateIdViewAlbum => {
tab => "display",
fieldType => "template",
defaultValue => "05FpjceLYhq4csF1Kww1KQ",
namespace => "GalleryAlbum/View",
label => $i18n->get("templateIdViewAlbum label"),
hoverHelp => $i18n->get("templateIdViewAlbum description"),
},
templateIdViewAlbumRss => {
tab => "display",
fieldType => "template",
defaultValue => "mM3bjP_iG9sv5nQb4S17tQ",
namespace => "GalleryAlbum/ViewRss",
label => $i18n->get("templateIdViewAlbumRss label"),
hoverHelp => $i18n->get("templateIdViewAlbumRss description"),
},
templateIdViewFile => {
tab => "display",
fieldType => "template",
defaultValue => "TEId5V-jEvUULsZA0wuRuA",
namespace => "GalleryFile/View",
label => $i18n->get("templateIdViewFile label"),
hoverHelp => $i18n->get("templateIdViewFile description"),
},
viewDefault => {
tab => "display",
fieldType => "selectBox",
defaultValue => "list",
options => \%viewDefaultOptions,
label => $i18n->get("viewDefault label"),
hoverHelp => $i18n->get("viewDefault description"),
},
viewAlbumAssetId => {
tab => "display",
fieldType => "asset",
class => "WebGUI::Asset::Wobject::GalleryAlbum",
label => $i18n->get("viewAlbumAssetId label"),
hoverHelp => $i18n->get("viewAlbumAssetId description"),
},
viewListOrderBy => {
tab => "display",
fieldType => "selectBox",
defaultValue => "lineage", # "Sequence Number"
options => \%viewListOrderByOptions,
label => $i18n->get("viewListOrderBy label"),
hoverHelp => $i18n->get("viewListOrderBy description"),
},
viewListOrderDirection => {
tab => "display",
fieldType => "selectBox",
defaultValue => "ASC",
options => \%viewListOrderDirectionOptions,
label => $i18n->get("viewListOrderDirection label"),
hoverHelp => $i18n->get("viewListOrderDirection description"),
},
workflowIdCommit => {
tab => "security",
fieldType => "workflow",
defaultValue => "pbworkflow000000000003", # Commit without approval
type => 'WebGUI::VersionTag',
label => $i18n->get("workflowIdCommit label"),
hoverHelp => $i18n->get("workflowIdCommit description"),
},
defaultFilesPerPage => {
tab => 'display',
fieldType => 'integer',
defaultValue => 24,
label => $i18n->get( 'defaultFilesPerPage label' ),
hoverHelp => $i18n->get( 'defaultFilesPerPage description' ),
},
);
push @{$definition}, {
assetName => $i18n->get('assetName'),
icon => 'photoGallery.gif',
autoGenerateForms => 1,
tableName => 'Gallery',
className => __PACKAGE__,
properties => \%properties,
};
return $class->next::method($session, $definition);
}
#----------------------------------------------------------------------------
=head2 appendTemplateVarsSearchForm ( var )
Appends the template vars for the search form to the hash reference C<var>.
Returns the hash reference for convenience.
=cut
sub appendTemplateVarsSearchForm {
my $self = shift;
my $var = shift;
my $session = $self->session;
my $form = $self->session->form;
my $i18n = WebGUI::International->new($session, 'Asset_Gallery');
$var->{ searchForm_start }
= WebGUI::Form::formHeader( $session, {
action => $self->getUrl('func=search'),
method => "GET",
});
$var->{ searchForm_end }
= WebGUI::Form::formFooter( $session );
$var->{ searchForm_basicSearch }
= WebGUI::Form::text( $session, {
name => "basicSearch",
value => $form->get("basicSearch"),
});
$var->{ searchForm_title }
= WebGUI::Form::text( $session, {
name => "title",
value => $form->get("title"),
});
$var->{ searchForm_description }
= WebGUI::Form::text( $session, {
name => "description",
value => $form->get("description"),
});
$var->{ searchForm_keywords }
= WebGUI::Form::text( $session, {
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"),
'WebGUI::Asset::Wobject::GalleryAlbum' => $i18n->get("search class galleryalbum"),
'' => $i18n->get("search class any"),
);
$var->{ searchForm_className }
= WebGUI::Form::radioList( $session, {
name => "className",
value => ( $form->get("className") || '' ),
options => \%searchClassOptions,
});
# Search creationDate
my $oneYearAgo = WebGUI::DateTime->new( $session, time )->add( years => -1 )->epoch;
$var->{ searchForm_creationDate_after }
= WebGUI::Form::dateTime( $session, {
name => "creationDate_after",
value => $form->get("creationDate_after", "dateTime", $oneYearAgo),
});
$var->{ searchForm_creationDate_before }
= WebGUI::Form::dateTime( $session, {
name => "creationDate_before",
value => $form->get("creationDate_before", "dateTime", time()),
});
# Buttons
$var->{ searchForm_submit }
= WebGUI::Form::submit( $session, {
name => "submit",
value => $i18n->get("search submit"),
});
return $var;
}
#----------------------------------------------------------------------------
=head2 canAddFile ( [userId] )
Returns true if the user can add files to this Gallery. C<userId> is the
userId to check. If no userId is passed, will check the current user.
Users can add files to this gallery if they are part of the C<groupIdAddFile>
=cut
sub canAddFile {
my $self = shift;
my $userId = shift;
my $user = $userId
? WebGUI::User->new( $self->session, $userId )
: $self->session->user
;
return $user->isInGroup( $self->get("groupIdAddFile") );
}
#----------------------------------------------------------------------------
=head2 canComment ( [userId] )
Returns true if the user can comment on this Gallery. C<userId> is the userId
to check. If no userId is passed, will check the current user.
Users can comment on this gallery if they are part of the
C<groupIdAddComment> group.
=cut
sub canComment {
my $self = shift;
my $userId = shift;
my $user = $userId
? WebGUI::User->new( $self->session, $userId )
: $self->session->user
;
return $user->isInGroup( $self->get("groupIdAddComment") );
}
#----------------------------------------------------------------------------
=head2 canEdit ( [userId] )
Returns true if the user can edit this Gallery. C<userId> is the userId to
check. If no userId is passed, will check the current user.
Users can edit this gallery if they are part of the C<groupIdEdit> group.
Also checks if a user is adding a GalleryAlbum and allows them to if they are
part of the C<groupIdAddFile> group.
=cut
sub canEdit {
my $self = shift;
my $userId = shift;
my $form = $self->session->form;
if ( $form->get('func') eq "add" && $form->get( 'class' )->isa( "WebGUI::Asset::Wobject::GalleryAlbum" ) ) {
return $self->canAddFile( $userId );
}
elsif ( $form->get('func') eq "editSave" && $form->get('assetId') eq "new" && $form->get( 'class' )->isa( 'WebGUI::Asset::Wobject::GalleryAlbum' ) ) {
return $self->canAddFile( $userId );
}
else {
my $user = $userId
? WebGUI::User->new( $self->session, $userId )
: $self->session->user
;
return $user->isInGroup( $self->get("groupIdEdit") );
}
}
#----------------------------------------------------------------------------
=head2 canView ( [userId] )
Returns true if the user can view this Gallery. C<userId> is the userId to
check. If no userId is passed, will check the current user.
Users can view this gallery if they are part of the C<groupIdView> group.
=cut
sub canView {
my $self = shift;
my $userId = shift;
my $user = $userId
? WebGUI::User->new( $self->session, $userId )
: $self->session->user
;
return $user->isInGroup( $self->get("groupIdView") );
}
#----------------------------------------------------------------------------
=head2 getAlbumIds ( options )
Gets an array reference of all the album IDs under this Gallery. C<options>
is a hash reference with the following keys.
orderBy => An SQL ORDER BY clause to sort the albums.
By default, uses the viewListOrderBy and viewListOrderDirection keys from
the asset properties.
=cut
sub getAlbumIds {
my $self = shift;
my $options = shift;
my $orderBy = $options->{ orderBy }
? $options->{ orderBy }
: $self->get( 'viewListOrderBy' )
? join( " ", $self->get( 'viewListOrderBy' ), $self->get( 'viewListOrderDirection' ) )
: "lineage ASC"
;
# Deal with "pending" albums.
my %pendingRules;
if ( $self->canEdit ) {
$pendingRules{ statusToInclude } = [ 'pending', 'approved' ];
}
else {
$pendingRules{ statusToInclude } = [ 'pending', 'approved' ];
$pendingRules{ whereClause } = q{
(
status = "approved" || ownerUserId = "} . $self->session->user->userId . q{"
)
};
}
my $assets
= $self->getLineage(['descendants'], {
includeOnlyClasses => ['WebGUI::Asset::Wobject::GalleryAlbum'],
orderByClause => $orderBy,
( %pendingRules ),
});
return $assets;
}
#----------------------------------------------------------------------------
=head2 getAlbumPaginator ( options )
Gets a WebGUI::Paginator for all the albums in this Gallery. C<options> is a
hash reference with the following keys.
perpage => The number of results to show per page. Default: 20
For more C<options>, see L</getAlbumIds>.
=cut
sub getAlbumPaginator {
my $self = shift;
my $options = shift;
my $perpage = $options->{ perpage } || 20;
delete $options->{ perpage };
my $p
= WebGUI::Paginator->new( $self->session, $self->getUrl, $perpage );
$p->setDataByArrayRef( $self->getAlbumIds( $options ) );
return $p;
}
#----------------------------------------------------------------------------
=head2 getAssetClassForFile ( filepath )
Gets the WebGUI Asset class for the file at the given C<filepath>. Returns
undef if the file cannot be saved under this Gallery.
=cut
sub getAssetClassForFile {
my $self = shift;
my $filepath = shift;
$self->session->log->info( "Checking asset class for file '$filepath'" );
# Checks for Photo assets
if ( $filepath =~ /\.(jpe?g|gif|png)$/i ) {
return "WebGUI::Asset::File::GalleryFile::Photo";
}
# No class found
return undef;
}
#----------------------------------------------------------------------------
=head2 getGalleryFileClassesAvailable ( )
Returns an array reference of the Asset classes available to be added to this
Gallery.
=cut
sub getGalleryFileClassesAvailable {
my $self = shift;
return [ 'WebGUI::Asset::File::GalleryFile::Photo' ];
}
#----------------------------------------------------------------------------
=head2 getImageResolutions ( )
Gets an array reference of the image resolutions to create for image-type
assets in this gallery.
=cut
sub getImageResolutions {
my $self = shift;
return [ split /\n/, $self->get("imageResolutions") ];
}
#----------------------------------------------------------------------------
=head2 getNextAlbumId ( albumId )
Gets the next albumId from the list of albumIds. C<albumId> is the base
albumId we want to find the next album for.
Returns C<undef> if there is no next albumId.
=cut
sub getNextAlbumId {
my $self = shift;
my $albumId = shift;
my $allAlbumIds = $self->getAlbumIds;
while ( my $checkId = shift @{ $allAlbumIds } ) {
# If this is the last albumId
return undef unless @{ $allAlbumIds };
if ( $albumId eq $checkId ) {
return shift @{ $allAlbumIds };
}
}
}
#----------------------------------------------------------------------------
=head2 getPreviousAlbumId ( albumId )
Gets the previous albumId from the list of albumIds. C<albumId> is the base
albumId we want to find the previous album for.
Returns C<undef> if there is no previous albumId.
=cut
sub getPreviousAlbumId {
my $self = shift;
my $albumId = shift;
my $allAlbumIds = $self->getAlbumIds;
while ( my $checkId = pop @{ $allAlbumIds } ) {
# If this is the last albumId
return undef unless @{ $allAlbumIds };
if ( $albumId eq $checkId ) {
return pop @{ $allAlbumIds };
}
}
}
#-------------------------------------------------------------------
=head2 getRssFeedItems ()
Returns an array reference of hash references. Each hash reference has a title,
description, link, and date field. The date field can be either an epoch date, an RFC 1123
date, or a ISO date in the format of YYYY-MM-DD HH:MM::SS. Optionally specify an
author, and a guid field.
=cut
sub getRssFeedItems {
my $self = shift;
my $p
= $self->getAlbumPaginator( {
perpage => $self->get('itemsPerFeed'),
} );
my $var = [];
my $siteUrl = $self->session->url->getSiteURL();
for my $assetId ( @{ $p->getPageData } ) {
my $asset = WebGUI::Asset::Wobject::GalleryAlbum->newPending( $self->session, $assetId );
push @{ $var }, {
'link' => $siteUrl . $asset->getUrl,
'guid' => $asset->{_properties}->{ 'assetId' },
'title' => $asset->getTitle,
'description' => $asset->{_properties}->{ 'description' },
'date' => $asset->{_properties}->{ 'creationDate' },
'author' => WebGUI::User->new($self->session, $asset->{_properties}->{ 'ownerUserId' })->username
};
}
return $var;
}
#----------------------------------------------------------------------------
=head2 getSearchPaginator ( rules )
Gets a WebGUI::Paginator for a search. C<rules> is a hash reference of
options with the following keys:
keywords => Keywords to search on
Other keys are valid, see C<WebGUI::Search::search()> for details.
=cut
sub getSearchPaginator {
my $self = shift;
my $rules = shift;
my $session = $self->session;
$rules->{ lineage } = [ $self->get("lineage") ];
my $search = WebGUI::Search->new( $self->session );
$search->search( $rules );
my $paginator = $search->getPaginatorResultSet( $rules->{url} );
return $paginator;
}
#----------------------------------------------------------------------------
=head2 getTemplateIdEditFile ( )
Returns the ID for the template to edit a file.
NOTE: This may need to change in the future to take into account different
classes of files inside of a Gallery.
=cut
sub getTemplateIdEditFile {
my $self = shift;
return $self->get("templateIdEditFile");
}
#----------------------------------------------------------------------------
=head2 getTemplateVars ( )
Gets a hash reference of vars common to all templates.
=cut
sub getTemplateVars {
my $self = shift;
my $var = $self->get;
# Add the search form variables
$self->appendTemplateVarsSearchForm( $var );
$var->{ url } = $self->getUrl;
$var->{ url_addAlbum } = $self->getUrl('func=add;class=WebGUI::Asset::Wobject::GalleryAlbum');
$var->{ url_listAlbums } = $self->getUrl('func=listAlbums');
$var->{ url_listAlbumsRss } = $self->getUrl('func=listAlbumsRss');
$var->{ url_listFilesForCurrentUser } = $self->getUrl('func=listFilesForUser');
$var->{ url_search } = $self->getUrl('func=search');
$var->{ canEdit } = $self->canEdit;
$var->{ canAddFile } = $self->canAddFile;
return $var;
}
#----------------------------------------------------------------------------
=head2 getUserAlbumIds ( [userId] )
Gets an array reference of assetIds for the GalleryAlbums in this Gallery
owned by the specified C<userId>. If userId is not defined, will use the
current user.
=cut
sub getUserAlbumIds {
my $self = shift;
my $userId = shift || $self->session->user->userId;
my $db = $self->session->db;
my $assetIds
= $self->getLineage( ['descendants'], {
includeOnlyClasses => [ 'WebGUI::Asset::Wobject::GalleryAlbum' ],
whereClause => "ownerUserId = " . $db->quote($userId),
});
return $assetIds;
}
#----------------------------------------------------------------------------
=head2 getUserFileIds ( [userId] )
Gets an array reference of assetIds for the files in this Gallery owned by
the specified C<userId>. If userId is not defined, will use the current user.
=cut
sub getUserFileIds {
my $self = shift;
my $userId = shift || $self->session->user->userId;
my $db = $self->session->db;
# Note: We use excludeClasses to avoid getting GalleryAlbum assets
my $assetIds
= $self->getLineage( ['descendants'], {
excludeClasses => [ 'WebGUI::Asset::Wobject::GalleryAlbum' ],
whereClause => "ownerUserId = " . $db->quote($userId),
});
return $assetIds;
}
#----------------------------------------------------------------------------
=head2 getUserFilePaginator ( options )
Gets a WebGUI::Paginator for the files owned by a specific C<userId>.
C<options> is a hash reference of options with the following keys:
userId => The user who owns the asset. Defaults to the current user.
url => The URL to give to the paginator
=cut
sub getUserFilePaginator {
my $self = shift;
my $options = shift;
my $userId = delete $options->{userId};
my $url = delete $options->{url};
my $p = WebGUI::Paginator->new( $self->session, $url );
$p->setDataByArrayRef( $self->getUserFileIds( $userId ) );
return $p;
}
#----------------------------------------------------------------------------
=head2 hasSpaceAvailable ( spaceWanted [, userId ] )
Returns true if the user has at least the specified bytes of C<spaceWanted>
available to use in this Gallery.
=cut
sub hasSpaceAvailable {
my $self = shift;
my $spaceWanted = shift;
my $userId = shift || $self->session->user->userId;
# If we don't care, just return
return 1 if ( $self->get( "maxSpacePerUser" ) == 0 );
my $db = $self->session->db;
# Compile the amount of disk space used
my $maxSpace = $self->get( "maxSpacePerUser" ) * ( 1_024 ** 2 ); # maxSpacePerUser is in MB
my $spaceUsed = 0;
my $fileIter
= $self->getLineageIterator( [ 'descendants' ], {
joinClass => 'WebGUI::Asset::File::GalleryFile',
whereClause => 'ownerUserId = ' . $db->quote( $userId ),
} );
while ( 1 ) {
my $file;
eval { $file = $fileIter->() };
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
$self->session->log->error($x->full_message);
next;
}
last unless $file;
$spaceUsed += $file->get( 'assetSize' );
return 0 if ( $spaceUsed + $spaceWanted >= $maxSpace );
}
# We must have enough space
return 1;
}
#----------------------------------------------------------------------------
=head2 prepareView ( )
See WebGUI::Asset::prepareView() for details.
=cut
sub prepareView {
my $self = shift;
$self->next::method();
if ( $self->get("viewDefault") eq "album" && $self->get("viewAlbumAssetId") && $self->get("viewAlbumAssetId")
ne 'PBasset000000000000001') {
my $asset
= WebGUI::Asset->newByDynamicClass( $self->session, $self->get("viewAlbumAssetId") );
if ($asset) {
$asset->prepareView;
$self->{_viewAsset} = $asset;
}
else {
$self->prepareViewListAlbums;
}
}
else {
$self->prepareViewListAlbums;
}
}
#----------------------------------------------------------------------------
=head2 prepareViewListAlbums ( )
Prepare the template for listing multiple albums.
=cut
sub prepareViewListAlbums {
my $self = shift;
my $template
= WebGUI::Asset::Template->new($self->session, $self->get("templateIdListAlbums"));
if (!$template) {
WebGUI::Error::ObjectNotFound::Template->throw(
error => qq{Template not found},
templateId => $self->get("templateIdListAlbums"),
assetId => $self->getId,
);
}
$template->prepare($self->getMetaDataAsTemplateVariables);
$self->{_viewTemplate} = $template;
}
#----------------------------------------------------------------------------
=head2 view ( )
Show the default view based on the Gallery settings.
=cut
sub view {
my $self = shift;
my $session = $self->session;
my $var = $self->get;
if ( $self->get("viewDefault") eq "album" && $self->{_viewAsset}) {
return $self->{_viewAsset}->view;
}
else {
return $self->view_listAlbums;
}
}
#----------------------------------------------------------------------------
=head2 view_listAlbums ( )
Show a paginated list of the albums in this gallery. This method does the
actual work.
=cut
sub view_listAlbums {
my $self = shift;
my $session = $self->session;
my $var = $self->getTemplateVars;
my $form = $self->session->form;
my $p
= $self->getAlbumPaginator( {
perpage => ( $form->get('perpage') || 20 ),
} );
$p->appendTemplateVars( $var );
for my $assetId ( @{ $p->getPageData } ) {
my $asset = WebGUI::Asset::Wobject::GalleryAlbum->newPending( $session, $assetId );
push @{ $var->{albums} }, $asset->getTemplateVars;
}
return $self->processTemplate( $var, undef, $self->{_viewTemplate} );
}
#----------------------------------------------------------------------------
=head2 www_add ( )
Add a GalleryAlbum to this Gallery. Overridden here to show an error message
if the Gallery is not committed.
If a GalleryAlbum is added to an uncommitted Gallery, and the GalleryAlbum
is committed before the Gallery, problems start happening.
TODO: This could be handled better by the requestAutoCommit subroutine
instead of having to block things from being added.
=cut
sub www_add {
my $self = shift;
unless ( $self->hasBeenCommitted ) {
my $i18n = WebGUI::International->new($self->session, 'Asset_Gallery');
return $self->processStyle($i18n->get("error add uncommitted"));
}
return $self->next::method( @_ );
}
#----------------------------------------------------------------------------
=head2 www_addAlbumService ( )
A web service to create albums. Returns a json string that looks like this:
{
"lastUpdated" : "2008-10-13 17:31:32",
"canAddFiles" : 1,
"url" : "http://dev.localhost.localdomain/cool-gallery/the-cool-album2",
"title" : "The Cool Album",
"dateCreated" : "2008-10-13 17:31:32"
}
You can make the request as a post to the gallery url with the following variables:
=head3 func
Required. Must have a value of "addAlbumService"
=head3 as
Defaults to 'json', but if specified as 'xml' then the return result will be:
<opt>
<canAddFiles>1</canAddFiles>
<dateCreated>2008-10-13 17:39:22</dateCreated>
<lastUpdated>2008-10-13 17:39:22</lastUpdated>
<title>The Cool Album</title>
<url>http://dev.localhost.localdomain/cool-gallery/the-cool-album3</url>
</opt>
=head3 title
The title of the album you wish to create.
=head3 synopsis
A brief description of the album you wish to create.
=head3 othersCanAdd
A 1 or a 0 depending on whether you want other people to be able to add images to this album.
=cut
sub www_addAlbumService {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient unless ($self->canAddFile);
my $form = $session->form;
my $album = $self->addChild({
className => "WebGUI::Asset::Wobject::GalleryAlbum",
title => $form->get('title','text'),
description => $form->get('synopsis','textarea'),
synopsis => $form->get('synopsis','textarea'),
othersCanAdd => $form->get('othersCanAdd','yesNo'),
ownerUserId => $session->user->userId,
});
$album->requestAutoCommit;
my $siteUrl = $session->url->getSiteURL;
my $date = $session->datetime;
my $as = $form->get('as') || 'json';
my $document = {
canAddFiles => $album->canAddFile,
title => $album->getTitle,
url => $siteUrl.$album->getUrl,
dateCreated => $date->epochToHuman($album->get('creationDate'), '%y-%m-%d %j:%n:%s'),
lastUpdated => $date->epochToHuman($album->get('revisionDate'), '%y-%m-%d %j:%n:%s'),
};
if ($as eq "xml") {
$session->http->setMimeType('text/xml');
return XML::Simple::XMLout($document, NoAttr => 1);
}
$session->http->setMimeType('application/json');
return JSON->new->pretty->encode($document);
}
#----------------------------------------------------------------------------
=head2 www_listAlbums ( )
Show a paginated list of the albums in this gallery.
=cut
sub www_listAlbums {
my $self = shift;
# Perform the prepareView ourselves
$self->prepareViewListAlbums;
return $self->processStyle(
$self->view_listAlbums
);
}
#----------------------------------------------------------------------------
=head2 www_listAlbumsRss ( )
Show an RSS feed for the albums in this gallery.
=cut
sub www_listAlbumsRss {
my $self = shift;
my $session = $self->session;
my $var = $self->getTemplateVars;
for my $assetId ( @{ $self->getAlbumIds } ) {
my $asset = WebGUI::Asset->new( $session, $assetId, 'WebGUI::Asset::Wobject::GalleryAlbum');
my $assetVar = $asset->getTemplateVars;
# Fix URLs
for my $key ( qw( url ) ) {
$assetVar->{ $key } = $self->session->url->getSiteURL . $assetVar->{ $key };
}
# Encode XML entities
for my $key ( qw( title description synopsis gallery_title gallery_menuTitle ) ) {
$assetVar->{ $key } = WebGUI::HTML::filter($assetVar->{$key}, 'xml');
}
# Additional vars for RSS
$assetVar->{ rssDate }
= $session->datetime->epochToMail( $assetVar->{ creationDate } );
push @{ $var->{albums} }, $assetVar;
}
$self->session->http->setMimeType('text/xml');
return $self->processTemplate( $var, $self->get("templateIdListAlbumsRss") );
}
#----------------------------------------------------------------------------
=head2 www_listAlbumsService ( )
A web service to retrieve album information. You may request information from this gallery with a straight GET request:
http://admin:123qwe@www.example.com/gallery-url?func=listAlbumsService
The following parameters are optional, but may be passed along the query to change the output of this method.
=head3 as
Defaults to 'json', but can be overridden as 'xml'. If specified as 'json' the document returned will look like this:
{
"pageNumber" : 1,
"gallery" : {
"lastUpdated" : "2008-10-13 14:56:49",
"synopsis" : "This is the summary.",
"menuTitle" : "My Cool Gallery",
"url" : "http://dev.localhost.localdomain/cool-gallery",
"title" : "My Cool Gallery",
"canAddAlbums" : 1,
"dateCreated" : "2008-10-13 14:48:44"
},
"albums" : [
{
"thumbnailUrl" : "http://dev.localhost.localdomain",
"lastUpdated" : "2008-10-13 14:51:38",
"canAddFiles" : 1,
"url" : "http://dev.localhost.localdomain/cool-gallery/the-gallery-you-can-post-to",
"title" : "The Gallery You Can Post To",
"dateCreated" : "2008-10-13 14:50:22"
},
{
"thumbnailUrl" : "http://dev.localhost.localdomain",
"lastUpdated" : "2008-10-13 14:51:20",
"canAddFiles" : 0,
"url" : "http://dev.localhost.localdomain/cool-gallery/another-album",
"title" : "Another Album",
"dateCreated" : "2008-10-13 14:51:20"
}
]
}
If specified as 'xml' the document returned will look like this:
<opt>
<albums>
<canAddFiles>1</canAddFiles>
<dateCreated>2008-10-13 14:50:22</dateCreated>
<lastUpdated>2008-10-13 14:51:38</lastUpdated>
<thumbnailUrl>http://dev.localhost.localdomain</thumbnailUrl>
<title>The Gallery You Can Post To</title>
<url>http://dev.localhost.localdomain/cool-gallery/the-gallery-you-can-post-to</url>
</albums>
<albums>
<canAddFiles>0</canAddFiles>
<dateCreated>2008-10-13 14:51:20</dateCreated>
<lastUpdated>2008-10-13 14:51:20</lastUpdated>
<thumbnailUrl>http://dev.localhost.localdomain</thumbnailUrl>
<title>Another Album</title>
<url>http://dev.localhost.localdomain/cool-gallery/another-album</url>
</albums>
<gallery>
<canAddAlbums>1</canAddAlbums>
<dateCreated>2008-10-13 14:48:44</dateCreated>
<lastUpdated>2008-10-13 14:56:49</lastUpdated>
<menuTitle>My Cool Gallery</menuTitle>
<synopsis>This is the summary.</synopsis>
<title>My Cool Gallery</title>
<url>http://dev.localhost.localdomain/cool-gallery</url>
</gallery>
<pageNumber>1</pageNumber>
</opt>
=head3 pn
Defaults to 1. This represents the page number. It will return up to 100 albums at a time.
=cut
sub www_listAlbumsService {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient unless ($self->canView);
my $siteUrl = $session->url->getSiteURL;
my @assets;
my $date = $session->datetime;
my $form = $session->form;
my $as = $form->get('as') || 'json';
my $pageNumber = $form->get('pn') || 1;
my $user = $session->user;
my $count = 1;
for my $assetId ( @{ $self->getAlbumIds } ) {
if ($count < $pageNumber * 100 - 100) { # skip low page numbers
next;
}
if ($count > $pageNumber * 100 - 1) { # skip high page numbers
last;
}
my $asset = WebGUI::Asset->new( $session, $assetId, 'WebGUI::Asset::Wobject::GalleryAlbum' );
if (defined $asset) {
if ($asset->canView) {
push @assets, {
title => $asset->getTitle,
url => $siteUrl.$asset->getUrl,
dateCreated => $date->epochToHuman($asset->get('creationDate'), '%y-%m-%d %j:%n:%s'),
lastUpdated => $date->epochToHuman($asset->get('revisionDate'), '%y-%m-%d %j:%n:%s'),
thumbnailUrl => $siteUrl.$asset->getThumbnailUrl,
canAddFiles => $asset->canAddFile,
};
}
}
$count++;
}
my $document = {
pageNumber => $pageNumber,
gallery => {
canAddAlbums => $self->canAddFile,
title => $self->getTitle,
menuTitle => $self->get('menuTitle'),
synopsis => $self->get('synopsis'),
url => $siteUrl.$self->getUrl,
dateCreated => $date->epochToHuman($self->get('creationDate'), '%y-%m-%d %j:%n:%s'),
lastUpdated => $date->epochToHuman($self->get('revisionDate'), '%y-%m-%d %j:%n:%s'),
},
albums => \@assets
};
if ($as eq "xml") {
$session->http->setMimeType('text/xml');
return XML::Simple::XMLout($document, NoAttr => 1);
}
$session->http->setMimeType('application/json');
return JSON->new->pretty->encode($document);
}
#----------------------------------------------------------------------------
=head2 search ( )
Helper method for C<www_search> 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 search {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
my $db = $session->db;
my $columns;
# Check whether we have to do a search
my $doSearch
= (
$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.
my $keywords;
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 }
. $db->quote( '%' . $form->get("title") . '%' )
;
}
if ( $form->get("description") ) {
$where .= q{ AND assetData.synopsis LIKE }
. $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);
my $dateBefore = $form->get("creationDate_before", "dateTime", time());
my $creationDate = {};
if ($dateAfter) {
$creationDate->{start} = $dateAfter;
}
if ($dateBefore) {
$creationDate->{end } = $dateBefore;
}
# Classes
my $classes = [
'WebGUI::Asset::Wobject::GalleryAlbum',
'WebGUI::Asset::File::GalleryFile::Photo',
];
if ( $form->get("className") ) {
$classes = [ $form->get('className') ];
}
# 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 ( @$classes ) {
$url .= 'className=' . $class . ';';
}
my $paginator
= $self->getSearchPaginator( {
url => $url,
keywords => $keywords,
where => $where,
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;
# 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 },
isAlbum => $asset->isa( 'WebGUI::Asset::Wobject::GalleryAlbum' ),
};
}
}
return $self->processStyle(
$self->processTemplate( $var, $self->get("templateIdSearch") )
);
}
#----------------------------------------------------------------------------
=head2 www_listFilesForUser ( )
Show all the GalleryAlbums and files owned by a given userId. If no userId is
given, will use the current user.
=cut
sub www_listFilesForUser {
my $self = shift;
my $session = $self->session;
my $var = $self->getTemplateVars;
my $userId = $self->session->form->get("userId") || $self->session->user->userId;
my $user = WebGUI::User->new( $session, $userId );
$var->{ url_rss } = $self->getUrl('func=listFilesForUserRss;userId=' . $userId);
$var->{ userId } = $userId;
$var->{ username } = $user->username;
# Get all the albums
my $albumIds = $self->getUserAlbumIds( $userId );
for my $albumId ( @$albumIds ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $albumId );
push @{ $var->{user_albums} }, $asset->getTemplateVars;
}
# Get a page of files
my $p
= $self->getUserFilePaginator({
userId => $userId,
url => $self->getUrl("func=listFilesForUser")
});
$p->appendTemplateVars( $var );
for my $fileId ( @{ $p->getPageData } ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $fileId );
push @{ $var->{user_files} }, $asset->getTemplateVars;
}
return $self->processStyle(
$self->processTemplate( $var, $self->get("templateIdListFilesForUser") )
);
}
#----------------------------------------------------------------------------
=head2 www_listFilesForUserRss ( )
=cut
sub www_listFilesForUserRss {
my $self = shift;
my $session = $self->session;
my $var = $self->getTemplateVars;
my $userId = $self->session->form("userId") || $self->session->user->userId;
# Fix URLs for template vars
for my $key ( qw( url ) ) {
$var->{ $key } = $self->session->url->getSiteURL . $var->{ $key };
}
# Get all the albums
my $albumIds = $self->getUserAlbumIds( $userId );
for my $albumId ( @$albumIds ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $albumId );
my $assetVar = $asset->getTemplateVars;
for my $key ( qw( url ) ) {
$assetVar->{ $key } = $self->session->url->getSiteURL . $assetVar->{ $key };
}
push @{ $var->{user_albums} }, $assetVar;
}
# Get all the files
my $fileIds = $self->getUserFileIds( $userId );
for my $fileId ( @$fileIds ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $fileId );
my $assetVar = $asset->getTemplateVars;
for my $key ( qw( url ) ) {
$assetVar->{ $key } = $self->session->url->getSiteURL . $assetVar->{ $key };
}
push @{ $var->{user_files} }, $assetVar;
}
$self->session->http->setMimeType('text/xml');
return $self->processTemplate( $var, $self->get("templateIdListFilesForUserRss") );
}
1;