Merge branch 'master' into WebGUI8

This commit is contained in:
Graham Knop 2010-04-13 07:50:02 -05:00
commit 2400f19099
797 changed files with 33894 additions and 27196 deletions

View file

@ -322,7 +322,7 @@ sub view {
my $cache = $self->session->cache;
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10 && !$self->session->form->process("overrideTemplateId") &&
!$self->session->form->process($self->paginateVar) && !$self->session->form->process("makePrintable")) {
my $out = eval{$cache->get("view_".$self->getId)};
my $out = eval{$cache->get($self->getViewCacheKey)};
return $out if $out;
}
my %var;
@ -386,7 +386,7 @@ sub view {
my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate});
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10 && !$self->session->form->process("overrideTemplateId") &&
!$self->session->form->process($self->paginateVar) && !$self->session->form->process("makePrintable")) {
eval{$cache->set("view_".$self->getId, $out, $self->cacheTimeout)};
eval{$cache->set($self->getViewCacheKey, $out, $self->cacheTimeout)};
}
return $out;
}

View file

@ -75,7 +75,6 @@ property groupIdSubscribed => (
fieldType => 'hidden',
);
##### TEMPLATES - DISPLAY #####
# Month
property templateIdMonth => (
@ -770,18 +769,18 @@ sub getEventsIn {
&& Event.endTime IS NULL
&&
!(
Event.startDate >= '$endDate'
|| Event.endDate < '$startDate'
Event.startDate > '$endDate'
|| Event.endDate < '$startDate'
)
)
|| (
CONCAT(Event.startDate,' ',Event.startTime) >= '$start'
&& CONCAT(Event.startDate,' ',Event.startTime) < '$end'
|| !(
CONCAT(Event.startDate,' ',Event.startTime) >= '$end'
|| CONCAT(Event.endDate, ' ',Event.endTime ) <= '$start'
)
};
my @order_priority
= ( 'Event.startDate',
= ( 'Event.startDate',
'Event.startTime',
'Event.endDate',
'Event.endTime',
@ -1275,9 +1274,11 @@ sub viewList {
my $session = $self->session;
my $i18n = WebGUI::International->new($session,"Asset_Calendar");
my $var = $self->getTemplateVars;
my $tz = $session->datetime->getTimeZone();
### Get the events
my $dtStart = WebGUI::DateTime->new( $session, $params->{start} )->truncate( to => "day" );
my $dtStart = WebGUI::DateTime->new( $session, $params->{start} );
$dtStart->set_time_zone($tz);
my $dtEnd = $dtStart->clone->add( seconds => $self->listViewPageInterval );
my @events
@ -1446,8 +1447,8 @@ sub viewMonth {
}
# Day names
my @dayNames = @{$dt->locale->day_names}[6,0..5]; # Put sunday first
my @dayAbbrs = @{$dt->locale->day_abbreviations}[6,0..5];
my @dayNames = @{$dt->locale->day_format_wide}[6,0..5]; # Put sunday first
my @dayAbbrs = @{$dt->locale->day_format_abbreviated}[6,0..5];
# Take from FirstDOW to the end and put it on the beginning
unshift @dayNames,splice(@dayNames,$first_dow);
unshift @dayAbbrs,splice(@dayAbbrs,$first_dow);
@ -1885,7 +1886,7 @@ sub www_ical {
);
}
else {
$dt_start = WebGUI::DateTime->new($self->session, time);
$dt_start = WebGUI::DateTime->new($session, time);
$dt_start->set_time_zone( $session->datetime->getTimeZone );
}
@ -1893,7 +1894,7 @@ sub www_ical {
my $end = $form->param("end");
if ($end) {
$dt_end
= WebGUI::DateTime->new($self->session,
= WebGUI::DateTime->new($session,
mysql => $end,
time_zone => $session->datetime->getTimeZone,
);
@ -1902,8 +1903,6 @@ sub www_ical {
$dt_end = $dt_start->clone->add( seconds => $self->icalInterval );
}
# Get all the events we're going to display
my @events = $self->getEventsIn($dt_start->toMysql,$dt_end->toMysql);
@ -2104,6 +2103,7 @@ sub www_search {
$var->{"form.header"}
= WebGUI::Form::formHeader($session, {
action => $self->getUrl,
method => 'GET',
})
. WebGUI::Form::hidden($self->session, {
name => "func",

View file

@ -13,7 +13,6 @@ $VERSION = "1.0.0";
#-------------------------------------------------------------------
use strict;
use warnings;
use JSON;
use WebGUI::International;
use Moose;

View file

@ -532,14 +532,16 @@ A reference to a WebGUI::Paginator object.
=cut
sub appendPostListTemplateVars {
my $self = shift;
my $var = shift;
my $p = shift;
my $page = $p->getPageData;
my $i = 0;
my ($icon, $datetime) = $self->session->quick(qw(icon datetime));
my $self = shift;
my $session = $self->session;
my $var = shift;
my $p = shift;
my $page = $p->getPageData;
my $i = 0;
my ($icon, $datetime) = $session->quick(qw(icon datetime));
my $isVisitor = $session->user->isVisitor;
foreach my $row (@$page) {
my $post = WebGUI::Asset->newById($self->session,$row->{assetId}, $row->{revisionDate});
my $post = WebGUI::Asset->newById($session,$row->{assetId}, $row->{revisionDate});
$post->{_parent} = $self; # caching parent for efficiency
my $controls = $icon->delete('func=delete',$post->url,"Delete") . $icon->edit('func=edit',$post->url);
if ($self->sortBy eq "lineage") {
@ -560,10 +562,11 @@ sub appendPostListTemplateVars {
if ($self->displayLastReply) {
my $lastPost = $post->getLastPost();
%lastReply = (
"lastReply.url" => $lastPost->getUrl.'#'.$lastPost->getId,
"lastReply.url" => $lastPost->getThreadLinkUrl,
"lastReply.title" => $lastPost->title,
"lastReply.user.isVisitor" => $lastPost->ownerUserId eq "1",
"lastReply.username" => $lastPost->username,
"lastReply.hideProfileUrl" => $lastPost->ownerUserId eq "1" || $isVisitor,
"lastReply.userProfile.url" => $lastPost->getPosterProfileUrl(),
"lastReply.dateSubmitted.human" => $datetime->epochToHuman($lastPost->creationDate,"%z"),
"lastReply.timeSubmitted.human" => $datetime->epochToHuman($lastPost->creationDate,"%Z"),
@ -571,16 +574,10 @@ sub appendPostListTemplateVars {
}
$hasRead = $post->isMarkedRead;
}
my $url;
if ($post->status eq "pending") {
$url = $post->getUrl("revision=".$post->revisionDate)."#".$post->getId;
} else {
$url = $post->getUrl."#".$post->getId;
}
my %postVars = (
%{$post->get},
"id" => $post->getId,
"url" => $url,
"url" => $post->getThreadLinkUrl,
rating_loop => \@rating_loop,
"content" => $post->formatContent,
"status" => $post->getStatus,
@ -590,14 +587,15 @@ sub appendPostListTemplateVars {
"dateUpdated.human" => $datetime->epochToHuman($post->revisionDate,"%z"),
"timeSubmitted.human" => $datetime->epochToHuman($post->creationDate,"%Z"),
"timeUpdated.human" => $datetime->epochToHuman($post->revisionDate,"%Z"),
"hideProfileUrl" => $post->ownerUserId eq '1' || $isVisitor,
"userProfile.url" => $post->getPosterProfileUrl,
"user.isVisitor" => $post->ownerUserId eq "1",
"edit.url" => $post->getEditUrl,
'controls' => $controls,
"isSecond" => (($i+1)%2==0),
"isThird" => (($i+1)%3==0),
"isFourth" => (($i+1)%4==0),
"isFifth" => (($i+1)%5==0),
"isSecond" => (($i+1) == 2),
"isThird" => (($i+1) == 3),
"isFourth" => (($i+1) == 4),
"isFifth" => (($i+1) == 5),
"user.hasRead" => $hasRead,
"user.isPoster" => $post->isPoster,
"avatar.url" => $post->getAvatarUrl,
@ -607,7 +605,7 @@ sub appendPostListTemplateVars {
if ($row->{className} =~ m/^WebGUI::Asset::Post::Thread/) {
$postVars{'rating'} = $post->threadRating;
}
push(@{$var->{post_loop}}, \%postVars );
push(@{$var->{post_loop}}, \%postVars );
$i++;
}
$p->appendTemplateVars($var);
@ -926,7 +924,8 @@ sub createSubscriptionGroup {
=head2 duplicate
Extend the base method to handle making a subscription group for the new CS.
Extend the base method to handle making a subscription group for the new CS, and
to build a new Cron job. It also recalculates the number of threads and replies.
=cut
@ -934,7 +933,33 @@ sub duplicate {
my $self = shift;
my $newAsset = $self->next::method(@_);
$newAsset->createSubscriptionGroup;
return $newAsset;
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
my $newCron = WebGUI::Workflow::Cron->create($self->session, {
title=>$self->getTitle." ".$i18n->get("mail"),
minuteOfHour=>"*/".($self->get("getMailInterval")/60),
className=>(ref $self),
methodName=>"new",
parameters=>$self->getId,
workflowId=>"csworkflow000000000001"
});
$newAsset->update({getMailCronId=>$newCron->getId});
$newAsset->incrementReplies('','');
return $newAsset;
}
#-------------------------------------------------------------------
=head2 duplicateBranch.
Extend the base method to recalculate the number of threads and replies.
=cut
sub duplicateBranch {
my $self = shift;
my $newAsset = $self->next::method(@_);
$newAsset->incrementReplies('','');
return $newAsset;
}
#-------------------------------------------------------------------
@ -1126,62 +1151,75 @@ Collaboration System
=cut
sub getThreadsPaginator {
my $self = shift;
my $scratchSortBy = $self->getId."_sortBy";
my $scratchSortOrder = $self->getId."_sortDir";
my $sortBy = $self->session->form->process("sortBy") || $self->session->scratch->get($scratchSortBy) || $self->sortBy;
my $sortOrder = $self->session->scratch->get($scratchSortOrder) || $self->sortOrder;
if ($sortBy ne $self->session->scratch->get($scratchSortBy) && $self->session->form->process("func") ne "editSave") {
$self->session->scratch->set($scratchSortBy,$self->session->form->process("sortBy"));
$self->session->scratch->set($scratchSortOrder, $sortOrder);
} elsif ($self->session->form->process("sortBy") && $self->session->form->process("func") ne "editSave") {
if ($sortOrder eq "asc") {
$sortOrder = "desc";
} else {
$sortOrder = "asc";
}
$self->session->scratch->set($scratchSortOrder, $sortOrder);
}
$sortBy ||= "assetData.revisionDate";
$sortOrder ||= "desc";
# Sort by the thread rating instead of the post rating. other places don't care about threads.
if ($sortBy eq 'rating') {
$sortBy = 'threadRating';
}
$sortBy = join('.', map { $self->session->db->dbh->quote_identifier($_) } split(/\./, $sortBy));
my $self = shift;
my $session = $self->session;
my $sql = "
select
asset.assetId,
asset.className,
assetData.revisionDate as revisionDate
from Thread
left join asset on Thread.assetId=asset.assetId
left join Post on Post.assetId=Thread.assetId and Thread.revisionDate = Post.revisionDate
left join assetData on assetData.assetId=Thread.assetId and Thread.revisionDate = assetData.revisionDate
where
asset.parentId=".$self->session->db->quote($self->getId)."
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and assetData.revisionDate=(
select
max(revisionDate)
from
assetData
where
assetData.assetId=asset.assetId
and (status='approved' or status='archived')
)
and status='approved'
group by
assetData.assetId
order by
Thread.isSticky desc,
".$sortBy."
".$sortOrder;
my $p = WebGUI::Paginator->new($self->session,$self->getUrl,$self->threadsPerPage);
$p->setDataByQuery($sql);
my $scratchSortBy = $self->getId."_sortBy";
my $scratchSortOrder = $self->getId."_sortDir";
my $sortBy = $self->session->form->process("sortBy")
|| $self->session->scratch->get($scratchSortBy)
|| $self->sortBy;
$sortBy =~ s/^\w+\.//;
# Sort by the thread rating instead of the post rating. other places don't care about threads.
$sortBy = $sortBy eq 'rating' ? 'threadRating' : $sortBy;
if (! WebGUI::Utility::isIn($sortBy, qw/userDefined1 userDefined2 userDefined3 userDefined4 userDefined5 title lineage revisionDate creationDate karmaRank threadRating/)) {
$sortBy = 'revisionDate';
}
if ($sortBy eq 'assetId' || $sortBy eq 'revisionDate') {
$sortBy = 'assetData.' . $sortBy;
}
my $sortOrder = $self->session->form->process("sortOrder")
|| $self->session->scratch->get($scratchSortOrder)
|| $self->get("sortOrder");
#$sortOrder = lc $sortOrder;
#$sortOrder = 'desc' if ($sortOrder ne 'asc' && $sortOrder ne 'desc');
if ($sortBy ne $self->session->scratch->get($scratchSortBy) && $self->session->form->process("func") ne "editSave") {
$self->session->scratch->set($scratchSortBy,$self->session->form->process("sortBy"));
$self->session->scratch->set($scratchSortOrder, $sortOrder);
}
elsif ($self->session->form->process("sortBy") && $self->session->form->process("func") ne "editSave" && ! $self->session->form->process('sortOrder')) {
if ($sortOrder eq "asc") {
$sortOrder = "desc";
}
else {
$sortOrder = "asc";
}
$self->session->scratch->set($scratchSortOrder, $sortOrder);
}
$sortBy = join('.', map { $self->session->db->dbh->quote_identifier($_) } split(/\./, $sortBy));
$sortOrder ||= 'desc';
my $sql = "
select
asset.assetId,
asset.className,
assetData.revisionDate as revisionDate
from Thread
left join asset on Thread.assetId=asset.assetId
left join Post on Post.assetId=Thread.assetId and Thread.revisionDate = Post.revisionDate
left join assetData on assetData.assetId=Thread.assetId and Thread.revisionDate = assetData.revisionDate
where
asset.parentId=".$self->session->db->quote($self->getId)."
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and assetData.revisionDate=(
select
max(revisionDate)
from
assetData
where
assetData.assetId=asset.assetId
and (status='approved' or status='archived')
)
and status='approved'
group by
assetData.assetId
order by
Thread.isSticky desc,
".$sortBy."
".$sortOrder;
my $p = WebGUI::Paginator->new($session,$self->getUrl,$self->threadsPerPage);
$p->setDataByQuery($sql);
return $p;
}
@ -1214,10 +1252,10 @@ sub getViewTemplateVars {
my %var;
$var{'user.canPost'} = $self->canPost;
$var{'user.canStartThread'} = $self->canStartThread;
$var{"add.url"} = $self->getNewThreadUrl;
$var{"rss.url"} = $self->getRssFeedUrl;
$var{'user.isModerator'} = $self->canModerate;
$var{'user.isVisitor'} = ($self->session->user->isVisitor);
$var{"add.url"} = $self->getNewThreadUrl;
$var{"rss.url"} = $self->getRssFeedUrl;
$var{'user.isModerator'} = $self->canModerate;
$var{'user.isVisitor'} = ($self->session->user->isVisitor);
$var{'user.isSubscribed'} = $self->isSubscribed;
$var{'sortby.title.url'} = $self->getSortByUrl("title");
$var{'sortby.username.url'} = $self->getSortByUrl("username");
@ -1564,6 +1602,23 @@ sub view {
#-------------------------------------------------------------------
=head2 www_edit
Override the master class to add an "Unarchive All" link.
=cut
sub www_edit {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canEdit;
return $self->session->privilege->locked() unless $self->canEditIfLocked;
my $i18n = WebGUI::International->new($self->session, 'Asset_Collaboration');
$self->getAdminConsole->addConfirmedSubmenuItem($self->getUrl('func=unarchiveAll'),$i18n->get("unarchive all"),$i18n->get("unarchive confirm"));
return $self->getAdminConsole->render($self->getEditForm->print,$i18n->get("assetName"));
}
#-------------------------------------------------------------------
=head2 www_search ( )
The web method to display and use the forum search interface.
@ -1578,7 +1633,8 @@ sub www_search {
my $query = $self->session->form->process("query","text");
$var->{'form.header'} = WebGUI::Form::formHeader($self->session,{
action=>$self->getUrl("func=search;doit=1")
action=> $self->getUrl("func=search;doit=1"),
method=> 'GET',
});
$var->{'query.form'} = WebGUI::Form::text($self->session,{
name => 'query',
@ -1619,6 +1675,35 @@ sub www_subscribe {
return $self->www_view;
}
#----------------------------------------------------------------------------
=head2 www_unarchiveAll ( )
Unarchive all the threads in this collaboration system
=cut
sub www_unarchiveAll {
my ( $self ) = @_;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canEdit;
my $pb = WebGUI::ProgressBar->new($session);
my $i18n = WebGUI::International->new($session, 'Asset_Collaboration');
$pb->start($i18n->get('unarchive all'), $self->getUrl('func=edit'));
my $threadIds = $self->getLineage(['children'],{
includeOnlyClasses => [ 'WebGUI::Asset::Post::Thread' ],
statusToInclude => [ 'archived' ],
} );
ASSET: foreach my $threadId (@$threadIds) {
my $thread = WebGUI::Asset->newPending($session, $threadId);
if (!$thread || !$thread->canEdit) {
next ASSET;
}
$thread->unarchive;
}
return $pb->finish( $self->getUrl('func=edit') );
}
#-------------------------------------------------------------------
=head2 www_unsubscribe ( )

View file

@ -223,9 +223,11 @@ has '+uiLevel' => (
use WebGUI::Pluggable;
use WebGUI::DateTime;
use WebGUI::User;
use WebGUI::Utility;
use WebGUI::Group;
use WebGUI::AssetCollateral::DataForm::Entry;
use WebGUI::Form::SelectRichEditor;
use WebGUI::Paginator;
=head1 NAME
@ -413,13 +415,13 @@ sub deleteTab {
=head2 getContentLastModified
Extends the base method to modify caching. If the currentView is in list mode, or
an entry is being viewed, bypass caching altogether.
an entry is being viewed, or the DataForm has a captcha, bypass caching altogether.
=cut
override getContentLastModified => sub {
my $self = shift;
if ($self->currentView eq 'list' || $self->session->form->process('entryId')) {
if ($self->currentView eq 'list' || $self->session->form->process('entryId') || $self->hasCaptcha) {
return time;
}
return super();
@ -427,6 +429,19 @@ override getContentLastModified => sub {
#-------------------------------------------------------------------
=head2 hasCaptcha
Returns true if the DataForm uses a captcha as one of the fields.
=cut
sub hasCaptcha {
my $self = shift;
return isIn('Captcha', map { $_->{type} } map { $self->getFieldConfig($_) } @{ $self->getFieldOrder });
}
#-------------------------------------------------------------------
=head2 renameField ($oldName, $newName)
Renames a field by name
@ -693,9 +708,10 @@ A hash reference. New template variables will be appended to it.
=cut
sub getListTemplateVars {
my $self = shift;
my $var = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $self = shift;
my $session = $self->session;
my $var = shift;
my $i18n = WebGUI::International->new($session,"Asset_DataForm");
$var->{"back.url"} = $self->getFormUrl;
$var->{"back.label"} = $i18n->get('go to form');
my $fieldConfig = $self->getFieldConfig;
@ -709,7 +725,9 @@ sub getListTemplateVars {
} @{ $self->getFieldOrder };
$var->{field_loop} = \@fieldLoop;
my @recordLoop;
my $entryIter = $self->entryClass->iterateAll($self);
my $p = WebGUI::Paginator->new($session);
$p->setDataByCallback(sub { return $self->entryClass->iterateAll($self, { offset => $_[0], limit => $_[1], }); });
my $entryIter = $p->getPageIterator();
while ( my $entry = $entryIter->() ) {
my $entryData = $entry->fields;
my @dataLoop;
@ -730,9 +748,9 @@ sub getListTemplateVars {
%dataVars,
"record.ipAddress" => $entry->ipAddress,
"record.edit.url" => $self->getFormUrl("func=view;entryId=".$entry->getId),
"record.edit.icon" => $self->session->icon->edit("func=view;entryId=".$entry->getId, $self->url),
"record.edit.icon" => $session->icon->edit("func=view;entryId=".$entry->getId, $self->url),
"record.delete.url" => $self->getUrl("func=deleteEntry;entryId=".$entry->getId),
"record.delete.icon" => $self->session->icon->delete("func=deleteEntry;entryId=".$entry->getId, $self->url, $i18n->get('Delete entry confirmation')),
"record.delete.icon" => $session->icon->delete("func=deleteEntry;entryId=".$entry->getId, $self->url, $i18n->get('Delete entry confirmation')),
"record.username" => $entry->username,
"record.userId" => $entry->userId,
"record.submissionDate.epoch" => $entry->submissionDate->epoch,
@ -742,6 +760,7 @@ sub getListTemplateVars {
};
}
$var->{record_loop} = \@recordLoop;
$p->appendTemplateVars($var);
return $var;
}
@ -1258,6 +1277,9 @@ sub viewForm {
$entry = $self->entryClass->new($self, ($entryId && $self->canEdit) ? $entryId : ());
}
$var = $passedVars || $self->getRecordTemplateVars($var, $entry);
if ($self->hasCaptcha) {
$self->session->http->setCacheControl('none');
}
return $self->processTemplate($var, undef, $self->{_viewFormTemplate});
}
@ -1338,6 +1360,8 @@ sub www_deleteFieldConfirm {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
$newSelf->deleteField($self->session->form->process("fieldName"));
$newSelf->{_mode} = 'form';
@ -1363,6 +1387,8 @@ sub www_deleteTabConfirm {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
$newSelf->deleteTab($self->session->form->process("tabId"));
$newSelf->{_mode} = 'form';
@ -1385,6 +1411,8 @@ sub www_editField {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $fieldName = shift || $self->session->form->process("fieldName");
my $field;
@ -1534,6 +1562,8 @@ sub www_editFieldSave {
my $session = $self->session;
return $session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $form = $session->form;
my $fieldName = $form->process('fieldName');
my $newName = $session->url->urlize($form->process('newName') || $form->process('label'));
@ -1587,7 +1617,7 @@ sub www_editFieldSave {
$newSelf->createField($newName, \%field);
}
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($session);
my $freshSelf = $newSelf->cloneFromDb();
if ($form->process("proceed") eq "editField") {
return $freshSelf->www_editField('new');
@ -1677,6 +1707,8 @@ sub www_editTab {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $tabId = shift || $self->session->form->process("tabId") || "new";
my $tab;
@ -1732,6 +1764,8 @@ sub www_editTabSave {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $name = $self->session->form->process("name") || $self->session->form->process("label");
$name = $self->session->url->urlize($name);
my $tabId = $self->session->form->process('tabId');
@ -1825,6 +1859,8 @@ sub www_moveFieldDown {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
my $fieldName = $self->session->form->process('fieldName');
$newSelf->moveFieldDown($fieldName);
@ -1883,6 +1919,8 @@ sub www_moveFieldUp {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
my $fieldName = $self->session->form->process('fieldName');
$newSelf->moveFieldUp($fieldName);
@ -1942,6 +1980,8 @@ sub www_moveTabRight {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
my $tabId = $self->session->form->process('tabId');
$newSelf->moveTabRight($tabId);
@ -1996,6 +2036,8 @@ sub www_moveTabLeft {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
return $self->session->privilege->locked
unless $self->canEditIfLocked;
my $newSelf = $self->addRevision;
my $tabId = $self->session->form->process('tabId');
$newSelf->moveTabLeft($tabId);

View file

@ -102,7 +102,7 @@ sub getDataTemplateVars {
my $self = shift;
my $json = $self->getDataJson;
my $dt = JSON->new->decode($json);
my $dt = eval { JSON->new->decode($json) };
# Make row data more friendly to templates
my %cols = map { $_->{key} => $_ } @{ $dt->{columns} };
@ -131,7 +131,8 @@ override getEditForm => sub {
my $tabform = super();
$tabform->getTab("data")->raw(
WebGUI::Form::DataTable->new(
q{<tr><td>}
. WebGUI::Form::DataTable->new(
$self->session, {
name => "data",
value => $self->data,
@ -139,6 +140,7 @@ override getEditForm => sub {
showEdit => 1,
}
)->toHtml
. q{</td></tr>}
);
return $tabform;

View file

@ -1,5 +1,6 @@
package WebGUI::Asset::Wobject::EventManagementSystem;
=head1 LEGAL
-------------------------------------------------------------------
@ -83,6 +84,38 @@ property printTicketTemplateId => (
hoverHelp => ['print ticket template help', 'Asset_EventManagementSystem'],
namespace => 'EMS/PrintTicket',
);
property eventSubmissionMainTemplateId => (
fieldType => 'template',
default => 'DoVNijm6lMDE0cYrtvEbDQ',
tab => 'display',
label => ['event submission main template', 'Asset_EventManagementSystem'],
hoverHelp => ['event submission main template help', 'Asset_EventManagementSystem'],
namespace => 'EMS/SubmissionMain',
);
property eventSubmissionTemplateId => (
fieldType => 'template',
default => '8tqyQx-LwYUHIWOlKPjJrA',
tab => 'display',
label => ['event submission template', 'Asset_EventManagementSystem'],
hoverHelp => ['event submission template help', 'Asset_EventManagementSystem'],
namespace => 'EMS/Submission',
);
property eventSubmissionQueueTemplateId => (
fieldType => 'template',
default => 'ktSvKU8riGimhcsxXwqvPQ',
tab => 'display',
label => ['event submission queue template', 'Asset_EventManagementSystem'],
hoverHelp => ['event submission queue template help', 'Asset_EventManagementSystem'],
namespace => 'EMS/SubmissionQueue',
);
property printRemainingTicketsTemplateId => (
fieldType => 'template',
default => 'hreA_bgxiTX-EzWCSZCZJw',
tab => 'display',
label => ['print remaining ticket template', 'Asset_EventManagementSystem'],
hoverHelp => ['print remaining ticket template help', 'Asset_EventManagementSystem'],
namespace => 'EMS/PrintRemainingTickets',
);
property badgeInstructions => (
fieldType => 'HTMLArea',
builder => '_badgeInstructions_builder',
@ -142,6 +175,18 @@ property registrationStaffGroupId => (
label => ['registration staff group', 'Asset_EventManagementSystem'],
hoverHelp => ['registration staff group help', 'Asset_EventManagementSystem'],
);
property submittedLocationsList => (
fieldType => 'textarea',
tab => 'properties',
default => '',
label => ['submitted location list label', 'Asset_EventManagementSystem'],
hoverHelp => ['submitted location list help', 'Asset_EventManagementSystem'],
);
property eventSubmissionGroups => (
fieldType => 'hidden',
default => '',
noFormPost => 1,
);
use Digest::MD5;
@ -161,6 +206,89 @@ use WebGUI::Utility;
use WebGUI::Workflow::Instance;
use Data::Dumper;
#-------------------------------------------------------------------
=head2 addGroupToSubmitList ( groupId )
adds the parameter to eventSubmissionGroups
=cut
sub addGroupToSubmitList {
my $self = shift;
my $groupId = shift;
my ($idString) = $self->session->db->read('select eventSubmissionGroups from EventManagementSystem where assetId = ?', [ $self->getId ] )->array;
my @ids = split(' ', $idString);
my %h;
@ids = map { $h{$_}++ == 0 ? $_ : () } ( $groupId, @ids );
$self->update({eventSubmissionGroups => join( ' ', @ids ) });
}
#-------------------------------------------------------------------
=head2 addSubmissionForm
creates a child of class WG::Asset::EMSSubmissionForm
=head3 params
parameters that define the form
=head4 title
the title for the form
=head4 canSubmitGroupId ( optional )
group id for the users that are allowed to submit via this form
defaults to 2 -- registered users
=head4 daysBeforeCleanup ( optional )
number fo days to leave denied/created status items in the database before deleting
defaults to 7
=head4 deleteCreatedItems ( optional )
1 indicates that items with status 'created' should be deleted as well as denied
default: 0
=head4 formDescription
a JSON description of the form data fields -- a hash of the names of fields (each is 1 for active, 0 for inactive) plus
'_fieldList' added as an ARRAYREF of the fields that are active
=cut
sub addSubmissionForm {
my $self = shift;
my $params = shift;
$params->{className} = 'WebGUI::Asset::EMSSubmissionForm';
$params->{canSubmitGroupId} ||= 2;
$self->addGroupToSubmitList($params->{canSubmitGroupId});
my $newAsset = $self->addChild($params);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
$self = $self->cloneFromDb;
return $newAsset;
}
#-------------------------------------------------------------------
=head2 canSubmit
returns true is the current user can submit to any form attached to this EMS
=cut
sub canSubmit {
my $self = shift;
my $user = $self->session->user;
return 0 if ! $self->hasSubmissionForms;
for my $groupId (split ' ', $self->get('eventSubmissionGroups')) {
return 1 if $user->isInGroup($groupId);
}
return 0;
}
#------------------------------------------------------------------
@ -178,6 +306,21 @@ sub deleteEventMetaField {
}
#-------------------------------------------------------------------
=head2 ems
this is called by the submission sub-system
it is for compatability and ensures that the ems
object is used for certain calls
=cut
sub ems {
my $self = shift;
return $self;
}
#-------------------------------------------------------------------
=head2 getBadges ()
@ -276,6 +419,7 @@ sub getEventFieldsForImport {
type => $field->{dataType},
options => $field->{possibleValues},
defaultValue => $field->{defaultValues},
helpText => $field->{defaultValues},
});
}
return \@fields;
@ -292,33 +436,37 @@ may be SQL optimized for quick access
sub getLocations {
my $self = shift;
my $dateRef = shift || [ ];
my $dateRef = shift;
my %hash;
my %hashDate;
my %h;
my $tickets = $self->getTickets;
for my $ticket ( @$tickets ) {
my $name = $ticket->location;
my $date = $ticket->startDate;
$hash{$name} = 1 if defined $name;
# cut off the time from the startDate.
$date =~ s/\s*\d+:\d+(:\d+)?// if defined $date;
$hashDate{$date} = 1 if defined $date;
# this is a really compact 'uniq' operation
my @locations = map { $h{$_}++ == 0 ? $_ : () } ( map { $_->location } ( @$tickets ) );
# the dates have the time data removed with a pattern substitution
if( $dateRef ) {
push @$dateRef, map { s/\s*\d+:\d+(:\d+)?//; $h{$_}++ == 0 ? $_ : () } ( map { $_->startDate } ( @$tickets ) );
}
my @locations = sort keys %hash;
push @$dateRef, sort keys %hashDate ;
# @locations = $self->session->db->read(q{
# select distinct(EMSTicket.location)
# from EMSTicket join asset using (assetId)
# where asset.parentId = ?
# order by EMSTicket.location
# },[$self->getId])->array;
return @locations;
}
#-------------------------------------------------------------------
=head2 getNextSubmissionId
get a sequence number for the submission id
=cut
sub getNextSubmissionId {
my $self = shift;
return $self->session->db->getNextId( 'SubmissionId' );
}
#-------------------------------------------------------------------
=head2 getRegistrant ( badgeId )
Returns a hash reference containing the properties of a registrant.
@ -349,6 +497,80 @@ sub getRibbons {
#-------------------------------------------------------------------
=head2 getSubmissionLocations
retuns an arrayref of the locations found in the submission location list
=cut
sub getSubmissionLocations {
my $self = shift;
my $text = $self->get('submittedLocationsList');
return undef if $text eq '';
return [ split( /[\n]+/, $text ) ];
}
#-------------------------------------------------------------------
=head2 getSubmissionForms
returns a list of objects; one for each submission form related to this EMS
this function is called twice in just a few lines of code so the results are cached
to prevent extra hits to the database
=cut
sub getSubmissionForms {
my $self = shift;
return $self->{_submissionForms} if $self->{_submissionFormTime} > time;
$self->{_submissionForms} = $self->getLineage( ['children'], { returnObjects => 1,
includeOnlyClasses => ['WebGUI::Asset::EMSSubmissionForm'],
} );
$self->{_submissionFormTime} = time + 60;
return $self->{_submissionForms};
}
#-------------------------------------------------------------------
=head2 getSubmissionStatus
returns internationalized hash of submission status values or one internationalized name if a status is passed in
=cut
sub getSubmissionStatus {
my $self = shift;
my $key = shift;
unless ($self->{_status}) {
tie my %hash, "Tie::IxHash";
my $i18n = $self->i18n;
for my $item (
'pending',
'feedback',
'denied',
'approved',
'created',
'failed',
) {
$hash{$item} = $i18n->get($item),
}
$self->{_status} = \%hash;
}
if($key) {
return $self->{_status}{$key};
}
return $self->{_status};
}
#-------------------------------------------------------------------
=head2 getTickets ()
Returns an array reference of ticket objects.
@ -384,6 +606,54 @@ sub getTokens {
#-------------------------------------------------------------------
=head2 hasSubmissionForms
returns true if the EMS has subission forms attached
=cut
sub hasSubmissionForms {
my $self = shift;
# are there ~any~ forms attached to this ems?
my $res = $self->getLineage(['children'],{ limit => 1,
includeOnlyClasses => ['WebGUI::Asset::EMSSubmissionForm'],
} );
return scalar(@$res);
}
#-------------------------------------------------------------------
=head2 hasSubmissions
returns true if the current user has submission forms in this EMS
=cut
sub hasSubmissions {
my $self = shift;
return 0 if ! $self->canSubmit;
my $res = $self->getLineage(['descendants'],{ limit => 1,
includeOnlyClasses => ['WebGUI::Asset::EMSSubmission'],
whereClause => q{createdBy='} . $self->session->user->userId . q/'/,
} );
return scalar(@$res);
}
#-------------------------------------------------------------------
=head2 i18n
returns the internationalisation object for this asset
=cut
sub i18n {
my $self = shift;
return $self->{_i18n} ||= WebGUI::International->new($self->session,'Asset_EventManagementSystem');
}
#-------------------------------------------------------------------
=head2 isRegistrationStaff ( [ user ] )
Returns a boolean indicating whether the user is a member of the registration staff.
@ -397,7 +667,7 @@ A WebGUI::User object. Defaults to $session->user.
sub isRegistrationStaff {
my $self = shift;
my $user = shift || $self->session->user;
$user->isInGroup($self->registrationStaffGroupId);
$user->isInGroup($self->registrationStaffGroupId) || $self->canEdit;
}
#-------------------------------------------------------------------
@ -477,9 +747,18 @@ sub view {
addBadgeUrl => $self->getUrl('func=add;class=WebGUI::Asset::Sku::EMSBadge'),
buildBadgeUrl => $self->getUrl('func=buildBadge'),
viewScheduleUrl => $self->getUrl('func=viewSchedule'),
addSubmissionUrl => $self->getUrl('func=viewSubmissionQueue'),
# addSubmissionUrl => $self->getUrl('func=viewSubmissionQueue#addSubmission'),
viewSubmissionQueueUrl => $self->getUrl('func=viewSubmissionQueue'),
addSubmissionFormUrl => $self->getUrl('func=viewSubmissionQueue'),
# addSubmissionFormUrl => $self->getUrl('func=viewSubmissionQueue#addSubmissionForm'),
manageBadgeGroupsUrl=> $self->getUrl('func=manageBadgeGroups'),
getBadgesUrl => $self->getUrl('func=getBadgesAsJson'),
canEdit => $self->canEdit,
isRegistrationStaff => $self->isRegistrationStaff,
canEdit => $self->canEdit,
canSubmit => $self->canSubmit && ! $self->isRegistrationStaff,
hasSubmissions => $self->hasSubmissions,
hasSubmissionForms => $self->hasSubmissionForms,
lookupRegistrantUrl => $self->getUrl('func=lookupRegistrant'),
);
@ -510,6 +789,76 @@ sub www_addRibbonToBadge {
#-------------------------------------------------------------------
=head2 www_addSubmission ()
display a form or links to forms to create a new submission
=cut
sub www_addSubmission {
my $self = shift;
my $params = shift || {};
my $session = $self->session;
my $formId = $params->{formId} || $session->form->get('formId');
my $i18n = WebGUI::International->new($session,'Asset_EventManagementSystem');
my $form;
if( ! defined $formId ) {
my $res = $self->getSubmissionForms;
my @new = map { $_->canSubmit ? $_ : () } ( @$res);
if( scalar(@new) == 0 ) {
return $self->www_view;
} elsif( scalar(@new) == 1 ) {
$form = $new[0];
$formId = $form->getId;
} else {
my $makeAnchorList =sub{ my $u=shift; my $n=shift; my $d=shift;
return qq{<li><a href='$u' onclick='WebGUI.EMS.loadItemFromAnchor(this)' title='$d'>$n</a></li>} } ;
my $listOfLinks = join '', ( map {
$makeAnchorList->(
$self->getUrl('func=viewSubmissionQueue#' . $_->getId . '_new' ), # _new has to match same in sub www_viewSubmissionQueue in this module
$_->get('title'),
WebGUI::HTML::filter($_->get('description'),'all')
)
} ( @new ) );
my $title = $i18n->get('select form to submit') ;
my $asJson = $session->form->get('asJson');
if( $asJson ) {
$session->http->setMimeType( 'application/json' );
} else {
$session->http->setMimeType( 'text/html' );
}
my $content = '<h1>' . $title . '</h1><ul>' . $listOfLinks . '</ul>' ;
if( $asJson ) {
return JSON->new->encode( { text => $content, title => $title, id => 'list' . rand } );
} else {
return $self->ProcessStyle( $content );
}
}
}
$form = WebGUI::Asset->newByDynamicClass($session,$formId);
if (!defined $form) {
$session->errorHandler->error(__PACKAGE__ . " - failed to instanciate asset with assetId $formId");
}
return $form->www_addSubmission;
}
#-------------------------------------------------------------------
=head2 www_addSubmissionForm ()
call www_editSubmissionForm with assetId == new
=cut
sub www_addSubmissionForm {
my $self = shift;
my $params = shift || { };
$self->www_editSubmissionForm( { assetId => 'new', %$params } );
}
#-------------------------------------------------------------------
=head2 www_addTicketsToBadge ()
Adds selected tickets to a badge. Expects two form parameters, assetId (multiples fine) and badgeId, where assetId represents the ticket and badgeId represents the badge.
@ -572,6 +921,7 @@ sub www_buildBadge {
importTicketsUrl => $self->getUrl('func=importEvents'),
exportTicketsUrl => $self->getUrl('func=exportEvents'),
getTicketsUrl => $self->getUrl('func=getTicketsAsJson;badgeId='.$badgeId),
printRemainingTicketsUrl => $self->getUrl('func=printRemainingTickets'),
canEdit => $self->canEdit,
hasBadge => ($badgeId ne ""),
badgeId => $badgeId,
@ -686,6 +1036,62 @@ sub www_editBadgeGroupSave {
#-------------------------------------------------------------------
=head2 www_editSubmission
use getLineage to find the item to edit based on submissionId
then call www_editSubmission on it
=cut
sub www_editSubmission {
my $self = shift;
my $submissionId = $self->session->form->get('submissionId');
my $asset = $self->getLineage(['descendants'], { returnObjects => 1,
joinClass => "WebGUI::Asset::EMSSubmission",
whereClause => 'submissionId = ' . int($submissionId),
includeOnlyClasses => ['WebGUI::Asset::EMSSubmission'],
} );
return $asset->[0]->www_editSubmission;
}
#-------------------------------------------------------------------
=head2 www_editSubmissionForm
calls editSubmissionForm in WebGUI::Asset::EMSSubmissionForm
=cut
sub www_editSubmissionForm {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->isRegistrationStaff || $self->canEdit;
return WebGUI::Asset::EMSSubmissionForm->www_editSubmissionForm($self,shift);
}
#-------------------------------------------------------------------
=head2 www_editSubmissionFormSave
test and save data posted from editSubmissionForm...
=cut
sub www_editSubmissionFormSave {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->isRegistrationStaff || $self->canEdit;
my $formParams = WebGUI::Asset::EMSSubmissionForm->processForm($self);
if( $formParams->{_isValid} ) {
delete $formParams->{_isValid};
$self->addSubmissionForm($formParams);
return $self->www_viewSubmissionQueue;
} else {
return $self->www_editSubmissionForm($formParams);
}
}
#-------------------------------------------------------------------
=head2 www_editEventMetaField ( )
Displays the edit form for event meta fields.
@ -712,6 +1118,7 @@ sub www_editEventMetaField {
required => $self->session->form->process("required",'yesNo'),
possibleValues => $self->session->form->process("possibleValues",'textarea'),
defaultValues => $self->session->form->process("defaultValues",'textarea'),
helpText => $self->session->form->process("helpText",'textarea'),
};
$f->readOnly(
-name => 'error',
@ -768,6 +1175,12 @@ sub www_editEventMetaField {
-hoverHelp => $i18n->get('488 description'),
-value => $data->{defaultValues},
);
$f->textarea(
-name => "helpText",
-label => $i18n2->get('meta field help text'),
-hoverHelp => $i18n2->get('meta field help text description'),
-value => $data->{helpText},
);
$f->submit;
return $self->processStyle($f->print);
}
@ -800,6 +1213,7 @@ sub www_editEventMetaFieldSave {
required => $self->session->form->process("required",'yesNo'),
possibleValues => $self->session->form->process("possibleValues",'textarea'),
defaultValues => $self->session->form->process("defaultValues",'textarea'),
helpText => $self->session->form->process("helpText",'textarea'),
},1,1);
return $self->www_manageEventMetaFields();
}
@ -884,6 +1298,90 @@ sub www_exportEvents {
return "chunked";
}
#----------------------------------------------------------------------------
=head2 www_getAllSubmissions ( )
Get a page of Asset Manager data, ajax style. Returns a JSON array to be
formatted in a WebGUI submission queue data table.
=cut
sub www_getAllSubmissions {
my $self = shift;
my $session = $self->session;
my $datetime = $session->datetime;
my $form = $session->form;
my $tableInfo = {};
return $session->privilege->insufficient unless $self->canSubmit || $self->isRegistrationStaff;
my $orderByColumn = $form->get( 'orderByColumn' ) || $self->get("sortColumn");
my $dir = $form->get('orderByDirection') || $self->get('sortOrder');
my $orderByDirection = lc ($dir) eq "asc" ? "ASC" : "DESC";
my $whereClause ;
if(!$self->isRegistrationStaff) {
my $userId = $session->user->userId;
$whereClause .= qq{ createdBy='$userId'};
}
my $rules;
$rules->{'joinClass' } = "WebGUI::Asset::EMSSubmission";
$rules->{'whereClause' } = $whereClause;
$rules->{'includeOnlyClasses'} = ['WebGUI::Asset::EMSSubmission'];
$rules->{'orderByClause' } = $session->db->dbh->quote_identifier( $orderByColumn ) . ' ' . $orderByDirection if $orderByColumn;
my $sql = "";
$sql = $self->getLineageSql(['descendants'], $rules);
my $startIndex = $form->get( 'startIndex' ) || 1;
my $rowsPerPage = $form->get( 'rowsPerPage' ) || 25;
my $currentPage = int ( $startIndex / $rowsPerPage ) + 1;
my $p = WebGUI::Paginator->new( $session, '', $rowsPerPage, 'pn', $currentPage );
$p->setDataByQuery($sql);
$tableInfo->{'recordsReturned'} = $rowsPerPage;
$tableInfo->{'totalRecords' } = $p->getRowCount;
$tableInfo->{'startIndex' } = $startIndex;
$tableInfo->{'sort' } = $orderByColumn;
$tableInfo->{'dir' } = $orderByDirection;
$tableInfo->{'records' } = [];
for my $record ( @{ $p->getPageData } ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $record->{assetId} );
my $lastReplyBy = $asset->get("lastReplyBy");
if ($lastReplyBy) {
$lastReplyBy = WebGUI::User->new($session,$lastReplyBy)->username;
}
# Populate the required fields to fill in
my $lastReplyDate = $asset->get("lastReplyDate");
if($lastReplyDate) {
$lastReplyDate = $datetime->epochToHuman($lastReplyDate,"%y-%m-%d @ %H:%n %p");
}
my %fields = (
submissionId => $asset->get("submissionId"),
url => $asset->getQueueUrl,
title => $asset->get( "title" ),
createdBy => WebGUI::User->new($session,$asset->get( "createdBy" ))->username,
creationDate => $datetime->epochToSet($asset->get( "creationDate" )),
submissionStatus => $self->getSubmissionStatus($asset->get( "submissionStatus" ) || 'pending' ),
lastReplyDate => $lastReplyDate || '',
lastReplyBy => $lastReplyBy || '',
);
push @{ $tableInfo->{ records } }, \%fields;
}
$session->http->setMimeType( 'application/json' );
return JSON->new->encode( $tableInfo );
}
#-------------------------------------------------------------------
=head2 www_getBadgesAsJson ()
@ -922,6 +1420,36 @@ sub www_getBadgesAsJson {
#-------------------------------------------------------------------
=head2 www_getSubmissionById
returns a JSON dataset with info about the requested submission
=cut
sub www_getSubmissionById {
my $self = shift;
my $submissionId = $self->session->form->get('submissionId');
my $result;
my $res = $self->getLineage(['descendants'],{ limit => 1, returnObjects=>1,
includeOnlyClasses => ['WebGUI::Asset::EMSSubmission'],
joinClass => "WebGUI::Asset::EMSSubmission",
whereClause => q{submissionId='} . $submissionId . q/'/,
} );
if( scalar(@$res) == 0 ) {
$result->{hasError} = 1;
$result->{errors} = [ 'failed to load submission' ];
} else {
$result->{text} = $res->[0]->www_editSubmission;
$result->{title} = $submissionId;
$result->{id} = $submissionId;
}
$self->session->http->setMimeType('application/json');
return JSON->new->encode($result);
}
#-------------------------------------------------------------------
=head2 www_getRegistrantAsJson ( )
Retrieves the properties of a specific badge and the items attached to it. Expects badgeId to be one of the form params.
@ -1206,7 +1734,7 @@ sub www_getScheduleDataJSON {
and ( assetData.status = 'approved'
or assetData.tagId = ? )
)
order by EMSTicket.startDate
order by EMSTicket.startDate, eventNumber asc
},[ $self->getId, $currentDate,
$session->scratch->get("versionTag")
]);
@ -1214,8 +1742,10 @@ sub www_getScheduleDataJSON {
tie %hash, 'Tie::IxHash';
while( my $row = $tickets->hashRef ) {
$row->{type} = 'ticket';
$hash{$row->{startDate}}{$row->{location}} = $row;
$row->{location} = '&nbsp;' if $row->{location} eq '';
push @{$hash{$row->{startDate}}{$row->{location}}}, $row;
}
grep { $_ = '&nbsp;' if defined $_ && $_ eq '' } @ticketLocations;
my %results = ();
$results{records} = []; ##Initialize to an empty array
my $ctr = 0;
@ -1223,20 +1753,25 @@ sub www_getScheduleDataJSON {
# fill out the columns in the table
while( $ctr < $locationsPerPage ) { $locationMap{ 'col' . ++$ctr } = '' };
push @{$results{records}}, { colDate => '' , map { $_ , { type => 'label', title => $locationMap{$_} || '' } } ( keys %locationMap ) };
my $redo = 0;
for my $startDate ( keys %hash ) {
$redo = 0;
my $row = { colDate => $startDate };
my $empty = 1;
for my $col ( keys %locationMap ) {
my $location = $locationMap{$col};
if( exists $hash{$startDate}{$location} ) {
$row->{$col} = $hash{$startDate}{$location};
$row->{$col} = pop @{$hash{$startDate}{$location}};
$empty = 0;
$redo = 1 if scalar(@{$hash{$startDate}{$location}}) > 0;
delete $hash{$startDate}{$location} if scalar(@{$hash{$startDate}{$location}}) == 0;
} else {
$row->{$col} = { type => 'empty' };
}
}
next if $empty;
push @{$results{records}}, $row;
redo if $redo;
}
my $rowCount = scalar(@{$results{records}});
@ -1257,8 +1792,6 @@ sub www_getScheduleDataJSON {
return JSON->new->encode(\%results);
}
#-------------------------------------------------------------------
=head2 www_getTicketsAsJson ()
@ -1969,6 +2502,75 @@ sub www_printBadge {
#-------------------------------------------------------------------
=head2 www_printRemainingTickets ()
Displays all of the remaining tickets for this EMS
=cut
sub www_printRemainingTickets {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($self->isRegistrationStaff);
my $var = $self->get;
my $sth = $session->db->read(qq{
SELECT
asset.creationDate,
assetData.*,
assetData.title as ticketTitle,
EMSTicket.price,
EMSTicket.seatsAvailable,
EMSTicket.startDate as ticketStart,
EMSTicket.duration as ticketDuration,
EMSTicket.eventNumber as ticketEventNumber,
EMSTicket.location as ticketLocation,
EMSTicket.relatedBadgeGroups,
EMSTicket.relatedRibbons,
EMSTicket.eventMetaData,
(seatsAvailable - (select count(*) from EMSRegistrantTicket where ticketAssetId = asset.assetId)) as seatsRemaining
FROM
asset
join assetData using (assetId)
left join EMSTicket using (assetId)
WHERE
parentId=?
and className='WebGUI::Asset::Sku::EMSTicket'
and state='published'
and EMSTicket.revisionDate=(select max(revisionDate) from EMSTicket where assetId=asset.assetId)
and (seatsAvailable - (select count(*) from EMSRegistrantTicket where ticketAssetId = asset.assetId)) > 0
GROUP BY
asset.assetId
ORDER BY
title desc
},[$self->getId]);
$var->{'tickets_loop'} = [];
while (my $hash = $sth->hashRef) {
my $seatsRemaining = $hash->{seatsRemaining};
#Put start time in the correct timezone
my $startTime = WebGUI::DateTime->new($hash->{ticketStart})->set_time_zone($self->get('timezone'));
$hash->{ticketStart} = $startTime->strftime('%F %R');
$hash->{ticketStart_epoch} = $startTime->epoch;
#Add meta data fields
my $data = $hash->{eventMetaData} || '{}';
my $meta = JSON->new->decode($data);
foreach my $key (keys %{$meta}) {
my $tmplKey = $key;
$tmplKey =~ s/[\s\W]/_/g;
$hash->{'ticketMeta_'.$tmplKey} = $meta->{$key};
}
#Add to the loop
for (my $i = 0; $i < $seatsRemaining; $i++ ) {
push(@{$var->{'tickets_loop'}},$hash);
}
}
return $self->processTemplate($var,$self->get('printRemainingTicketsTemplateId'));
}
#-------------------------------------------------------------------
=head2 www_printTicket ( )
Prints a ticket using a template.
@ -2049,7 +2651,7 @@ Toggles the registrant checked in flag.
sub www_toggleRegistrantCheckedIn {
my $self = shift;
return $self->session->privilege->insfufficient() unless ($self->isRegistrationStaff);
return $self->session->privilege->insufficient() unless ($self->isRegistrationStaff);
my $db = $self->session->db;
my $badgeId = $self->session->form->param('badgeId');
my $flag = $db->quickScalar("select hasCheckedIn from EMSRegistrant where badgeId=?",[$badgeId]);
@ -2058,7 +2660,6 @@ sub www_toggleRegistrantCheckedIn {
return $self->www_manageRegistrant;
}
#-------------------------------------------------------------------
=head2 www_viewSchedule ()
@ -2070,7 +2671,6 @@ View the schedule table.
sub www_viewSchedule {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canView;
my $db = $self->session->db;
my $rowsPerPage = 25;
my $locationsPerPage = $self->scheduleColumnsPerPage;
@ -2091,5 +2691,80 @@ sub www_viewSchedule {
}
#---------------------------------------------
=head2 www_viewSubmissionQueue
=cut
sub www_viewSubmissionQueue {
my $self = shift;
my $isRegistrationStaff = $self->isRegistrationStaff;
my $canSubmit = $self->canSubmit && ! $isRegistrationStaff;
my $canEdit = $self->canEdit;
my $i18n = $self->i18n;
return $self->session->privilege->insufficient() unless $canSubmit || $isRegistrationStaff;
# this map returns an array of hash refs with an id,url pair to describe the submissionForm assets
my @submissionFormUrls = map { { # edit form
id => $_->getId,
edit => 1,
title => $_->get('title'),
linkUrl => $self->getUrl('func=viewSubmissionQueue#' . $_->getId ),
ajaxUrl => $_->getUrl('func=editSubmissionForm'),
},{ # new submission ( _new has to match same in sub www_addSubmission in this module
id => $_->getId . '_new',
title => $_->get('title') . ' - ' . $i18n->get('add submission'),
linkUrl => $self->getUrl('func=viewSubmissionQueue#' . $_->getId . '_new' ),
ajaxUrl => $_->getUrl('func=addSubmission'),
} } (
@{$self->getSubmissionForms}
);
my $params = {
backUrl => $self->getUrl,
isRegistrationStaff => $isRegistrationStaff,
canEdit => $canEdit,
canSubmit => $canSubmit,
hasSubmissionForms => $self->hasSubmissionForms,
getSubmissionQueueDataUrl => $self->getUrl('func=getAllSubmissions'),
editSubmissionUrl => $self->getUrl('func=viewSubmissionQueue#editSubmission'),
editSubmissionFormUrl => $self->getUrl('func=viewSubmissionQueue#editSubmissionForm'),
addSubmissionFormUrl => $self->getUrl('func=viewSubmissionQueue#addSubmissionForm'),
addSubmissionUrl => $self->getUrl('func=viewSubmissionQueue#addSubmission'),
editSubmissionAjaxUrl => $self->getUrl('func=editSubmission'),
editSubmissionFormAjaxUrl => $self->getUrl('func=editSubmissionForm'),
addSubmissionFormAjaxUrl => $self->getUrl('func=addSubmissionForm'),
addSubmissionAjaxUrl => $self->getUrl('func=addSubmission'),
submissionFormUrls => \@submissionFormUrls,
};
push( @{$params->{tabs}}, {
title => $isRegistrationStaff ? $i18n->get('submission queue') : $i18n->get('my submissions'),
text => $self->processTemplate($params,$self->get('eventSubmissionQueueTemplateId')),
} );
if( $isRegistrationStaff ) {
for my $tabSource ( @{$self->getSubmissionForms} ) {
push @{$params->{tabs}}, $tabSource->www_editSubmissionForm( { asHashRef => 1 } );
}
push @{$params->{tabs}}, $self->www_addSubmissionForm( { asHashRef => 1 } );
if( scalar( @{$params->{tabs}} ) == 2 ) { # there were no existing forms
$params->{tabs}[1]{selected} = 1; # the new submission form tab
} else {
$params->{tabs}[0]{selected} = 1; # the submission queue tab
}
}
elsif( $canSubmit ) {
for my $tabSource ( @{$self->getSubmissionForms} ) {
next unless $tabSource->canSubmit;
push @{$params->{tabs}}, $tabSource->www_addSubmission( { asHashRef => 1 } );
}
$params->{tabs}[0]{selected} = 1;
}
my $tabid = 'tab01';
for my $tab ( @{$params->{tabs}} ) { $tab->{id} = $tabid ++; }
return $self->processStyle(
$self->processTemplate( $params, $self->get('eventSubmissionMainTemplateId')));
}
1;

View file

@ -758,11 +758,12 @@ sub getRssFeedItems {
perpage => $self->itemsPerFeed,
} );
my $var = [];
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' => $asset->getUrl,
'link' => $siteUrl . $asset->getUrl,
'guid' => $asset->{_properties}->{ 'assetId' },
'title' => $asset->getTitle,
'description' => $asset->{_properties}->{ 'description' },

View file

@ -47,8 +47,10 @@ use Carp qw( croak );
use File::Find;
use File::Spec;
use File::Temp qw{ tempdir };
use JSON ();
use WebGUI::International;
use WebGUI::HTML;
use WebGUI::ProgressBar;
use Archive::Any;
@ -61,10 +63,11 @@ use Archive::Any;
=head1 DIAGNOSTICS
=head1 METHODS
=cut
#----------------------------------------------------------------------------
=head2 addArchive ( filename, properties )
=head2 addArchive ( filename, properties, [$outputSub] )
Add an archive of Files to this Album. C<filename> is the full path of the
archive. C<properties> is a hash reference of properties to assign to the
@ -75,13 +78,29 @@ a directory outside of the storage location.
Will only handle file types handled by the parent Gallery.
=head3 filename
The name of the file archive to import.
=head3 properties
A base set of properties to add to each file in the archive.
=head3 $outputSub
A callback to use for outputting data, most likely to a progress bar. It expects the
callback to accept an i18n key for use in sprintf, and then any extra fields to stuff
into the translated key.
=cut
sub addArchive {
my $self = shift;
my $filename = shift;
my $properties = shift;
my $outputSub = shift || sub {};
my $gallery = $self->getParent;
my $session = $self->session;
my $archive = Archive::Any->new( $filename );
@ -89,11 +108,12 @@ sub addArchive {
if $archive->is_naughty;
my $tempdirName = tempdir( "WebGUI-Gallery-XXXXXXXX", TMPDIR => 1, CLEANUP => 1);
$outputSub->('Extracting archive');
$archive->extract( $tempdirName );
# Get all the files in the archive
my @files;
my $wanted = sub { push @files, $File::Find::name };
my $wanted = sub { push @files, $File::Find::name; $outputSub->('Found file: %s', $File::Find::name); };
find( {
wanted => $wanted,
}, $tempdirName );
@ -106,23 +126,26 @@ sub addArchive {
my $class = $gallery->getAssetClassForFile( $filePath );
next unless $class; # class is undef for those files the Gallery can't handle
$self->session->errorHandler->info( "Adding $filename to album!" );
# Remove the file extention
$session->errorHandler->info( "Adding $filename to album!" );
$outputSub->('Adding %s to album', $filename);
# Remove the file extension
$filename =~ s{\.[^.]+}{};
$properties->{ className } = $class;
$properties->{ menuTitle } = $filename;
$properties->{ title } = $filename;
$properties->{ url } = $self->session->url->urlize( $self->getUrl . "/" . $filename );
$properties->{ ownerUserId } = $session->user->userId;
$properties->{ url } = $session->url->urlize( $self->getUrl . "/" . $filename );
my $asset = $self->addChild( $properties, undef, undef, { skipAutoCommitWorkflows => 1 } );
$asset->setFile( $filePath );
}
my $versionTag = WebGUI::VersionTag->getWorking( $self->session );
my $versionTag = WebGUI::VersionTag->getWorking( $session );
$versionTag->set({
"workflowId" => $self->getParent->workflowIdCommit,
});
$outputSub->('Requesting commit for version tag');
$versionTag->requestCommit;
return undef;
@ -236,16 +259,12 @@ sub canEdit {
my $form = $self->session->form;
# Handle adding a photo
if ( $form->get("func") eq "add" ) {
return $self->canAddFile;
}
elsif ( $form->get("func") eq "editSave" && $form->get("className") eq __PACKAGE__ ) {
if ( $form->get("func") eq "add" || $form->get("func") eq "editSave" ) {
return $self->canAddFile;
}
else {
return 1 if $userId eq $self->ownerUserId;
return $gallery->canEdit($userId);
return $gallery && $gallery->canEdit($userId);
}
}
@ -394,6 +413,58 @@ sub getFileIds {
#----------------------------------------------------------------------------
=head2 getNextFileId ( fileId )
Gets the next fileId from the list of fileIds. C<fileId> is the base
fileId we want to find the next file for.
Returns C<undef> if there is no next fileId.
=cut
sub getNextFileId {
my $self = shift;
my $fileId = shift;
my $allFileIds = $self->getFileIds;
while ( my $checkId = shift @{ $allFileIds } ) {
# If this is the last albumId
return undef unless @{ $allFileIds };
if ( $fileId eq $checkId ) {
return shift @{ $allFileIds };
}
}
}
#----------------------------------------------------------------------------
=head2 getPreviousFileId ( fileId )
Gets the previous fileId from the list of fileIds. C<fileId> is the base
fileId we want to find the previous file for.
Returns C<undef> if there is no previous fileId.
=cut
sub getPreviousFileId {
my $self = shift;
my $fileId = shift;
my $allFileIds = $self->getFileIds;
while ( my $checkId = pop @{ $allFileIds } ) {
# If this is the last albumId
return undef unless @{ $allFileIds };
if ( $fileId eq $checkId ) {
return pop @{ $allFileIds };
}
}
}
#----------------------------------------------------------------------------
=head2 getFilePaginator ( paginatorUrl )
Gets a WebGUI::Paginator for the files in this album. C<paginatorUrl> is the
@ -854,7 +925,7 @@ sub www_addArchive {
my $i18n = WebGUI::International->new($session);
$var->{ error } = $params->{ error };
$var->{ error } = $params->{ error } || $form->get('error');
$var->{ form_start }
= WebGUI::Form::formHeader( $session, {
@ -909,32 +980,27 @@ sub www_addArchiveSave {
my $session = $self->session;
my $form = $self->session->form;
my $i18n = WebGUI::International->new( $session, 'Asset_GalleryAlbum' );
my $pb = WebGUI::ProgressBar->new($session);
my $properties = {
keywords => $form->get("keywords"),
friendsOnly => $form->get("friendsOnly"),
};
$pb->start($i18n->get('Uploading archive'), $session->url->extras('adminConsole/assets.gif'));
my $storageId = $form->get("archive", "File");
my $storage = WebGUI::Storage->get( $session, $storageId );
if (!$storage) {
return $self->www_addArchive({
error => sprintf $i18n->get('addArchive error too big'),
});
return $pb->finish($self->getUrl('func=addArchive;error='.$i18n->get('addArchive error too big')));
}
my $filename = $storage->getPath( $storage->getFiles->[0] );
eval { $self->addArchive( $filename, $properties ) };
eval { $self->addArchive( $filename, $properties, sub{ $pb->update(sprintf $i18n->get(shift), @_); }); };
$storage->delete;
if ( my $error = $@ ) {
return $self->www_addArchive({
error => sprintf( $i18n->get('addArchive error generic'), $error ),
});
return $pb->finish($self->getUrl('func=addArchive;error='.sprintf $i18n->get('addArchive error generic'), $error ));
}
$storage->delete;
return $self->processStyle(
sprintf $i18n->get('addArchive message'), $self->getUrl,
);
return $pb->finish($self->getUrl);
}
#----------------------------------------------------------------------------
@ -1076,6 +1142,172 @@ sub www_deleteConfirm {
#----------------------------------------------------------------------------
=head2 www_ajax ( )
Generic AJAX service for gallery.
Arguments are accepted in JSON format in the form variable C<args>. The single
obligatory argument is C<action> determining the service to be called. A list
of available services is given in the following. Additional arguments may be
required depending on the service.
Results are returned in JSON format. The information returned depends on the
service called. Generally, success is indicated by a value of 0 in C<err>.
=head3 moveFile
Service for changing the rank of files. Accepts the asset Id of the photo to be moved
in C<target>. The asset Id of the photo to be replaced is specified in C<before>
or C<after> depending on the desired order. Returns -1 in C<err> and an error
message in C<errMessage> if moving of the photo failed.
=cut
sub www_ajax {
my $self = shift;
my $session = $self->session;
my $form = $self->session->form;
my $result;
# Get arguments encoded in json format
my $args = decode_json($form->get("args"));
# Log some debug information
$session->log->debug("Ajax service called with args=" . $form->get("args"));
# Process requests depending on action argument
SWITCH: {
# Return if no action was specified
if ( $args->{action} eq '' ) {
$session->log->error("Call of ajax service without action argument.");
$result->{ errMessage } = "Action argument is missing.";
last;
}
# ----- Move file action -----
$args->{action} eq 'moveFile' && do { $result = $self->_moveFileAjaxRequest( $args ); last; };
# ----- Unkown action -----
$session->log->error("Call of ajax service with unknown action '" . $args->{action} . "'.");
$result->{ errMessage } = "Action '" . $args->{action} ."' is unknown.";
}
# Set error flag if error message exists
$result->{ err } = -1 if $result->{ errMessage };
# Return results encoded in json format
return encode_json( $result );
}
#----------------------------------------------------------------------------
=head2 _moveFileAjaxRequest ( args )
AJAX service for changing the rank of single files. Returns a hash ref with
error information. Arguments passed to the ajax service are provided via the
hash ref C<args>. Note that this is a private function owned by www_ajax. It
should not be used directly.
=cut
sub _moveFileAjaxRequest {
my $self = shift;
my $args = shift;
my $session = $self->session;
my %result;
# Return if current user is not allowed to edit this album
unless ( $self->canEdit ) {
$session->log->error("Call of moveFile action without having edit permission.");
$result{ errMessage } = "You do not have permission to move files.";
return \%result;
}
# Return if no target was specified
if ( $args->{target} eq '') {
$session->log->error("Call of moveFile action without target argument.");
$result{ errMessage } = "Target argument is missing.";
return \%result;
}
# Return if before or after argument is missing
unless( $args->{before} or $args->{after} ) {
$session->log->error("Call of moveFile action without before/after argument.");
$result{ errMessage } = "Before/after argument is missing.";
return \%result;
}
# Return if before and after arguments were specified
unless( $args->{before} xor $args->{after} ) {
$session->log->error("Call of moveFile action with before *and* after argument.");
$result{ errMessage } = "Both, before and after arguments were specified.";
return \%result;
}
# Get Id of target photo and instantiate asset
my $targetId = $args->{target};
my $target = WebGUI::Asset->newByDynamicClass( $session, $targetId );
# Return if target photo could not be instantiated
unless ( $target ) {
$session->log->error("Couldn't move file '$targetId' because we couldn't instantiate it.");
$result{ errMessage } = "ID of target file seems to be invalid.";
return \%result;
}
# Return if target is not a child of the current album
unless ( $target->getParent->getId eq $self->getId ) {
$session->log->error("Couldn't move file '$targetId' because it is not a child of this album.");
$result{ errMessage } = "ID of target file seems to be invalid.";
return \%result;
}
my ($destId, $dest);
# Instantiate file with ID in before/after argument
$destId = $args->{before} ? $args->{before} : $args->{after};
$dest = WebGUI::Asset->newByDynamicClass( $session, $destId );
# Return if destination file could not be instantiated
unless ( $dest ) {
$session->log->error("Couldn't move file '$targetId' before/after file '$destId' because we couldn't instantiate the latter.");
$result{ errMessage } = "ID in before/after argument seems to be invalid.";
return \%result;
}
# Return if destination file is not a child of the current album
unless ( $dest->getParent->getId eq $self->getId ) {
$session->log->error("Couldn't move file '$targetId' before/after file '$destId' because the latter is not a child of the same album.");
$result{ errMessage } = "ID in before/after argument seems to be invalid.";
return \%result;
}
# Check for use of after argument when lowering the rank
if ( $args->{after} && $target->getRank() > $dest->getRank() ) {
# Get ID of next sibling
$destId = $self->getNextFileId( $destId );
# Instantiate next sibling
$dest = WebGUI::Asset->newByDynamicClass( $session, $destId );
}
# Check for use of before argument when increasing the rank
if ( $args->{before} && $target->getRank() < $dest->getRank() ) {
# Get ID of previous sibling
$destId = $self->getPreviousFileId( $destId );
# Instantiate previous sibling
$dest = WebGUI::Asset->newByDynamicClass( $session, $destId );
}
# Update rank of target photo
$target->setRank( $dest->getRank );
# Log some debug information
$session->log->debug("Successfully moved file '$targetId' before/after file '$destId'.");
# Return reporting success
$result{ err } = 0;
return \%result;
}
#----------------------------------------------------------------------------
=head2 www_edit ( )
Show the form to add / edit a GalleryAlbum asset.

View file

@ -408,11 +408,11 @@ sub www_setStatus {
$db->write("delete from InOutBoard_status where userId=? and assetId=?", [ $sessionUserId, $self->getId ]);
$db->write(
"insert into InOutBoard_status (assetId,userId,status,dateStamp,message) values (?,?,?,?,?)",
[$self->getId, $sessionUserId, $status, $session->datetime->time(), $message ],
[$self->getId, $sessionUserId, $status, time(), $message ],
);
$db->write(
"insert into InOutBoard_statusLog (assetId,userId,createdBy,status,dateStamp,message) values (?,?,?,?,?,?)",
[$self->getId, $sessionUserId, $session->user->userId, $status, $session->datetime->time(), $message ],
[$self->getId, $sessionUserId, $session->user->userId, $status, time(), $message ],
);
}
else {
@ -446,7 +446,7 @@ sub www_viewReport {
-name=>"doit",
-value=>"1"
);
my $startDate = $self->session->datetime->addToDate($self->session->datetime->time(),0,0,-15);
my $startDate = $self->session->datetime->addToDate(time(),0,0,-15);
$startDate = $self->session->form->date("startDate") if ($self->session->form->process("doit"));
$f->date(
-name=>"startDate",

View file

@ -37,6 +37,8 @@ property mobileTemplateId => (
fieldType => 'template',
namespace => 'Layout',
default => 'PBtmpl0000000000000054',
label => ['mobileTemplateId label', 'Asset_Layout'],
hoverHelp => ['mobileTemplateId description', 'Asset_Layout'],
noFormPost => 1,
);
property contentPositions => (
@ -53,6 +55,8 @@ property assetsToHide => (
property assetOrder => (
default => 'asc',
fieldType => 'selectBox',
label => ['asset order label', 'Asset_Layout'],
hoverHelp => ['asset order hoverHelp', 'Asset_Layout'],
noFormPost => 1,
);
@ -97,66 +101,88 @@ override getEditForm => sub {
else {
$templateId = $self->templateId;
}
$tabform->getTab("display")->template(
-value=>$templateId,
-label=>$i18n->get('layout template title'),
-hoverHelp=>$i18n->get('template description'),
-namespace=>"Layout"
);
tie my %extraFields, "Tie::IxHash";
%extraFields = (
templateId => {
fieldType => 'template',
tab => 'display',
value => $templateId,
label => $i18n->get('layout template title'),
hoverHelp => $i18n->get('template description'),
namespace => "Layout",
});
if ( $self->session->setting->get('useMobileStyle') ) {
$tabform->getTab("display")->template(
name => 'mobileTemplateId',
value => $self->mobileTemplateId,
label => $i18n->get('mobileTemplateId label'),
hoverHelp => $i18n->get('mobileTemplateId description'),
namespace => 'Layout',
);
$extraFields{mobileTemplateId} = {
fieldType => 'template',
tab => 'display',
name => 'mobileTemplateId',
value => $self->mobileTemplateId,
label => $i18n->get('mobileTemplateId label'),
hoverHelp => $i18n->get('mobileTemplateId description'),
namespace => 'Layout',
};
}
else {
$tabform->getTab("display")->hidden(
$extraFields{mobileTemplateId} = {
fieldType => 'hidden',
tab => 'display',
name => 'mobileTemplateId',
value => $self->mobileTemplateId,
);
};
}
tie my %assetOrder, "Tie::IxHash";
%assetOrder = (
"asc" =>$i18n->get("asset order asc"),
"desc" =>$i18n->get("asset order desc"),
);
$tabform->getTab("display")->selectBox(
-name => 'assetOrder',
-label => $i18n->get('asset order label'),
-hoverHelp => $i18n->get('asset order hoverHelp'),
-value => $self->assetOrder,
-options => \%assetOrder
"asc" => $i18n->get("asset order asc"),
"desc" => $i18n->get("asset order desc"),
);
$extraFields{assetOrder} = {
tab => 'display',
fieldType => 'selectBox',
name => 'assetOrder',
label => $i18n->get('asset order label'),
hoverHelp => $i18n->get('asset order hoverHelp'),
value => $self->assetOrder,
options => \%assetOrder,
};
if ($self->get("assetId") eq "new") {
$tabform->getTab("properties")->whatNext(
-options=>{
view=>$i18n->get(823),
viewParent=>$i18n->get(847)
},
-value=>"view"
);
} else {
$extraFields{whatNext} = {
fieldType => 'whatNext',
value => "view",
options => {
view => $i18n->get(823),
viewParent => $i18n->get(847)
},
};
}
else {
my @assetsToHide = split("\n",$self->assetsToHide);
my $children = $self->getLineage(["children"],{"returnObjects"=>1, excludeClasses=>["WebGUI::Asset::Wobject::Layout"]});
my %childIds;
foreach my $child (@{$children}) {
$childIds{$child->getId} = $child->getTitle;
}
$tabform->getTab("display")->checkList(
-name=>"assetsToHide",
-value=>\@assetsToHide,
-options=>\%childIds,
-label=>$i18n->get('assets to hide'),
-hoverHelp=>$i18n->get('assets to hide description'),
-vertical=>1,
-uiLevel=>9
);
$extraFields{assetsToHide} = {
fieldType => 'checkList',
tab => 'display',
name => "assetsToHide",
value => \@assetsToHide,
options => \%childIds,
label => $i18n->get('assets to hide'),
hoverHelp => $i18n->get('assets to hide description'),
vertical => 1,
uiLevel => 9,
};
}
my $overrides = $self->session->config->get("assets/".$self->get("className"));
foreach my $fieldName (keys %extraFields) {
$self->setupFormField($tabform, $fieldName, \%extraFields, $overrides);
}
return $tabform;
};
@ -391,17 +417,14 @@ override www_view => sub {
) {
my $check = $self->checkView;
return $check if (defined $check);
my $cacheKey = "view_".$self->getId;
if ($session->env->sslRequest) {
$cacheKey .= '_ssl';
}
my $cacheKey = $self->getWwwCacheKey('view');
my $cache = $session->cache;
my $out = eval{$cache->get($cacheKey)};
my $out = eval{ $cache->get($cacheKey) };
unless ($out) {
$self->prepareView;
$session->stow->set("cacheFixOverride", 1);
$out = $self->processStyle($self->view, { noHeadTags => 1 });
eval{$cache->set($cacheKey, $out, 60)};
eval{ $cache->set($cacheKey, $out, 60) };
$session->stow->delete("cacheFixOverride");
}
# keep those ads rotating even though the output is cached

View file

@ -90,6 +90,7 @@ property templateIdEditPoint => (
tab => "display",
fieldType => "template",
namespace => "MapPoint/Edit",
default => 'oHh0UqAJeY7u2n--WD-BAA',
label => ["templateIdEditPoint label", 'Asset_Map'],
hoverHelp => ["templateIdEditPoint description", 'Asset_Map'],
);
@ -97,6 +98,7 @@ property templateIdView => (
tab => "display",
fieldType => "template",
namespace => "Map/View",
default => '9j0_Z1j3Jd0QBbY2akb6qw',
label => ["templateIdView label", 'Asset_Map'],
hoverHelp => ["templateIdView description", 'Asset_Map'],
);
@ -104,6 +106,7 @@ property templateIdViewPoint => (
tab => "display",
fieldType => "template",
namespace => "MapPoint/View",
default => 'u9vfx33XDk5la1-QC5FK7g',
label => ["templateIdViewPoint label", 'Asset_Map'],
hoverHelp => ["templateIdViewPoint description", 'Asset_Map'],
);
@ -291,6 +294,8 @@ sub loadMapApiTags {
my $style = $self->session->style;
my $url = $self->session->url;
$style->setLink($url->extras('yui/build/container/assets/skins/sam/container.css'),{type=>'text/css',rel=>'stylesheet'});
$style->setLink($url->extras('yui/build/button/assets/skins/sam/button.css'),{type=>'text/css',rel=>'stylesheet'});
$style->setScript("http://www.google.com/jsapi?key=" . $self->mapApiKey,{type=>"text/javascript"});
$style->setRawHeadTags(<<'ENDHTML');
<script type="text/javascript">
@ -300,6 +305,10 @@ ENDHTML
$style->setScript('http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/src/markermanager.js', {type=>"text/javascript"});
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/connection/connection-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/element/element-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/button/button-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/container/container-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui/build/json/json-min.js'),{type=>'text/javascript'});
$style->setScript($url->extras('yui-webgui/build/map/map.js'),{type=>'text/javascript'});
@ -355,14 +364,17 @@ sub view {
;
# The script to load the map into the container
$mapHtml .= sprintf <<'ENDHTML', $self->getId, $self->getUrl, $self->startLatitude, $self->startLongitude, $self->startZoom;
$mapHtml .= sprintf <<'ENDHTML', $self->getId, $self->getUrl, $self->startLatitude, $self->startLongitude, $self->startZoom, $session->url->extras;
<script type="text/javascript">
google.setOnLoadCallback( function() {
var mapId = "%s";
var mapUrl = "%s";
var map = new GMap2( document.getElementById("map_" + mapId) );
map.url = mapUrl;
map.assetId = mapId;
map.setCenter(new GLatLng(%s, %s), %s);
map.setUIToDefault();
map.extrasUrl = "%s";
var markermanager = new MarkerManager(map, {trackMarkers: true});
ENDHTML
@ -386,7 +398,7 @@ ENDHTML
}
$mapHtml .= <<'ENDHTML';
markermanager.addMarkers( WebGUI.Map.preparePoints(map, markermanager, mapUrl, points), 1 );
markermanager.addMarkers( WebGUI.Map.preparePoints(map, markermanager, points), 0 );
ENDHTML
}
@ -406,13 +418,13 @@ ENDHTML
if ( document.getElementById( "setCenter_" + mapId ) ) {
var button = document.getElementById( "setCenter_" + mapId );
GEvent.addDomListener( button, "click", function () {
WebGUI.Map.setCenter( map, mapUrl );
WebGUI.Map.setCenter( map );
} );
}
if ( document.getElementById( "addPoint_" + mapId ) ) {
var button = document.getElementById( "addPoint_" + mapId );
GEvent.addDomListener( button, "click", function () {
WebGUI.Map.editPoint( map, markermanager, mapUrl );
WebGUI.Map.editPoint( map, markermanager );
} );
}
});
@ -435,6 +447,22 @@ ENDHTML
id => sprintf( 'setCenter_%s', $self->getId ),
} );
# Select box to choose a map point
tie my %selectPointOptions, 'Tie::IxHash', (
"" => '-- ' . $i18n->get('select a point'),
);
if ( $var->{mapPoints} ) {
for my $point ( sort { $a->{title} cmp $b->{title} } @{$var->{mapPoints}} ) {
$selectPointOptions{ $point->{assetId} } = $point->{title};
}
}
$var->{ selectPoint }
= WebGUI::Form::selectBox( $session, {
extras => q{onchange="WebGUI.Map.focusOn(this.options[this.selectedIndex].value);"},
id => sprintf( q{selectPoint_%s}, $self->getId ),
options => \%selectPointOptions,
} );
return $self->processTemplate( $var, undef, $self->{_viewTemplate} );
}
@ -528,8 +556,19 @@ sub www_ajaxEditPointSave {
my $errors = $asset->processAjaxEditForm;
# Commit!
if ($asset->getAutoCommitWorkflowId && $self->hasBeenCommitted) {
$asset->requestAutoCommit;
if ( $asset->getAutoCommitWorkflowId ) {
if ( $self->hasBeenCommitted) {
$asset->requestAutoCommit;
}
else {
# Add mappoint to map's version tag
my $oldTagId = $asset->get('tagId');
$asset->setVersionTag( $self->get('tagId') );
my $oldTag = WebGUI::VersionTag->new( $session, $oldTagId );
if ( $oldTag->getAssetCount <= 0 ) {
$oldTag->rollback;
}
}
}
# Encode entities because we're returning as HTML

View file

@ -595,20 +595,14 @@ sub view {
$style->setLink($url->extras('yui/build/datatable/assets/skins/sam/datatable.css'),
{type =>'text/css', rel=>'stylesheet'});
$style->setScript($url->extras('yui/build/utilities/utilities.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/json/json-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datasource/datasource-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/button/button-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/utilities/utilities.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/json/json-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datasource/datasource-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/button/button-min.js'), {type => 'text/javascript'});
my ($varStatistics,$varStatisticsEncoded);
my $var = $self->get;
$var->{listing_loop} = $self->getListings;
$var->{isLoggedIn} = ($session->user->userId ne "1");
$var->{addMatrixListing_url} = $self->getUrl('func=add;class=WebGUI::Asset::MatrixListing');
$var->{exportAttributes_url} = $self->getUrl('func=exportAttributes');
@ -729,7 +723,7 @@ sub view {
push (@{ $varStatistics->{last_updated_loop} }, {
url => $lastUpdatedListing->getUrl,
name => $lastUpdatedListing->title,
lastUpdated => $self->session->datetime->epochToHuman($lastUpdatedListing->lastUpdated,"%z")
lastUpdated => $session->datetime->epochToHuman($lastUpdatedListing->lastUpdated,"%z")
});
}
$varStatistics->{lastUpdated_sortButton} = "<span id='sortByUpdated'><button type='button'>"
@ -757,6 +751,7 @@ sub view {
rating.category =?
and asset.parentId=?
and asset.state='published'
and rating.countValue >= 10
and assetData.revisionDate=(
select
max(revisionDate)
@ -772,21 +767,21 @@ sub view {
$data = $db->quickHashRef($sql." desc limit 1",[$category,$self->getId]);
push(@{ $varStatistics->{best_rating_loop} },{
url=>'/'.$data->{url},
category=>$category,
name=>$data->{productName},
mean=>$data->{meanValue},
median=>$data->{medianValue},
count=>$data->{countValue}
url => $session->url->gateway($data->{url}),
category => $category,
name => $data->{productName},
mean => 0+$data->{meanValue},
median => 0+$data->{medianValue},
count => 0+$data->{countValue}
});
$data = $db->quickHashRef($sql." asc limit 1",[$category,$self->getId]);
push(@{ $varStatistics->{worst_rating_loop} },{
url=>'/'.$data->{url},
category=>$category,
name=>$data->{productName},
mean=>$data->{meanValue},
median=>$data->{medianValue},
count=>$data->{countValue}
url => $session->url->gateway($data->{url}),
category => $category,
name => $data->{productName},
mean => 0+$data->{meanValue},
median => 0+$data->{medianValue},
count => 0+$data->{countValue}
});
}
@ -1156,34 +1151,35 @@ sub www_getCompareFormData {
if($form->process("search")) {
if ($searchParamList) {
RESULT: foreach my $result (@{$self->getListings}) {
my $checked = '';
my $matrixListing_attributes = $session->db->buildHashRefOfHashRefs("
select value, fieldType, attributeId from Matrix_attribute
left join MatrixListing_attribute as listing using(attributeId)
where listing.matrixListingId = ?
and attributeId IN(".$searchParamList.")",
[$result->{assetId}],'attributeId');
##Searching is AND based.
PARAM: foreach my $param (@searchParams_sorted) {
my $fieldType = $matrixListing_attributes->{$param->{attributeId}}->{fieldType};
my $listingValue = $matrixListing_attributes->{$param->{attributeId}}->{value};
if(($fieldType eq 'MatrixCompare') && ($listingValue < $param->{value})){
$result->{checked} = '';
$checked = '';
last PARAM;
}
elsif(($fieldType ne 'MatrixCompare' && $fieldType ne '') && ($param->{value} ne $listingValue)){
$result->{checked} = '';
$checked = '';
last PARAM;
}
else{
$result->{checked} = 'checked';
$checked = 'checked';
}
}
$result->{assetId} =~ s/-/_____/g;
push @results, $result if $result->{checked} eq 'checked';
push @results, $result if $checked eq 'checked';
}
}
else {
foreach my $result (@{$self->getListings}) {
$result->{checked} = 'checked';
$result->{assetId} =~ s/-/_____/g;
push @results, $result;
}
@ -1353,7 +1349,7 @@ sub www_listAttributes {
=head2 www_search ( )
Returns the search screen.
Returns the search screen. Uses www_getCompareFormData with search=1 for doing AJAX requests.
=cut

View file

@ -98,8 +98,9 @@ to be displayed within the page style
sub view {
my $self = shift;
my $cache = $self->session->cache;
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
my $out = eval{$cache->get("view_".$self->getId)};
my $cacheKey = $self->getWwwCacheKey( 'view' );
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
my $out = eval { $cache->get( $cacheKey ) };
return $out if $out;
}
my $i18n = WebGUI::International->new($self->session, 'Asset_MultiSearch');
@ -111,10 +112,10 @@ sub view {
$var{'submit'} = WebGUI::Form::Submit->new($self->session, {name=>'SearchSubmit',value=>$i18n->get('submit','WebGUI')})->toHtml();
my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate});
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
eval{$cache->set("view_".$self->getId, $out, $self->cacheTimeout)};
}
return $out;
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
eval { $cache->set( $cacheKey, $out, $self->cacheTimeout) };
}
return $out;
}
#-------------------------------------------------------------------

View file

@ -278,20 +278,6 @@ override getEditForm => sub {
".($ancestorsChecked ? "" : "toggleAncestorEndPoint();")."
//]]>
</script>");
my $previewButton;# = qq{
# <INPUT TYPE="button" VALUE="Preview" NAME="preview"
# OnClick="
# window.open('', 'navPreview', 'toolbar=no,status=no,location=no,scrollbars=yes,resizable=yes');
# this.form.func.value='preview';
# this.form.target = 'navPreview';
# this.form.submit()">};
my $saveButton = ' <input type="button" class="forwardButton" value="'.$i18n->get(62,'WebGUI').'" onclick="
this.value=\''.$i18n->get(452,'WebGUI').'\';
this.form.func.value=\'editSave\';
this.form.target=\'_self\';
this.form.submit();
" />';
$tabform->{_submit} = $previewButton." ".$saveButton;
return $tabform;
};

View file

@ -316,6 +316,11 @@ override getEditForm => sub {
### Download
# Download Type
my %downloadTypes;
tie %downloadTypes, 'Tie::IxHash',
"none" => $i18n->get("No Download"),
"csv" => $i18n->get("CSV"),
"template" => $i18n->get("Template"),
;
$tabform->getTab("properties")->radioList(
-name=>"downloadType", # ID is downloadType_formId
@ -508,7 +513,9 @@ sub download {
}
elsif ($self->downloadType eq "template") {
my $data = $self->_processQuery(1,0);
return $self->processTemplate($data,$self->downloadTemplateId);
my $output = $self->processTemplate($data,$self->downloadTemplateId);
WebGUI::Macro::process($self->session, \$output);
return $output;
}
else {
# I don't know what to do
@ -568,8 +575,9 @@ if the user is not in Admin Mode.
sub view {
my $self = shift;
my $cache = $self->session->cache;
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
my $out = eval{$cache->get("view_".$self->getId)};
my $cacheKey = $self->getWwwCacheKey( 'view' );
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
my $out = eval{ $cache->get( $cacheKey ) };
return $out if $out;
}
# Initiate an empty debug loop
@ -594,10 +602,10 @@ sub view {
}
my $out = $self->processTemplate($var,undef,$self->{_viewTemplate});
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
eval{$cache->set("view_".$self->getId, $out, $self->cacheTimeout)};
}
return $out;
if (!$self->session->var->isAdminOn && $self->cacheTimeout > 10) {
eval { $cache->set( $cacheKey, $out, $self->cacheTimeout ) };
}
return $out;
}
#-------------------------------------------------------------------
@ -681,14 +689,15 @@ sub _processQuery {
$page = 1 unless defined $page;
my $nr = shift || 1;
my ($query, %var, $prefix);
my $i18n = WebGUI::International->new($self->session,"Asset_SQLReport");
if($nr > 1) {
$prefix = 'query'.$nr.'.';
}
if (! $self->{_query}{$nr}{dbQuery}) {
if (! $self->{_query}{$nr}{dbQuery} || $self->{_query}{$nr}{dbQuery} =~ m{\A \s* \Z}msx) {
$self->session->errorHandler->warn("No query specified for query $nr on '" . $self->getId . "'");
push @{$self->{_debug_loop}}, { 'debug.output' => "No query specfied for query $nr" };
push @{$self->{_debug_loop}}, { 'debug.output' => sprintf($i18n->get('No query specified for query'), $nr) };
return \%var;
}
@ -703,7 +712,6 @@ sub _processQuery {
$query = $self->{_query}{$nr}{dbQuery};
}
my $i18n = WebGUI::International->new($self->session,"Asset_SQLReport");
push(@{$self->{_debug_loop}},{'debug.output'=>$i18n->get(17).$query});
push(@{$self->{_debug_loop}},{'debug.output'=>$i18n->get('debug placeholder parameters').join(",",@$placeholderParams)});
my $dbLink = WebGUI::DatabaseLink->new($self->session,$self->{_query}{$nr}{databaseLinkId});
@ -782,7 +790,7 @@ sub _processQuery {
$row{$prefix.'row.field.'.$tmpl_name.'.value'} = $data->{$name};
}
# Process nested query
if($nest && $self->{_query}{$nr + 1}{dbQuery}) {
if ($nest && $self->{_query}{$nr + 1}{dbQuery} =~ m/\S/) {
my $nest = $self->_processQuery($nest,$page,$nr+1);
%row = (%row , %$nest);
$row{$prefix.'hasNest'} = $nest->{'query'.($nr+1).'.rows.count'};
@ -832,12 +840,10 @@ sub www_download {
unless $self->session->user->isInGroup($self->downloadUserGroup);
# Set filename and mimetype
if ($self->downloadType eq "csv")
{
if ($self->downloadType eq "csv") {
$self->session->http->setFilename($self->downloadFilename,"application/octet-stream");
}
else
{
else {
$self->session->http->setFilename($self->downloadFilename, $self->downloadMimeType);
}

View file

@ -143,13 +143,17 @@ sub view {
value=>$keywords
});
$var{'no_results' } = $i18n->get("no results");
my $searchRoot = $self->searchRoot;
if (my $searchOverride = $form->get('searchroot', 'asset')) {
$searchRoot = $searchOverride;
}
if ($form->get("doit")) {
my $search = WebGUI::Search->new($session);
my %rules = (
keywords =>$keywords,
lineage =>[
WebGUI::Asset->newById($session,$self->searchRoot)->get("lineage")
WebGUI::Asset->newById($session,$searchRoot)->get("lineage")
],
);
my @classes = split("\n",$self->classLimiter);
@ -157,7 +161,7 @@ sub view {
$search->search(\%rules);
#Instantiate the highlighter
my @words = split(/\s+/,$keywords);
my @words = grep { $_ ne '' } map { tr/+?*//d; $_; } split(/\s+/,$keywords);
my @wildcards = map { "%" } @words;
my $hl = HTML::Highlight->new(
words => \@words,
@ -182,7 +186,8 @@ sub view {
if (defined $asset) {
my $properties = $asset->get;
if ($self->useContainers) {
$properties->{url} = $asset->getContainer->url;
$properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl()
: $asset->getContainer->url;
}
#Add highlighting
$properties->{'title' } = $hl->highlight($properties->{title} || '');

View file

@ -355,7 +355,7 @@ sub getKeywordStaticURL {
my $url = $self->getUrl;
my @parts = split /\//, $url;
my $lastPart = pop @parts;
if (index $lastPart, '.' == -1) {
if (index( $lastPart, '.' ) == -1) {
return join '/', $self->getUrl, $self->getKeywordFilename($keyword);
}
else {
@ -573,7 +573,7 @@ sub viewTemplateVariables {
}
$var->{keywordCloud} = WebGUI::Keyword->new($session)->generateCloud($cloudOptions);
if (! $exporting) {
$var->{searchHeader} = WebGUI::Form::formHeader($session, { action => $self->getUrl })
$var->{searchHeader} = WebGUI::Form::formHeader($session, { action => $self->getUrl, method => 'GET', })
. WebGUI::Form::hidden($session, { name => 'func', value => 'view' });
$var->{searchFooter} = WebGUI::Form::formFooter($session);
$var->{searchButton} = WebGUI::Form::submit($session, { name => 'search', value => $i18n->get('search','Asset')});

View file

@ -35,6 +35,13 @@ property timeLimit => (
label => ['timelimit', 'Asset_Survey'],
hoverHelp => ['timelimit hoverHelp', 'Asset_Survey'],
);
property maxResponsesPerUser => (
fieldType => 'integer',
tab => 'properties',
default => 1,
label => ['Max user responses', 'Asset_Survey'],
hoverHelp => ['Max user responses help', 'Asset_Survey'],
);
property doAfterTimeLimit => (
fieldType => 'selectBox',
default => 'exitUrl',
@ -209,13 +216,6 @@ property groupToViewReports => (
label => ['Group to view reports', 'Asset_Survey'],
hoverHelp => ['Group to view reports help', 'Asset_Survey'],
);
property maxResponsesPerUser => (
fieldType => 'integer',
tab => 'security',
default => 1,
label => ['Max user responses', 'Asset_Survey'],
hoverHelp => ['Max user responses help', 'Asset_Survey'],
);
# Other
property surveyJSON => (
@ -236,11 +236,6 @@ use Text::CSV_XS;
use Params::Validate qw(:all);
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
my $TAP_PARSER_MISSING = <<END_WARN;
The Survey Test Suite feature requires TAP::Parser and TAP::Parser::Aggregator CPAN modules.
These will be installed as a dependency if you upgrade to Test::Harness 3.x
END_WARN
#-------------------------------------------------------------------
=head2 surveyJSON_update ( )
@ -668,15 +663,18 @@ test suite.
sub getAdminConsole {
my $self = shift;
my $ac = WebGUI::AdminConsole->new( $self->session, 'Survey' );
my $i18n = WebGUI::International->new($self->session, "Asset_Survey");
$ac->addSubmenuItem($self->session->url->page("func=edit"), WebGUI::International->new($self->session, "WebGUI")->get(575));
$ac->addSubmenuItem($self->session->url->page("func=editSurvey"), $i18n->get('edit survey'));
$ac->addSubmenuItem($self->session->url->page("func=takeSurvey"), $i18n->get('take survey'));
$ac->addSubmenuItem($self->session->url->page("func=graph"), $i18n->get('visualize'));
$ac->addSubmenuItem($self->session->url->page("func=editTestSuite"), $i18n->get("test suite"));
$ac->addSubmenuItem($self->session->url->page("func=runTests"), $i18n->get("run all tests"));
$ac->addSubmenuItem($self->session->url->page("func=runTests;format=tap"), $i18n->get("run all tests") . " (TAP)");
my $ac = $self->SUPER::getAdminConsole;
unless ($self->{_modifiedAdminConsole}) {
my $i18n = WebGUI::International->new($self->session, "Asset_Survey");
$ac->addSubmenuItem($self->session->url->page("func=edit"), WebGUI::International->new($self->session, "WebGUI")->get(575));
$ac->addSubmenuItem($self->session->url->page("func=editSurvey"), $i18n->get('edit survey'));
$ac->addSubmenuItem($self->session->url->page("func=takeSurvey"), $i18n->get('take survey'));
$ac->addSubmenuItem($self->session->url->page("func=graph"), $i18n->get('visualize'));
$ac->addSubmenuItem($self->session->url->page("func=editTestSuite"), $i18n->get("test suite"));
$ac->addSubmenuItem($self->session->url->page("func=runTests"), $i18n->get("run all tests"));
$ac->addSubmenuItem($self->session->url->page("func=runTests;format=tap"), $i18n->get("run all tests") . " (TAP)");
$self->{_modifiedAdminConsole} = 1;
}
return $ac;
}
@ -1233,6 +1231,8 @@ sub www_loadSurvey {
$editHtml = $self->processTemplate( $var, $self->answerEditTemplateId );
}
WebGUI::Macro::process($self->session, \$editHtml);
# Generate the list of valid goto targets
my $gotoTargets = $self->getSurveyJSON->getGotoTargets;
@ -1962,6 +1962,7 @@ sub prepareShowSurveyTemplate {
$section->{allowBackBtn} = $self->allowBackBtn;
my $out = $self->processTemplate( $section, $self->surveyQuestionsId );
WebGUI::Macro::process($self->session, \$out);
$self->session->http->setMimeType('application/json');
return to_json( { type => 'displayquestions', section => $section, questions => $questions, html => $out } );
@ -2256,6 +2257,9 @@ END_SQL
}
$var->{response_loop} = \@responseloop;
$paginator->appendTemplateVars($var);
# Clean up
$self->clearTempReportTable;
my $out = $self->processTemplate( $var, $self->gradebookTemplateId );
return $self->processStyle($out);
@ -2346,6 +2350,9 @@ sub www_viewStatisticalOverview {
$var->{question_loop} = \@questionloop;
$paginator->appendTemplateVars($var);
# Clean up
$self->clearTempReportTable;
my $out = $self->processTemplate( $var, $self->overviewTemplateId );
return $self->processStyle($out);
@ -2401,6 +2408,9 @@ sub export {
$content = $self->session->db->$method( $opts{sql}, $opts{sqlParams} );
}
# Clean up
$self->clearTempReportTable;
my $filename = $self->session->url->escape( $self->title . "_$opts{name}.$format" );
$self->session->http->setFilename($filename,"text/$format");
return $content;
@ -2541,6 +2551,21 @@ END_HTML
#-------------------------------------------------------------------
=head2 clearTempReportTable
Clears the Survey_tempReport table
Typically called after L<loadTempReportTable> has been used
=cut
sub clearTempReportTable {
my $self = shift;
$self->session->db->write( 'delete from Survey_tempReport where assetId = ?', [ $self->getId() ] );
}
#-------------------------------------------------------------------
=head2 loadTempReportTable
Loads the responses from the survey into the Survey_tempReport table, so that other or custom reports can be ran against this data.
@ -2563,7 +2588,7 @@ sub loadTempReportTable {
my %opts = validate(@_, { ignoreRevisionDate => 0 });
# Remove old temp report data
$self->session->db->write( 'delete from Survey_tempReport where assetId = ?', [ $self->getId() ] );
$self->clearTempReportTable;
# Build the sql that will select all responses
my $sql = 'select * from Survey_response where assetId = ?';
@ -2879,11 +2904,7 @@ sub www_runTest {
my $i18n = WebGUI::International->new($session, 'Asset_Survey');
my $ac = $self->getAdminConsole;
eval { require TAP::Parser };
if ($@) {
$self->session->log->warn($TAP_PARSER_MISSING);
return $ac->render($TAP_PARSER_MISSING, $i18n->get('test results'));
}
require TAP::Parser;
my $testId = $session->form->get("testId");
@ -2915,11 +2936,7 @@ all interesting TAP::Parser and TAP::Parser::Result properties) and the template
sub parseTap {
my ($self, $tap) = @_;
eval { require TAP::Parser };
if ($@) {
$self->session->log->warn($TAP_PARSER_MISSING);
return;
}
require TAP::Parser;
my $parser = TAP::Parser->new( { tap => $tap } );
# Expose TAP::Parser and TAP::Parser::Result info as template variables
@ -3014,16 +3031,8 @@ sub www_runTests {
my @parsers;
eval { require TAP::Parser };
if ($@) {
$self->session->log->warn($TAP_PARSER_MISSING);
return $ac->render($TAP_PARSER_MISSING, $i18n->get('test results'));
}
eval { require TAP::Parser::Aggregator };
if ($@) {
$self->session->log->warn($TAP_PARSER_MISSING);
return $ac->render($TAP_PARSER_MISSING, $i18n->get('test results'));
}
require TAP::Parser;
require TAP::Parser::Aggregator;
my $aggregate = TAP::Parser::Aggregator->new;
$aggregate->start;

View file

@ -24,8 +24,10 @@ use WebGUI::Asset;
use WebGUI::Asset::Wobject::Survey;
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
# We need these as semi-globals so that utility subs (which are shared with the safe compartment)
# We need these as file-scoped lexicals so that our utility subs (which are shared with the safe compartment)
# can access them.
# N.B. If you add any new ones, make sure you initialize them in L<run> otherwise they will be cached across
# unrelated engine runs, which leads to bugs that are hairy to track down
my $session;
my $values;
my $scores;
@ -431,7 +433,7 @@ sub run {
my ( $s, $expression, $opts )
= validate_pos( @_, { isa => 'WebGUI::Session' }, { type => SCALAR }, { type => HASHREF, default => {} } );
# Init package globals
# Initialize all file-scoped lexicals that our Safe utility subs have access to
$session = $s;
$values = $opts->{values} || {};
$scores = $opts->{scores} || {};
@ -439,6 +441,7 @@ sub run {
$validate = $opts->{validate};
$validTargets = $opts->{validTargets};
$tags = $opts->{tags} || {};
$otherInstances = {};
if ( !$session->config->get('enableSurveyExpressionEngine') ) {
$session->log->debug('enableSurveyExpressionEngine config option disabled, skipping');

View file

@ -918,7 +918,7 @@ sub responseValues {
# Find out what we're indexing responses by
my $identifier
= $opts{indexBy} eq 'variable' ? $question && $question->{variable}
: $self->questionId($address);
: $self->questionId(@address);
next unless $identifier;
my $answer = $self->survey->answer([@address]);

View file

@ -68,6 +68,13 @@ property hasTerms => (
hoverHelp => ['hasTermsLabel description', 'Asset_SyndicatedContent'],
maxlength => 255,
);
property sortItems => (
tab => 'properties',
fieldType => 'yesNo',
default => 1,
label => ['sortItemsLabel', 'Asset_SyndicatedContent'],
hoverHelp => ['sortItemsLabel description', 'Asset_SyndicatedContent'],
);
has '+uiLevel' => (
default => 6,
);
@ -110,7 +117,7 @@ sub generateFeed {
my $limit = shift || $self->maxHeadlines;
my $feed = XML::FeedPP::Atom->new();
my $log = $self->session->log;
# build one feed out of many
my $newlyCached = 0;
my $cache = $self->session->cache;
@ -131,33 +138,47 @@ sub generateFeed {
utf8::downgrade($value, 1);
eval {
my $singleFeed = XML::FeedPP->new($value, utf8_flag => 1, -type => 'string');
$feed->merge($singleFeed);
$feed->merge_channel($singleFeed);
$feed->merge_item($singleFeed);
};
if ($@) {
$log->error("Syndicated Content asset (".$self->getId.") has a bad feed URL (".$url."). Failed with ".$@);
}
}
# build a new feed that matches the term the user is interested in
if ($self->hasTerms ne '') {
my @terms = split /,\s*/, $self->hasTerms; # get the list of terms
my $termRegex = join("|", map quotemeta($_), @terms); # turn the terms into a regex string
my @items = $feed->match_item(title=>qr/$termRegex/msi, description=>qr/$termRegex/msi);
$feed->clear_item;
foreach my $item (@items) {
$feed->add_item($item);
}
my @items = $feed->match_item(title => qr/$termRegex/msi);
push @items, $feed->match_item(description => qr/$termRegex/msi);
$feed->clear_item;
ITEM: foreach my $item (@items) {
$feed->add_item($item);
}
}
# sort them by date
$feed->sort_item();
my %seen = {};
my @items = $feed->get_item;
$feed->clear_item;
ITEM: foreach my $item (@items) {
my $key = join "\n", $item->link, $item->pubDate, $item->description, $item->title;
next ITEM if $seen{$key}++;
$feed->add_item($item);
}
# sort them by date and remove any duplicate from the OR based term matching above
if ($self->sortItems) {
$feed->sort_item();
}
# limit the feed to the maximum number of headlines (or the feed generator limit).
$feed->limit_item($limit);
# mark this asset as updated
$self->update({}) if ($newlyCached);
return $feed;
}
@ -222,7 +243,8 @@ sub getTemplateVariables {
$item{author} = WebGUI::HTML::filter(scalar $object->author, 'javascript');
$item{guid} = WebGUI::HTML::filter(scalar $object->guid, 'javascript');
$item{link} = WebGUI::HTML::filter(scalar $object->link, 'javascript');
$item{description} = WebGUI::HTML::filter(scalar($object->description), 'javascript');
my $description = WebGUI::HTML::filter(scalar($object->description), 'javascript');
$item{description} = defined $description ? $description : '';
$item{descriptionFirst100words} = $item{description};
$item{descriptionFirst100words} =~ s/(((\S+)\s+){100}).*/$1/s;
$item{descriptionFirst75words} = $item{descriptionFirst100words};

View file

@ -65,12 +65,13 @@ always taken from the field hashref.
sub addField {
my $self = shift;
my $field = shift;
my $isImport = shift;
my $self = shift;
my $field = shift;
my $isImport = shift;
my $dbDataType = shift || $self->_getDbDataType($field->{fieldType});
my $db = $self->session->db;
my $error = $self->session->errorHandler;
my $session = $self->session;
my $db = $session->db;
my $error = $session->errorHandler;
my ($oldFieldId, $newFieldId,$useAssetId,$useSequence);
$error->info("Adding Field, label: ".$field->{label}.", fieldId: ".$field->{fieldId}.",thingId: ".$field->{thingId});
@ -415,13 +416,37 @@ The id of row of data that should be copied.
=cut
sub copyThingData {
my $self = shift;
my $thingId = shift;
my $self = shift;
my $thingId = shift;
my $thingDataId = shift;
my $db = $self->session->db;
return undef unless $self->canEditThingData($thingId, $thingDataId);;
my $session = $self->session;
my $db = $session->db;
return undef unless $self->canEditThingData($thingId, $thingDataId);
$self->copyCollateral("Thingy_".$thingId,"thingDataId",$thingDataId);
my $origCollateral = $self->getCollateral("Thingy_".$thingId, "thingDataId", $thingDataId);
use Data::Dumper;
$session->log->warn(Dumper $origCollateral);
$origCollateral->{thingDataId} = "new";
##Get all fields
my $fields = $db->buildArrayRefOfHashRefs('select * from Thingy_fields where assetId=? and thingId=?'
,[$self->getId,$thingId]);
my @storage_field_ids = ();
##Check to see if any of them are File or Image
foreach my $field (@{ $fields }) {
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
push @storage_field_ids, $field->{fieldId};
}
}
##Instance the storage object and duplicate it
foreach my $fieldId (@storage_field_ids) {
my $currentId = $origCollateral->{"field_". $fieldId};
my $storage = WebGUI::Storage->get($session, $currentId);
my $new_store = $storage->copy;
##Update the copy with the new storageId.
$origCollateral->{"field_". $fieldId} = $new_store->getId;
}
##Update the copy
$self->setCollateral("Thingy_".$thingId, "thingDataId", $origCollateral, 0, 0);
return undef;
}
@ -445,12 +470,13 @@ The id of row of data that should be deleted.
sub deleteThingData {
my $self = shift;
my $thingId = shift;
my $self = shift;
my $thingId = shift;
my $thingDataId = shift;
my $db = $self->session->db;
my $session = $self->session;
my $db = $session->db;
return undef unless $self->canEditThingData($thingId, $thingDataId);;
return undef unless $self->canEditThingData($thingId, $thingDataId);
my ($onDeleteWorkflowId) = $db->quickArray("select onDeleteWorkflowId from Thingy_things where thingId=?"
,[$thingId]);
@ -458,7 +484,22 @@ sub deleteThingData {
$self->triggerWorkflow($onDeleteWorkflowId, $thingId,$thingDataId);
}
my $origCollateral = $self->getCollateral("Thingy_".$thingId, "thingDataId", $thingDataId);
$self->deleteCollateral("Thingy_".$thingId,"thingDataId",$thingDataId);
my $fields = $db->buildArrayRefOfHashRefs('select * from Thingy_fields where assetId=? and thingId=?'
,[$self->getId,$thingId]);
my @storage_field_ids = ();
##Check to see if any of them are File or Image
foreach my $field (@{ $fields }) {
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
push @storage_field_ids, $field->{fieldId};
}
}
foreach my $fieldId (@storage_field_ids) {
my $currentId = $origCollateral->{"field_". $fieldId};
my $storage = WebGUI::Storage->get($session, $currentId);
$storage->delete;
}
return undef;
}
@ -839,10 +880,10 @@ sub getFieldValue {
my $processedValue = $value;
my $dbh = $self->session->db->dbh;
if ($field->{fieldType} eq "date"){
if (lc $field->{fieldType} eq "date"){
$processedValue = $self->session->datetime->epochToHuman($value,$dateFormat);
}
elsif ($field->{fieldType} eq "dateTime"){
elsif (lc $field->{fieldType} eq "datetime"){
$processedValue = $self->session->datetime->epochToHuman($value,$dateTimeFormat);
}
# TODO: The otherThing field type is probably also handled by getFormPlugin, so the elsif below can probably be
@ -895,7 +936,7 @@ sub getFormElement {
Returns an instanciated WebGUI::Form::* plugin.
=head3 proeprties
=head3 properties
The properties to configure the form plugin with. The fieldType key should contain the type of the form plugin.
@ -912,19 +953,19 @@ sub getFormPlugin {
my %param;
my $session = $self->session;
my $db = $session->db;
my $dbh = $db->dbh;
my $i18n = WebGUI::International->new($session,"Asset_Thingy");
my $db = $session->db;
my $dbh = $db->dbh;
my $i18n = WebGUI::International->new($session,"Asset_Thingy");
$param{name} = "field_".$data->{fieldId};
my $name = $param{name};
my $name = $param{name};
$name =~ s/\^.*?\;//xgs ; # remove macro's from user input
$param{value} = $data->{value} || $data->{defaultValue};
$param{size} = $data->{size};
$param{height} = $data->{height};
$param{width} = $data->{width};
$param{extras} = $data->{extras};
$param{vertical} = $data->{vertical};
$param{value} = $data->{value} || $data->{defaultValue};
$param{size} = $data->{size};
$param{height} = $data->{height};
$param{width} = $data->{width};
$param{extras} = $data->{extras};
$param{vertical} = $data->{vertical};
$param{fieldType} = $data->{fieldType};
if ($data->{fieldType} eq "Checkbox") {
@ -936,7 +977,7 @@ sub getFormPlugin {
if ( WebGUI::Utility::isIn( $data->{fieldType}, qw(SelectList CheckList SelectBox Attachments) ) ) {
my @values;
if ( $useFormPostData && $self->session->form->param($name) ) {
if ( $useFormPostData && $session->form->param($name) ) {
$param{ value } = [ $session->form->process( $name, $data->{fieldType} ) ];
}
elsif ( $data->{ value } ) {
@ -947,7 +988,7 @@ sub getFormPlugin {
$param{value} = \@values;
}
}
elsif ( $useFormPostData && $self->session->form->param($name) ) {
elsif ( $useFormPostData && $session->form->param($name) ) {
$param{value} = $session->form->process( $name, $data->{fieldType} );
}
@ -981,30 +1022,36 @@ sub getFormPlugin {
}
if ($data->{fieldType} =~ m/^otherThing/x){
my $otherThingId = $data->{fieldType};
$otherThingId =~ s/^otherThing_(.*)/$1/x;
$param{fieldType} = "SelectList";
$class = 'WebGUI::Form::'. $param{fieldType};
my $otherThingId = $data->{fieldType};
$otherThingId =~ s/^otherThing_(.*)/$1/x;
$param{fieldType} = "SelectList";
$class = 'WebGUI::Form::'. $param{fieldType};
my $options = ();
my $tableName = 'Thingy_'.$otherThingId;
my $fieldName = 'field_'.$data->{fieldInOtherThingId};
my $tableName = 'Thingy_'.$otherThingId;
my $fieldName = 'field_'.$data->{fieldInOtherThingId};
my $errorMessage = $self->badOtherThing($tableName, $fieldName);
return $errorMessage if $errorMessage;
$options = $db->buildHashRef('select thingDataId, '
my $sth = $session->db->read('select thingDataId, '
.$dbh->quote_identifier($fieldName)
.' from '.$dbh->quote_identifier($tableName));
while (my $result = $sth->hashRef){
if ($self->canViewThingData($otherThingId,$result->{thingDataId})){
$options->{$result->{thingDataId}} = $result->{$fieldName}
}
}
my $value = $data->{value} || $data->{defaultValue};
($param{value}) = $db->quickArray('select '
.$dbh->quote_identifier($fieldName)
.' from '.$dbh->quote_identifier($tableName)
.' where thingDataId = ?',[$value]);
$param{size} = 1;
$param{size} = 1;
$param{multiple} = 0;
$param{options} = $options;
$param{value} = $data->{value} || $data->{defaultValue};
$param{options} = $options;
$param{value} = $data->{value} || $data->{defaultValue};
}
my $formElement = eval { WebGUI::Pluggable::instanciate($class, "new", [$session, \%param ])};
@ -1874,7 +1921,7 @@ sub www_editThing {
);
# create the options hash for the 'Who can edit' and 'Who can view' selectBoxes.
%editViewOptions = ('owner'=>'owner',$session->db->buildHash(
%editViewOptions = ('owner'=>$i18n->get('owner'),$session->db->buildHash(
"select groupId,groupName from groups where showInForms=1 order by groupName"
));
@ -2161,53 +2208,53 @@ Processes and saves a field. Returns the edited/added fieldId and the inner html
sub www_editFieldSave {
my $self = shift;
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canEdit;
my ($fieldId, $fieldTypeChanged, $newFieldId, $formClass, $dbDataType, $thingyTableName, $columnName);
my (%properties,$listItemHTML,$formElement);
my $i18n = WebGUI::International->new($self->session, "Asset_Thingy");
my $label = $session->form->process("label");
my $thingId = $self->session->form->process("thingId");
my $error = $self->session->errorHandler;
my $i18n = WebGUI::International->new($session, "Asset_Thingy");
my $label = $session->form->process("label");
my $thingId = $session->form->process("thingId");
my $log = $session->log;
my $defaultValue = $session->form->process("defaultValue");
my $fieldType = $session->form->process("fieldType") || "ReadOnly";
my $fieldType = $session->form->process("fieldType") || "ReadOnly";
if ($fieldType =~ m/^otherThing/){
$defaultValue = $session->form->process("defaultFieldInThing");
}
$fieldId = $self->session->form->process("fieldId");
$fieldId = $session->form->process("fieldId");
%properties = (
fieldId=>$fieldId,
thingId=>$thingId,
label=>$label,
fieldType=>$fieldType,
defaultValue=>$defaultValue,
possibleValues=>$self->session->form->process("possibleValues"),
pretext=>$self->session->form->process("pretext"),
subtext=>$self->session->form->process("subtext"),
status=>$self->session->form->process("status"),
size=>$self->session->form->process("size"),
width=>$self->session->form->process("width"),
height=>$self->session->form->process("height"),
vertical=>$self->session->form->process("vertical"),
extras=>$self->session->form->process("extras"),
display=>$self->session->form->process("display") || 1,
viewScreenTitle=>$self->session->form->process("viewScreenTitle") || 0,
fieldInOtherThingId=>$session->form->process("fieldInOtherThingId") || "",
fieldId => $fieldId,
thingId => $thingId,
label => $label,
fieldType => $fieldType,
defaultValue => $defaultValue,
possibleValues => $session->form->process("possibleValues"),
pretext => $session->form->process("pretext"),
subtext => $session->form->process("subtext"),
status => $session->form->process("status"),
size => $session->form->process("size"),
width => $session->form->process("width"),
height => $session->form->process("height"),
vertical => $session->form->process("vertical"),
extras => $session->form->process("extras"),
display => $session->form->process("display") || 1,
viewScreenTitle => $session->form->process("viewScreenTitle") || 0,
fieldInOtherThingId => $session->form->process("fieldInOtherThingId") || "",
);
# Get the field's data type
$dbDataType = $self->_getDbDataType($properties{fieldType});
if ($fieldId eq "new") {
$properties{dateCreated} = time();
$properties{createdBy} = $self->session->user->userId;
$properties{createdBy} = $session->user->userId;
$newFieldId = $self->addField(\%properties,0,$dbDataType);
}
else{
$properties{dateUpdated} = time();
$properties{updatedBy} = $self->session->user->userId;
$properties{updatedBy} = $session->user->userId;
# Check if column has to be altered for existing fields.
$self->_updateFieldType($fieldType,$fieldId,$thingId,$self->getId,$dbDataType);
$newFieldId = $self->setCollateral("Thingy_fields","fieldId",\%properties,1,1,"thingId",$thingId);
@ -2231,13 +2278,13 @@ sub www_editFieldSave {
$listItemHTML = "<table>\n<tr>\n<td style='width:100px;' valign='top' class='formDescription'>".$label."</td>\n"
."<td style='width:370px;'>".$formElement."</td>\n"
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$self->session->url->page()
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$session->url->page()
."?func=editField;fieldId=".$newFieldId.";thingId=".$properties{thingId}."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
."<input onClick=\"deleteListItem('".$self->session->url->page()."','".$newFieldId
."<input onClick=\"deleteListItem('".$session->url->page()."','".$newFieldId
."','".$properties{thingId}."')\" value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>";
# Make sure we send debug information along with the field.
$session->log->preventDebugOutput;
$log->preventDebugOutput;
$session->output->print($newFieldId.$listItemHTML);
return "chunked";

View file

@ -592,7 +592,7 @@ sub view {
$var{user_loop} = \@users;
$var{alphabetSearch_loop} = $self->getAlphabetSearchLoop($self->alphabetSearchField,$self->alphabet);
$var{searchFormHeader} = WebGUI::Form::formHeader($self->session,{action => $self->getUrl});
$var{searchFormHeader} = WebGUI::Form::formHeader($self->session,{action => $self->getUrl, method => 'GET', });
$var{searchFormSubmit} = WebGUI::Form::submit($self->session,{value => $i18n->get('submit search label')});
$var{searchFormFooter} = WebGUI::Form::formFooter($self->session);

View file

@ -16,17 +16,6 @@ package WebGUI::Asset::Wobject::WeatherData;
use strict;
use Weather::Com::Finder;
BEGIN {
# This is horrible, and needs to be removed when Weather::Com > 0.5.3 is released.
my $old_get_weather = \&Weather::Com::Base::get_weather;
no warnings 'redefine';
*Weather::Com::Base::get_weather = sub {
my $self = shift;
$self->{LINKS} = 1;
return $self->$old_get_weather(@_);
};
}
use WebGUI::International;
use Moose;
use WebGUI::Definition::Asset;

View file

@ -313,7 +313,7 @@ sub appendSearchBoxVars {
my $queryText = shift;
my $submitText = WebGUI::International->new($self->session, 'Asset_WikiMaster')->get('searchLabel');
$var->{'searchFormHeader'} = join '',
(WebGUI::Form::formHeader($self->session, { action => $self->getUrl}),
(WebGUI::Form::formHeader($self->session, { action => $self->getUrl, method => 'GET', }),
WebGUI::Form::hidden($self->session, { name => 'func', value => 'search' }));
$var->{'searchQuery'} = WebGUI::Form::text($self->session, { name => 'query', value => $queryText });
$var->{'searchSubmit'} = WebGUI::Form::submit($self->session, { value => $submitText });
@ -324,7 +324,7 @@ sub appendSearchBoxVars {
#-------------------------------------------------------------------
=head2 autolinkHtml ($html)
=head2 autolinkHtml ($html, [options])
Scan HTML for words and phrases that match wiki titles, and automatically
link them to those wiki pages. Returns the modified HTML.
@ -333,6 +333,14 @@ link them to those wiki pages. Returns the modified HTML.
The HTML to scan.
=head3 options
Either a hashref, or a hash of options.
=head4 skipTitles
An array reference of titles that should not be autolinked.
=cut
sub autolinkHtml {
@ -340,18 +348,21 @@ sub autolinkHtml {
my $html = shift;
# opts is always the last parameter, and a hash ref
my %opts = ref $_[-1] eq 'HASH' ? %{pop @_} : ();
my $skipTitles = $opts{skipTitles} || [];
$opts{skipTitles} ||= [];
# LC all the skip titles once, for efficiency
my @skipTitles = map { lc $_ } @{ $opts{skipTitles} };
# TODO: ignore caching for now, but maybe do it later.
my %mapping = $self->session->db->buildHash("SELECT LOWER(d.title), d.url FROM asset AS i INNER JOIN assetData AS d ON i.assetId = d.assetId WHERE i.parentId = ? and className='WebGUI::Asset::WikiPage' and i.state='published' and d.status='approved'", [$self->getId]);
foreach my $key (keys %mapping) {
if (grep {lc $_ eq $key} @$skipTitles) {
delete $mapping{$key};
next;
}
$key =~ s{\(}{\\\(}gxms; # escape parens
$key =~ s{\)}{\\\)}gxms; # escape parens
$mapping{$key} = $self->session->url->gateway($mapping{$key});
}
# This query returns multiple entries for each asset, so we order by revisionDate and count on the hash to only have the
# latest version.
my %mapping = $self->session->db->buildHash("SELECT LOWER(d.title), d.url FROM asset AS i INNER JOIN assetData AS d ON i.assetId = d.assetId WHERE i.parentId = ? and className='WebGUI::Asset::WikiPage' and i.state='published' and d.status='approved' order by d.revisionDate ASC", [$self->getId]);
TITLE: foreach my $title (keys %mapping) {
my $url = delete $mapping{$title};
##isIn short circuits and is faster than grep and/or first
next TITLE if isIn($title, @skipTitles);
$mapping{$title} = $self->session->url->gateway($url);
}
return $html unless %mapping;
# sort by length so it prefers matching longer titles
my $matchString = join('|', map{quotemeta} sort {length($b) <=> length($a)} keys %mapping);
@ -385,7 +396,7 @@ sub autolinkHtml {
=head2 canAdminister
Returns true if the current user is in the groupToAdminister group, or the user can edit
this WikiMaster.
this WikiMaster due to groupIdEdit or ownerUserId.
=cut
@ -398,34 +409,28 @@ sub canAdminister {
=head2 canEdit ( )
Overriding canEdit method to check permissions correctly when someone is adding a wikipage
Overriding canEdit method to check permissions correctly when someone is adding a wikipage.
=cut
around canEdit => sub {
my $orig = shift;
my $self = shift;
return (
(
(
$self->session->form->process("func") eq "add" ||
(
$self->session->form->process("assetId") eq "new" &&
$self->session->form->process("func") eq "editSave" &&
$self->session->form->process("class") eq "WebGUI::Asset::WikiPage"
)
) &&
$self->canEditPages
) || # account for new posts
$self->$orig(@_)
);
my $form = $self->session->form;
my $addNew = $form->process("func" ) eq "add";
my $editSave = $form->process("assetId" ) eq "new"
&& $form->process("func" ) eq "editSave"
&& $form->process("class","className" ) eq "WebGUI::Asset::WikiPage";
my $canEdit = ( ($addNew || $editSave) && $self->canEditPages )
|| $self->$orig(@_);
return $canEdit;
};
#-------------------------------------------------------------------
=head2 canEditPages
Returns true is the current user is in the group that can edit page, or if
Returns true is the current user is in the group that can edit pages, or if
they can administer the wiki (canAdminister).
=cut