Autocommit assets like CS posts or Calendar Events can now be added before the parent is committed. They will go into the same version tag as their parent.
1473 lines
47 KiB
Perl
1473 lines
47 KiB
Perl
package WebGUI::Asset::Wobject::Collaboration;
|
|
|
|
#-------------------------------------------------------------------
|
|
# WebGUI is Copyright 2001-2008 Plain Black Corporation.
|
|
#-------------------------------------------------------------------
|
|
# Please read the legal notices (docs/legal.txt) and the license
|
|
# (docs/license.txt) that came with this distribution before using
|
|
# this software.
|
|
#-------------------------------------------------------------------
|
|
# http://www.plainblack.com info@plainblack.com
|
|
#-------------------------------------------------------------------
|
|
|
|
use strict;
|
|
use Tie::IxHash;
|
|
use WebGUI::Group;
|
|
use WebGUI::Cache;
|
|
use WebGUI::HTML;
|
|
use WebGUI::International;
|
|
use WebGUI::Paginator;
|
|
use WebGUI::Utility;
|
|
use WebGUI::Asset::Wobject;
|
|
use WebGUI::Workflow::Cron;
|
|
use WebGUI::Asset::RSSCapable;
|
|
use base 'WebGUI::Asset::RSSCapable';
|
|
use base 'WebGUI::Asset::Wobject';
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _computePostCount {
|
|
my $self = shift;
|
|
return scalar @{$self->getLineage(['descendants'], {includeOnlyClasses => ['WebGUI::Asset::Post']})};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _computeThreadCount {
|
|
my $self = shift;
|
|
return scalar @{$self->getLineage(['children'], {includeOnlyClasses => ['WebGUI::Asset::Post::Thread']})};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# format the date according to rfc 822 (for RSS export)
|
|
my @_months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
|
|
sub _get_rfc822_date {
|
|
my $self = shift;
|
|
my ($time) = @_;
|
|
my ($year, $mon, $mday, $hour, $min, $sec) = $self->session->datetime->localtime($time);
|
|
my $month = $_months[$mon - 1];
|
|
return sprintf("%02d %s %04d %02d:%02d:%02d GMT",
|
|
$mday, $month, $year, $hour, $min, $sec);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _visitorCacheKey {
|
|
my $self = shift;
|
|
my $pn = $self->session->form->process('pn');
|
|
return "view_".$self->getId."?pn=".$pn;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _visitorCacheOk {
|
|
my $self = shift;
|
|
return ($self->session->user->isVisitor
|
|
&& !$self->session->form->process('sortBy'));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# encode a string to include in xml (for RSS export)
|
|
sub _xml_encode {
|
|
my $text = shift;
|
|
$text =~ s/&/&/g;
|
|
$text =~ s/</</g;
|
|
$text =~ s/\]\]>/\]\]>/g;
|
|
return $text;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub addChild {
|
|
my $self = shift;
|
|
my $properties = shift;
|
|
my @other = @_;
|
|
if ($properties->{className} ne "WebGUI::Asset::Post::Thread"
|
|
and $properties->{className} ne 'WebGUI::Asset::RSSFromParent') {
|
|
$self->session->errorHandler->security("add a ".$properties->{className}." to a ".$self->get("className"));
|
|
return undef;
|
|
}
|
|
return $self->SUPER::addChild($properties, @other);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
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));
|
|
foreach my $row (@$page) {
|
|
my $post = WebGUI::Asset->new($self->session,$row->{assetId}, $row->{className}, $row->{revisionDate});
|
|
$post->{_parent} = $self; # caching parent for efficiency
|
|
my $controls = $icon->delete('func=delete',$post->get("url"),"Delete") . $icon->edit('func=edit',$post->get("url"));
|
|
if ($self->get("sortBy") eq "lineage") {
|
|
if ($self->get("sortOrder") eq "desc") {
|
|
$controls .= $icon->moveUp('func=demote',$post->get("url")).$icon->moveDown('func=promote',$post->get("url"));
|
|
}
|
|
else {
|
|
$controls .= $icon->moveUp('func=promote',$post->get("url")).$icon->moveDown('func=demote',$post->get("url"));
|
|
}
|
|
}
|
|
my @rating_loop;
|
|
for (my $i=0;$i<=$post->get("rating");$i++) {
|
|
push(@rating_loop,{'rating_loop.count'=>$i});
|
|
}
|
|
my %lastReply;
|
|
my $hasRead = 0;
|
|
if ($post->get("className") =~ /Thread/) {
|
|
if ($self->get("displayLastReply")) {
|
|
my $lastPost = $post->getLastPost();
|
|
%lastReply = (
|
|
"lastReply.url" => $lastPost->getUrl.'#'.$lastPost->getId,
|
|
"lastReply.title" => $lastPost->get("title"),
|
|
"lastReply.user.isVisitor" => $lastPost->get("ownerUserId") eq "1",
|
|
"lastReply.username" => $lastPost->get("username"),
|
|
"lastReply.userProfile.url" => $lastPost->getPosterProfileUrl(),
|
|
"lastReply.dateSubmitted.human" => $datetime->epochToHuman($lastPost->get("creationDate"),"%z"),
|
|
"lastReply.timeSubmitted.human" => $datetime->epochToHuman($lastPost->get("creationDate"),"%Z"),
|
|
);
|
|
}
|
|
$hasRead = $post->isMarkedRead;
|
|
}
|
|
my $url;
|
|
if ($post->get("status") eq "pending") {
|
|
$url = $post->getUrl("revision=".$post->get("revisionDate"))."#".$post->getId;
|
|
} else {
|
|
$url = $post->getUrl."#".$post->getId;
|
|
}
|
|
my %postVars = (
|
|
%{$post->get},
|
|
"id" => $post->getId,
|
|
"url" => $url,
|
|
rating_loop => \@rating_loop,
|
|
"content" => $post->formatContent,
|
|
"status" => $post->getStatus,
|
|
"thumbnail" => $post->getThumbnailUrl,
|
|
"image.url" => $post->getImageUrl,
|
|
"dateSubmitted.human" => $datetime->epochToHuman($post->get("creationDate"),"%z"),
|
|
"dateUpdated.human" => $datetime->epochToHuman($post->get("revisionDate"),"%z"),
|
|
"timeSubmitted.human" => $datetime->epochToHuman($post->get("creationDate"),"%Z"),
|
|
"timeUpdated.human" => $datetime->epochToHuman($post->get("revisionDate"),"%Z"),
|
|
"userProfile.url" => $post->getPosterProfileUrl,
|
|
"user.isVisitor" => $post->get("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),
|
|
"user.hasRead" => $hasRead,
|
|
"user.isPoster" => $post->isPoster,
|
|
"avatar.url" => $post->getAvatarUrl,
|
|
%lastReply
|
|
);
|
|
$post->getTemplateMetadataVars(\%postVars);
|
|
if ($row->{className} =~ m/^WebGUI::Asset::Post::Thread/) {
|
|
$postVars{'rating'} = $post->get('threadRating');
|
|
}
|
|
push(@{$var->{post_loop}}, \%postVars );
|
|
$i++;
|
|
}
|
|
$p->appendTemplateVars($var);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub appendTemplateLabels {
|
|
my $self = shift;
|
|
my $var = shift;
|
|
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
|
|
$var->{"transferkarma.label"} = $i18n->get("transfer karma");
|
|
$var->{"karmaScale.label"} = $i18n->get("karma scale");
|
|
$var->{"close.label"} = $i18n->get("close");
|
|
$var->{"closed.label"} = $i18n->get("closed");
|
|
$var->{"open.label"} = $i18n->get("open");
|
|
$var->{"critical.label"} = $i18n->get("critical");
|
|
$var->{"cosmetic.label"} = $i18n->get("cosmetic");
|
|
$var->{"minor.label"} = $i18n->get("minor");
|
|
$var->{"fatal.label"} = $i18n->get("fatal");
|
|
$var->{"severity.label"} = $i18n->get("severity");
|
|
$var->{"add.label"} = $i18n->get("add");
|
|
$var->{"addlink.label"} = $i18n->get("addlink");
|
|
$var->{"addquestion.label"} = $i18n->get("addquestion");
|
|
$var->{'answer.label'} = $i18n->get("answer");
|
|
$var->{'attachment.label'} = $i18n->get("attachment");
|
|
$var->{'archive.label'} = $i18n->get("archive");
|
|
$var->{'unarchive.label'} = $i18n->get("unarchive");
|
|
$var->{"by.label"} = $i18n->get("by");
|
|
$var->{'body.label'} = $i18n->get("body");
|
|
$var->{"back.label"} = $i18n->get("back");
|
|
$var->{'compensation.label'} = $i18n->get("compensation");
|
|
$var->{'contentType.label'} = $i18n->get("contentType");
|
|
$var->{"date.label"} = $i18n->get("date");
|
|
$var->{"delete.label"} = $i18n->get("delete");
|
|
$var->{'description.label'} = $i18n->get("description");
|
|
$var->{"edit.label"} = $i18n->get("edit");
|
|
$var->{'image.label'} = $i18n->get("image");
|
|
$var->{"job.header.label"} = $i18n->get("edit job");
|
|
$var->{"job.title.label"} = $i18n->get("job title");
|
|
$var->{"job.description.label"} = $i18n->get("job description");
|
|
$var->{"job.requirements.label"} = $i18n->get("job requirements");
|
|
$var->{"karmaRank.label"} = $i18n->get("karma rank");
|
|
$var->{"location.label"} = $i18n->get("location");
|
|
$var->{"layout.flat.label"} = $i18n->get("flatLayout");
|
|
$var->{'link.header.label'} = $i18n->get("edit link");
|
|
$var->{"lastReply.label"} = $i18n->get("lastReply");
|
|
$var->{"lock.label"} = $i18n->get("lock");
|
|
$var->{"layout.label"} = $i18n->get("layout");
|
|
$var->{'message.header.label'} = $i18n->get("edit message");
|
|
$var->{'message.label'} = $i18n->get("message");
|
|
$var->{"next.label"} = $i18n->get("next");
|
|
$var->{'newWindow.label'} = $i18n->get("new window");
|
|
$var->{"layout.nested.label"} = $i18n->get("nested");
|
|
$var->{"previous.label"} = $i18n->get("previous");
|
|
$var->{"post.label"} = $i18n->get("post");
|
|
$var->{'question.label'} = $i18n->get("question");
|
|
$var->{'question.header.label'} = $i18n->get("edit question");
|
|
$var->{"rating.label"} = $i18n->get("rating");
|
|
$var->{"rate.label"} = $i18n->get("rate");
|
|
$var->{"reply.label"} = $i18n->get("reply");
|
|
$var->{"replies.label"} = $i18n->get("replies");
|
|
$var->{"readmore.label"} = $i18n->get("read more");
|
|
$var->{"responses.label"} = $i18n->get("responses");
|
|
$var->{"search.label"} = $i18n->get("search");
|
|
$var->{'subject.label'} = $i18n->get("subject");
|
|
$var->{"subscribe.label"} = $i18n->get("subscribe");
|
|
$var->{'submission.header.label'} = $i18n->get("edit submission");
|
|
$var->{"stick.label"} = $i18n->get("sticky");
|
|
$var->{"status.label"} = $i18n->get("status");
|
|
$var->{"synopsis.label"} = $i18n->get("synopsis");
|
|
$var->{"thumbnail.label"} = $i18n->get("thumbnail");
|
|
$var->{"title.label"} = $i18n->get("title");
|
|
$var->{"unlock.label"} = $i18n->get("unlock");
|
|
$var->{"unstick.label"} = $i18n->get("unstick");
|
|
$var->{"unsubscribe.label"} = $i18n->get("unsubscribe");
|
|
$var->{'url.label'} = $i18n->get("url");
|
|
$var->{"user.label"} = $i18n->get("user");
|
|
$var->{"views.label"} = $i18n->get("views");
|
|
$var->{'visitorName.label'} = $i18n->get("visitor");
|
|
$var->{"captcha_label"} = $i18n->get("captcha label");
|
|
$var->{'keywords.label'} = $i18n->get('keywords label');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canEdit {
|
|
my $self = shift;
|
|
my $userId = shift || $self->session->user->userId;
|
|
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::Post::Thread"
|
|
)
|
|
) &&
|
|
$self->canStartThread( $userId )
|
|
) || # account for new threads
|
|
$self->SUPER::canEdit( $userId )
|
|
);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canModerate {
|
|
my $self = shift;
|
|
my $userId = shift || $self->session->user->userId;
|
|
return $self->SUPER::canEdit( $userId );
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canPost {
|
|
my $self = shift;
|
|
my $userId = shift;
|
|
my $session = $self->session;
|
|
my $user = $userId
|
|
? WebGUI::User->new( $session, $userId )
|
|
: $self->session->user
|
|
;
|
|
|
|
# checks to make sure that the cs has been committed at least once
|
|
if ( $self->get("status") ne "approved" && $self->getTagCount <= 1 ) {
|
|
return 0;
|
|
}
|
|
# Users in the postGroupId can post
|
|
elsif ( $user->isInGroup( $self->get("postGroupId") ) ) {
|
|
return 1;
|
|
}
|
|
# Users who can edit the collab can post
|
|
else {
|
|
return $self->SUPER::canEdit( $userId );
|
|
}
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canSubscribe {
|
|
my $self = shift;
|
|
my $userId = shift;
|
|
my $session = $self->session;
|
|
my $user = $userId
|
|
? WebGUI::User->new( $session, $userId )
|
|
: $self->session->user
|
|
;
|
|
return ($user->isRegistered && $self->canView( $userId ) );
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canStartThread {
|
|
my $self = shift;
|
|
my $userId = shift;
|
|
my $session = $self->session;
|
|
my $user = $userId
|
|
? WebGUI::User->new( $session, $userId )
|
|
: $self->session->user
|
|
;
|
|
return (
|
|
$user->isInGroup($self->get("canStartThreadGroupId"))
|
|
|| $self->SUPER::canEdit( $userId )
|
|
);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub canView {
|
|
my $self = shift;
|
|
my $userId = shift || $self->session->user->userId;
|
|
return $self->SUPER::canView( $userId ) || $self->canPost( $userId );
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub commit {
|
|
my $self = shift;
|
|
$self->SUPER::commit;
|
|
my $cron = undef;
|
|
if ($self->get("getMailCronId")) {
|
|
$cron = WebGUI::Workflow::Cron->new($self->session, $self->get("getMailCronId"));
|
|
}
|
|
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
|
|
unless (defined $cron) {
|
|
$cron = 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"
|
|
});
|
|
$self->update({getMailCronId=>$cron->getId});
|
|
}
|
|
if ($self->get("getMail")) {
|
|
$cron->set({enabled=>1,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->get("getMailInterval")/60)});
|
|
} else {
|
|
$cron->set({enabled=>0,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->get("getMailInterval")/60)});
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub createSubscriptionGroup {
|
|
my $self = shift;
|
|
my $group = WebGUI::Group->new($self->session, "new");
|
|
$group->name($self->getId);
|
|
$group->description("The group to store subscriptions for the collaboration system ".$self->getId);
|
|
$group->isEditable(0);
|
|
$group->showInForms(0);
|
|
$group->deleteGroups([3]); # admins don't want to be auto subscribed to this thing
|
|
$self->update({
|
|
subscriptionGroupId=>$group->getId
|
|
});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub definition {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my $definition = shift;
|
|
my $i18n = WebGUI::International->new($session,"Asset_Collaboration");
|
|
my $useKarma = $session->setting->get('useKarma');
|
|
|
|
# obtain the groupIdEdit default value. Try to get it from the parent asset
|
|
# if it exists. If not, default to the value specified in WebGUI::Asset's
|
|
# definition.
|
|
my $groupIdEdit;
|
|
if($session->asset) {
|
|
$groupIdEdit = $session->asset->get('groupIdEdit');
|
|
}
|
|
else {
|
|
$groupIdEdit = '4';
|
|
}
|
|
|
|
|
|
my %sortByOptions;
|
|
tie %sortByOptions, 'Tie::IxHash';
|
|
%sortByOptions = (lineage=>$i18n->get('sequence'),
|
|
"assetData.revisionDate"=>$i18n->get('date updated'),
|
|
creationDate=>$i18n->get('date submitted'),
|
|
title=>$i18n->get('title'),
|
|
userDefined1=>$i18n->get('user defined 1'),
|
|
userDefined2=>$i18n->get('user defined 2'),
|
|
userDefined3=>$i18n->get('user defined 3'),
|
|
userDefined4=>$i18n->get('user defined 4'),
|
|
userDefined5=>$i18n->get('user defined 5'),
|
|
($useKarma? (karmaRank=>$i18n->get('karma rank')) : ()),
|
|
);
|
|
|
|
my %properties;
|
|
tie %properties, 'Tie::IxHash';
|
|
%properties = (
|
|
visitorCacheTimeout => {
|
|
tab => "display",
|
|
fieldType => "interval",
|
|
defaultValue => 3600,
|
|
uiLevel => 8,
|
|
label => $i18n->get("visitor cache timeout"),
|
|
hoverHelp => $i18n->get("visitor cache timeout help")
|
|
},
|
|
autoSubscribeToThread => {
|
|
fieldType=>"yesNo",
|
|
defaultValue=>1,
|
|
tab=>'mail',
|
|
label=>$i18n->get("auto subscribe to thread"),
|
|
hoverHelp=>$i18n->get("auto subscribe to thread help"),
|
|
},
|
|
requireSubscriptionForEmailPosting => {
|
|
fieldType=>"yesNo",
|
|
defaultValue=>1,
|
|
tab=>'mail',
|
|
label=>$i18n->get("require subscription for email posting"),
|
|
hoverHelp=>$i18n->get("require subscription for email posting help"),
|
|
},
|
|
approvalWorkflow =>{
|
|
fieldType=>"workflow",
|
|
defaultValue=>"pbworkflow000000000003",
|
|
type=>'WebGUI::VersionTag',
|
|
tab=>'security',
|
|
label=>$i18n->get('approval workflow'),
|
|
hoverHelp=>$i18n->get('approval workflow description'),
|
|
},
|
|
threadApprovalWorkflow =>{
|
|
fieldType=>"workflow",
|
|
defaultValue=>"pbworkflow000000000003",
|
|
type=>'WebGUI::VersionTag',
|
|
tab=>'security',
|
|
label=>$i18n->get('thread approval workflow'),
|
|
hoverHelp=>$i18n->get('thread approval workflow description'),
|
|
},
|
|
thumbnailSize => {
|
|
fieldType => "integer",
|
|
defaultValue => 0,
|
|
tab => "display",
|
|
label => $i18n->get("thumbnail size"),
|
|
hoverHelp => $i18n->get("thumbnail size help")
|
|
},
|
|
maxImageSize => {
|
|
fieldType => "integer",
|
|
defaultValue => 0,
|
|
tab => "display",
|
|
label => $i18n->get("max image size"),
|
|
hoverHelp => $i18n->get("max image size help")
|
|
},
|
|
mailServer=>{
|
|
fieldType=>"text",
|
|
defaultValue=>undef,
|
|
tab=>'mail',
|
|
label=>$i18n->get("mail server"),
|
|
hoverHelp=>$i18n->get("mail server help"),
|
|
},
|
|
mailAccount=>{
|
|
fieldType=>"text",
|
|
defaultValue=>undef,
|
|
tab=>'mail',
|
|
label=>$i18n->get("mail account"),
|
|
hoverHelp=>$i18n->get("mail account help"),
|
|
},
|
|
mailPassword=>{
|
|
fieldType=>"password",
|
|
defaultValue=>undef,
|
|
tab=>'mail',
|
|
label=>$i18n->get("mail password"),
|
|
hoverHelp=>$i18n->get("mail password help"),
|
|
},
|
|
mailAddress=>{
|
|
fieldType=>"email",
|
|
defaultValue=>undef,
|
|
tab=>'mail',
|
|
label=>$i18n->get("mail address"),
|
|
hoverHelp=>$i18n->get("mail address help"),
|
|
},
|
|
mailPrefix=>{
|
|
fieldType=>"text",
|
|
defaultValue=>undef,
|
|
tab=>'mail',
|
|
label=>$i18n->get("mail prefix"),
|
|
hoverHelp=>$i18n->get("mail prefix help"),
|
|
},
|
|
getMailCronId=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef,
|
|
noFormPost=>1
|
|
},
|
|
getMail=>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>0,
|
|
tab=>'mail',
|
|
label=>$i18n->get("get mail"),
|
|
hoverHelp=>$i18n->get("get mail help"),
|
|
},
|
|
getMailInterval=>{
|
|
fieldType=>"interval",
|
|
defaultValue=>300,
|
|
tab=>'mail',
|
|
label=>$i18n->get("get mail interval"),
|
|
hoverHelp=>$i18n->get("get mail interval help"),
|
|
},
|
|
displayLastReply =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>0,
|
|
tab=>'display',
|
|
label=>$i18n->get('display last reply'),
|
|
hoverHelp=>$i18n->get('display last reply description'),
|
|
},
|
|
allowReplies =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>1,
|
|
tab=>'security',
|
|
label=>$i18n->get('allow replies'),
|
|
hoverHelp=>$i18n->get('allow replies description'),
|
|
},
|
|
threadsPerPage =>{
|
|
fieldType=>"integer",
|
|
defaultValue=>30,
|
|
tab=>'display',
|
|
label=>$i18n->get('threads/page'),
|
|
hoverHelp=>$i18n->get('threads/page description'),
|
|
},
|
|
postsPerPage =>{
|
|
fieldType=>"integer",
|
|
defaultValue=>10,
|
|
tab=>'display',
|
|
label=>$i18n->get('posts/page'),
|
|
hoverHelp=>$i18n->get('posts/page description'),
|
|
},
|
|
archiveEnabled => {
|
|
fieldType => "yesNo",
|
|
defaultValue => 1,
|
|
tab => 'properties',
|
|
label => $i18n->get('editForm archiveEnabled label'),
|
|
hoverHelp => $i18n->get('editForm archiveEnabled description'),
|
|
},
|
|
archiveAfter =>{
|
|
fieldType=>"interval",
|
|
defaultValue=>31536000,
|
|
tab=>'properties',
|
|
label=>$i18n->get('archive after'),
|
|
hoverHelp=>$i18n->get('archive after description'),
|
|
},
|
|
lastPostDate =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
lastPostId =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
rating =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
replies =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
views =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
threads =>{
|
|
noFormPost=>1,
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
useContentFilter =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>1,
|
|
tab=>'display',
|
|
label=>$i18n->get('content filter'),
|
|
hoverHelp=>$i18n->get('content filter description'),
|
|
},
|
|
filterCode =>{
|
|
fieldType=>"filterContent",
|
|
defaultValue=>'javascript',
|
|
tab=>'security',
|
|
label=>$i18n->get('filter code'),
|
|
hoverHelp=>$i18n->get('filter code description'),
|
|
},
|
|
richEditor =>{
|
|
fieldType=>"selectRichEditor",
|
|
defaultValue=>"PBrichedit000000000002",
|
|
tab=>'display',
|
|
label=>$i18n->get('rich editor'),
|
|
hoverHelp=>$i18n->get('rich editor description'),
|
|
},
|
|
attachmentsPerPost =>{
|
|
fieldType=>"integer",
|
|
defaultValue=>0,
|
|
tab=>'properties',
|
|
label=>$i18n->get('attachments/post'),
|
|
hoverHelp=>$i18n->get('attachments/post description'),
|
|
},
|
|
editTimeout =>{
|
|
fieldType=>"interval",
|
|
defaultValue=>3600,
|
|
tab=>'security',
|
|
label=>$i18n->get('edit timeout'),
|
|
hoverHelp=>$i18n->get('edit timeout description'),
|
|
},
|
|
addEditStampToPosts =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>0,
|
|
tab=>'security',
|
|
label=>$i18n->get('edit stamp'),
|
|
hoverHelp=>$i18n->get('edit stamp description'),
|
|
},
|
|
usePreview =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>1,
|
|
tab=>'properties',
|
|
label=>$i18n->get('use preview'),
|
|
hoverHelp=>$i18n->get('use preview description'),
|
|
},
|
|
sortOrder =>{
|
|
fieldType=>"selectBox",
|
|
defaultValue=>'desc',
|
|
tab=>'display',
|
|
options=>{ asc => $i18n->get('ascending'),
|
|
desc => $i18n->get('descending') },
|
|
label=>$i18n->get('sort order'),
|
|
hoverHelp=>$i18n->get('sort order description'),
|
|
},
|
|
sortBy =>{
|
|
fieldType=>"selectBox",
|
|
defaultValue=>'assetData.revisionDate',
|
|
tab=>'display',
|
|
options=>\%sortByOptions,
|
|
label=>$i18n->get('sort by'),
|
|
hoverHelp=>$i18n->get('sort by description'),
|
|
},
|
|
notificationTemplateId =>{
|
|
fieldType=>"template",
|
|
namespace=>"Collaboration/Notification",
|
|
defaultValue=>'PBtmpl0000000000000027',
|
|
tab=>'mail',
|
|
label=>$i18n->get('notification template'),
|
|
hoverHelp=>$i18n->get('notification template description'),
|
|
},
|
|
searchTemplateId =>{
|
|
fieldType=>"template",
|
|
namespace=>"Collaboration/Search",
|
|
defaultValue=>'PBtmpl0000000000000031',
|
|
tab=>'display',
|
|
label=>$i18n->get('search template'),
|
|
hoverHelp=>$i18n->get('search template description'),
|
|
},
|
|
postFormTemplateId =>{
|
|
fieldType=>"template",
|
|
namespace=>"Collaboration/PostForm",
|
|
defaultValue=>'PBtmpl0000000000000029',
|
|
tab=>'display',
|
|
label=>$i18n->get('post template'),
|
|
hoverHelp=>$i18n->get('post template description'),
|
|
},
|
|
threadTemplateId =>{
|
|
fieldType=>"template",
|
|
namespace=>"Collaboration/Thread",
|
|
defaultValue=>'PBtmpl0000000000000032',
|
|
tab=>'display',
|
|
label=>$i18n->get('thread template'),
|
|
hoverHelp=>$i18n->get('thread template description'),
|
|
},
|
|
collaborationTemplateId =>{
|
|
fieldType=>"template",
|
|
namespace=>'Collaboration',
|
|
defaultValue=>'PBtmpl0000000000000026',
|
|
tab=>'display',
|
|
label=>$i18n->get('system template'),
|
|
hoverHelp=>$i18n->get('system template description'),
|
|
},
|
|
karmaPerPost =>{
|
|
fieldType=>"integer",
|
|
defaultValue=>0,
|
|
tab=>'properties',
|
|
visible=>$useKarma,
|
|
label=>$i18n->get('karma/post'),
|
|
hoverHelp=>$i18n->get('karma/post description'),
|
|
},
|
|
karmaSpentToRate => {
|
|
fieldType => "integer",
|
|
defaultValue=> 0,
|
|
tab=>'properties',
|
|
visible => $useKarma,
|
|
label => $i18n->get('karma spent to rate'),
|
|
hoverHelp => $i18n->get('karma spent to rate description'),
|
|
},
|
|
karmaRatingMultiplier => {
|
|
fieldType => "integer",
|
|
defaultValue=> 1,
|
|
tab=>'properties',
|
|
visible => $useKarma,
|
|
label=>$i18n->get('karma rating multiplier'),
|
|
hoverHelp=>$i18n->get('karma rating multiplier description'),
|
|
},
|
|
avatarsEnabled =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>0,
|
|
tab=>'properties',
|
|
label=>$i18n->get('enable avatars'),
|
|
hoverHelp=>$i18n->get('enable avatars description'),
|
|
},
|
|
enablePostMetaData =>{
|
|
fieldType=>"yesNo",
|
|
defaultValue=>0,
|
|
tab=>'meta',
|
|
label=>$i18n->get('enable metadata'),
|
|
hoverHelp=>$i18n->get('enable metadata description'),
|
|
},
|
|
postGroupId =>{
|
|
fieldType=>"group",
|
|
defaultValue=>'2',
|
|
tab=>'security',
|
|
label=>$i18n->get('who posts'),
|
|
hoverHelp=>$i18n->get('who posts description'),
|
|
},
|
|
canStartThreadGroupId =>{
|
|
fieldType=>"group",
|
|
defaultValue=>'2',
|
|
tab=>'security',
|
|
label=>$i18n->get('who threads'),
|
|
hoverHelp=>$i18n->get('who threads description'),
|
|
},
|
|
defaultKarmaScale => {
|
|
fieldType=>"integer",
|
|
defaultValue=>1,
|
|
tab=>'properties',
|
|
visible=>$useKarma,
|
|
label=>$i18n->get("default karma scale"),
|
|
hoverHelp=>$i18n->get('default karma scale help'),
|
|
},
|
|
useCaptcha => {
|
|
fieldType=>"yesNo",
|
|
defaultValue=>'0',
|
|
tab=>'security',
|
|
label=>$i18n->get('use captcha label'),
|
|
hoverHelp=>$i18n->get('use captcha hover help'),
|
|
},
|
|
subscriptionGroupId =>{
|
|
fieldType=>"subscriptionGroup",
|
|
tab=>'security',
|
|
label=>$i18n->get("subscription group label"),
|
|
hoverHelp=>$i18n->get("subscription group hoverHelp"),
|
|
noFormPost=>1,
|
|
defaultValue=>undef,
|
|
},
|
|
groupToEditPost=>{
|
|
tab=>"security",
|
|
label=>$i18n->get('group to edit label'),
|
|
excludeGroups=>[1,7],
|
|
hoverHelp=>$i18n->get('group to edit hoverhelp'),
|
|
uiLevel=>6,
|
|
fieldType=>'group',
|
|
filter=>'fixId',
|
|
defaultValue=>$groupIdEdit, # groupToEditPost should default to groupIdEdit
|
|
},
|
|
postReceivedTemplateId =>{
|
|
fieldType=>'template',
|
|
namespace=>'Collaboration/PostReceived',
|
|
tab=>'display',
|
|
label=>$i18n->get('post received template'),
|
|
hoverHelp=>$i18n->get('post received template hoverHelp'),
|
|
defaultValue=>'default_post_received1',
|
|
},
|
|
);
|
|
|
|
push(@{$definition}, {
|
|
assetName=>$i18n->get('assetName'),
|
|
autoGenerateForms=>1,
|
|
icon=>'collaboration.gif',
|
|
tableName=>'Collaboration',
|
|
className=>'WebGUI::Asset::Wobject::Collaboration',
|
|
properties=>\%properties,
|
|
});
|
|
return $class->SUPER::definition($session, $definition);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub duplicate {
|
|
my $self = shift;
|
|
my $newAsset = $self->SUPER::duplicate(@_);
|
|
$newAsset->createSubscriptionGroup;
|
|
return $newAsset;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# Too slow to try to find out children, just always assume new data
|
|
sub getContentLastModified {
|
|
return time();
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getEditTabs
|
|
|
|
Add a tab for the mail interface.
|
|
|
|
=cut
|
|
|
|
sub getEditTabs {
|
|
my $self = shift;
|
|
my $i18n = WebGUI::International->new($self->session,"Asset_Collaboration");
|
|
return ($self->SUPER::getEditTabs(), ['mail', $i18n->get('mail'), 9]);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getNewThreadUrl( )
|
|
|
|
Formats the url to start a new thread.
|
|
|
|
=cut
|
|
|
|
sub getNewThreadUrl {
|
|
my $self = shift;
|
|
$self->getUrl("func=add;class=WebGUI::Asset::Post::Thread");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub getRssItems {
|
|
my $self = shift;
|
|
|
|
# XXX copied and reformatted this query from www_viewRSS, but why is it constructed like this?
|
|
# And it's duplicated inside view, too! Eeeagh! And it uses the versionTag scratch var...
|
|
my ($sortBy, $sortOrder) = ($self->getValue('sortBy'), $self->getValue('sortOrder'));
|
|
|
|
my @postIds = $self->session->db->buildArray(<<"SQL", [$self->getId, $self->session->scratch->get('versionTag')]);
|
|
SELECT asset.assetId
|
|
FROM Thread
|
|
LEFT JOIN asset ON Thread.assetId = asset.assetId
|
|
LEFT JOIN Post ON Post.assetId = Thread.assetId AND Post.revisionDate = Thread.revisionDate
|
|
LEFT JOIN assetData ON assetData.assetId = Thread.assetId
|
|
AND assetData.revisionDate = Thread.revisionDate
|
|
WHERE asset.parentId = ? AND asset.state = 'published' AND asset.className = 'WebGUI::Asset::Post::Thread'
|
|
AND (assetData.status = 'approved' OR assetData.tagId = ?)
|
|
GROUP BY assetData.assetId
|
|
ORDER BY $sortBy $sortOrder
|
|
SQL
|
|
my $siteUrl = $self->session->url->getSiteURL();
|
|
my $datetime = $self->session->datetime;
|
|
|
|
my @posts;
|
|
for my $postId (@postIds) {
|
|
my $post = WebGUI::Asset->new($self->session, $postId, 'WebGUI::Asset::Post::Thread');
|
|
my $postUrl = $siteUrl . $post->getUrl;
|
|
# Buggo: this is an abuse of 'author'. 'author' is supposed to be an email address.
|
|
# But this is how it was in the original Collaboration RSS, so.
|
|
|
|
# Create the attachment template loop
|
|
my $storage = $post->getStorageLocation;
|
|
my $attachmentLoop = [];
|
|
if ($post->get('storageId')) {
|
|
for my $file (@{$storage->getFiles}) {
|
|
push @{$attachmentLoop}, {
|
|
'attachment.url' => $storage->getUrl($file),
|
|
'attachment.path' => $storage->getPath($file),
|
|
'attachment_thumbnail' => $storage->getThumbnailUrl($file),
|
|
'attachment.length' => $storage->getFileSize($file),
|
|
};
|
|
}
|
|
}
|
|
|
|
push @posts, {
|
|
author => $post->get('username'),
|
|
title => $post->get('title'),
|
|
'link' => $postUrl,
|
|
guid => $postUrl,
|
|
description => $post->get('synopsis'),
|
|
epochDate => $post->get('creationDate'),
|
|
pubDate => $datetime->epochToMail($post->get('creationDate')),
|
|
attachmentLoop => $attachmentLoop,
|
|
userDefined1 => $post->get("userDefined1"),
|
|
userDefined2 => $post->get("userDefined2"),
|
|
userDefined3 => $post->get("userDefined3"),
|
|
userDefined4 => $post->get("userDefined4"),
|
|
userDefined5 => $post->get("userDefined5"),
|
|
};
|
|
}
|
|
|
|
return @posts;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getSearchUrl ( )
|
|
|
|
Formats the url to the forum search engine.
|
|
|
|
=cut
|
|
|
|
sub getSearchUrl {
|
|
my $self = shift;
|
|
return $self->getUrl("func=search");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getSortByUrl ( sortBy )
|
|
|
|
Formats the url to change the default sort.
|
|
|
|
=head3 sortBy
|
|
|
|
The sort by string. Can be views, rating, date replies, or lastreply.
|
|
|
|
=cut
|
|
|
|
sub getSortByUrl {
|
|
my $self = shift;
|
|
my $sortBy = shift;
|
|
return $self->getUrl("sortBy=".$sortBy);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getSortBy
|
|
|
|
Retrieves the field to sort by
|
|
|
|
=cut
|
|
|
|
sub getSortBy {
|
|
my $self = shift;
|
|
my $scratchSortBy = $self->getId."_sortBy";
|
|
my $sortBy = $self->session->scratch->get($scratchSortBy) || $self->getValue("sortBy");
|
|
return $sortBy;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getSortOrder
|
|
|
|
Retrieves the direction to sort in
|
|
|
|
=cut
|
|
|
|
sub getSortOrder {
|
|
my $self = shift;
|
|
my $scratchSortOrder = $self->getId."_sortDir";
|
|
my $sortOrder = $self->session->scratch->get($scratchSortOrder) || $self->getValue("sortOrder");
|
|
return $sortOrder;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getSubscribeUrl ( )
|
|
|
|
Formats the url to subscribe to the forum.
|
|
|
|
=cut
|
|
|
|
sub getSubscribeUrl {
|
|
my $self = shift;
|
|
return $self->getUrl("func=subscribe");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getThreadsPaginator
|
|
|
|
Returns a WebGUI::Paginator object containing all the threads in this
|
|
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->get("sortBy");
|
|
my $sortOrder = $self->session->scratch->get($scratchSortOrder) || $self->get("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"));
|
|
} 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 $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->get("threadsPerPage"));
|
|
$p->setDataByQuery($sql);
|
|
|
|
return $p;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getUnsubscribeUrl ( )
|
|
|
|
Formats the url to unsubscribe from the forum.
|
|
|
|
=cut
|
|
|
|
sub getUnsubscribeUrl {
|
|
my $self = shift;
|
|
return $self->getUrl("func=unsubscribe");
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub getViewTemplateVars {
|
|
my $self = shift;
|
|
my %var;
|
|
$var{'user.canPost'} = $self->canPost;
|
|
$var{'user.canStartThread'} = $self->canStartThread;
|
|
$var{"add.url"} = $self->getNewThreadUrl;
|
|
$var{"rss.url"} = $self->getRssUrl;
|
|
$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");
|
|
$var{'karmaIsEnabled'} = $self->session->setting->get("useKarma");
|
|
$var{'sortby.karmaRank.url'} = $self->getSortByUrl("karmaRank");
|
|
$var{'sortby.date.url'} = $self->getSortByUrl("creationDate");
|
|
$var{'sortby.lastreply.url'} = $self->getSortByUrl("lastPostDate");
|
|
$var{'sortby.views.url'} = $self->getSortByUrl("views");
|
|
$var{'sortby.replies.url'} = $self->getSortByUrl("replies");
|
|
$var{'sortby.rating.url'} = $self->getSortByUrl("rating");
|
|
$var{"search.url"} = $self->getSearchUrl;
|
|
$var{"subscribe.url"} = $self->getSubscribeUrl;
|
|
$var{"unsubscribe.url"} = $self->getUnsubscribeUrl;
|
|
$var{"collaborationAssetId"} = $self->getId;
|
|
|
|
# Get the threads in this CS
|
|
my $p = $self->getThreadsPaginator;
|
|
$self->appendPostListTemplateVars(\%var, $p);
|
|
$self->appendTemplateLabels(\%var);
|
|
|
|
return \%var;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 incrementReplies ( lastPostDate, lastPostId )
|
|
|
|
Increments the reply counter for this forum.
|
|
|
|
=head3 lastPostDate
|
|
|
|
The date of the post being added.
|
|
|
|
=head3 lastPostId
|
|
|
|
The unique identifier of the post being added.
|
|
|
|
=cut
|
|
|
|
sub incrementReplies {
|
|
my ($self, $lastPostDate, $lastPostId) = @_;
|
|
my $threads = $self->_computeThreadCount;
|
|
my $replies = $self->_computePostCount;
|
|
$self->update({replies=>$replies, threads=>$threads, lastPostId=>$lastPostId, lastPostDate=>$lastPostDate});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 incrementThreads ( lastPostDate, lastPostId )
|
|
|
|
Increments the thread counter for this forum.
|
|
|
|
=head3 lastPostDate
|
|
|
|
The date of the post that was just added.
|
|
|
|
=head3 lastPostId
|
|
|
|
The unique identifier of the post that was just added.
|
|
|
|
=cut
|
|
|
|
sub incrementThreads {
|
|
my ($self, $lastPostDate, $lastPostId) = @_;
|
|
$self->update({threads=>$self->_computeThreadCount, lastPostId=>$lastPostId, lastPostDate=>$lastPostDate});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 incrementViews ( )
|
|
|
|
Increments the views counter on this forum.
|
|
|
|
=cut
|
|
|
|
sub incrementViews {
|
|
my ($self) = @_;
|
|
$self->update({views=>$self->get("views")+1});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 isSubscribed ( )
|
|
|
|
Returns a boolean indicating whether the user is subscribed to the forum.
|
|
|
|
=cut
|
|
|
|
sub isSubscribed {
|
|
my $self = shift;
|
|
return $self->session->user->isInGroup($self->get("subscriptionGroupId"));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 prepareView ( )
|
|
|
|
See WebGUI::Asset::prepareView() for details.
|
|
|
|
=cut
|
|
|
|
sub prepareView {
|
|
my $self = shift;
|
|
$self->SUPER::prepareView();
|
|
my $template = WebGUI::Asset::Template->new($self->session, $self->get("collaborationTemplateId")) or die "no good: ".$self->get("collaborationTemplateId");
|
|
if ($self->get('rssCapableRssEnabled')) {
|
|
$self->session->style->setLink($self->getRssUrl,{ rel=>'alternate', type=>'application/rss+xml', title=>$self->get('title') . ' RSS' });
|
|
}
|
|
$template->prepare($self->getMetaDataAsTemplateVariables);
|
|
$self->{_viewTemplate} = $template;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub processPropertiesFromFormPost {
|
|
my $self = shift;
|
|
my $updatePrivs = ($self->session->form->process("groupIdView") ne $self->get("groupIdView") || $self->session->form->process("groupIdEdit") ne $self->get("groupIdEdit"));
|
|
$self->SUPER::processPropertiesFromFormPost;
|
|
if ($self->get("subscriptionGroupId") eq "") {
|
|
$self->createSubscriptionGroup;
|
|
}
|
|
if ($updatePrivs) {
|
|
foreach my $descendant (@{$self->getLineage(["descendants"],{returnObjects=>1})}) {
|
|
$descendant->update({
|
|
groupIdView=>$self->get("groupIdView"),
|
|
groupIdEdit=>$self->get("groupIdEdit")
|
|
});
|
|
}
|
|
}
|
|
$self->session->scratch->delete($self->getId."_sortBy");
|
|
$self->session->scratch->delete($self->getId."_sortDir");
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub purge {
|
|
my $self = shift;
|
|
my $group = WebGUI::Group->new($self->session, $self->get("subscriptionGroupId"));
|
|
if ($group) {
|
|
$group->delete;
|
|
}
|
|
if ($self->get("getMailCronId")) {
|
|
my $cron = WebGUI::Workflow::Cron->new($self->session, $self->get("getMailCronId"));
|
|
$cron->delete if defined $cron;
|
|
}
|
|
$self->SUPER::purge;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 purgeCache ( )
|
|
|
|
See WebGUI::Asset::purgeCache() for details.
|
|
|
|
=cut
|
|
|
|
sub purgeCache {
|
|
my $self = shift;
|
|
WebGUI::Cache->new($self->session,"view_".$self->getId)->delete;
|
|
WebGUI::Cache->new($self->session,$self->_visitorCacheKey)->delete;
|
|
$self->SUPER::purgeCache;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 recalculateRating ( )
|
|
|
|
Calculates the rating of this forum from its threads and stores the new value in the forum properties.
|
|
|
|
=cut
|
|
|
|
sub recalculateRating {
|
|
my $self = shift;
|
|
|
|
# Get the number of threads
|
|
my ($count)
|
|
= $self->session->db->quickArray(
|
|
"select count(*) from Thread
|
|
left join asset on Thread.assetId=asset.assetId
|
|
left join Post on Thread.assetId=Post.assetId
|
|
AND Thread.revisionDate = (SELECT MAX(revisionDate) FROM Thread t WHERE t.assetId=asset.assetId)
|
|
where asset.parentId=?",
|
|
[$self->getId]
|
|
);
|
|
$count = $count || 1;
|
|
|
|
# Get the ratings of all the threads
|
|
my ($sum)
|
|
= $self->session->db->quickArray(
|
|
"SELECT SUM(Thread.threadRating)
|
|
FROM Thread
|
|
LEFT JOIN asset ON Thread.assetId=asset.assetId
|
|
LEFT JOIN Post ON Thread.assetId=Post.assetId
|
|
AND Thread.revisionDate = (SELECT MAX(revisionDate) FROM Thread t WHERE t.assetId=asset.assetId)
|
|
WHERE asset.parentId=?",
|
|
[$self->getId]
|
|
);
|
|
|
|
my $average = round($sum/$count);
|
|
$self->update({rating=>$average});
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 setLastPost ( id, date )
|
|
|
|
Sets the most recent post in this collaboration system.
|
|
|
|
=head3 id
|
|
|
|
The assetId of the most recent post.
|
|
|
|
=head3 date
|
|
|
|
The date of the most recent post.
|
|
|
|
=cut
|
|
|
|
sub setLastPost {
|
|
my $self = shift;
|
|
my $id = shift;
|
|
my $date = shift;
|
|
$self->update({lastPostId=>$id, lastPostDate=>$date});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 sumReplies ( )
|
|
|
|
Calculates the number of replies to this collaboration system and updates the counter to reflect that. Also updates thread count since it needs to know that to calculate reply count.
|
|
|
|
=cut
|
|
|
|
sub sumReplies {
|
|
my $self = shift;
|
|
my $threads = $self->_computeThreadCount;
|
|
my $replies = $self->_computePostCount;
|
|
$self->update({replies=>$replies, threads=>$threads});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 sumThreads ( )
|
|
|
|
Calculates the number of threads in this collaboration system and updates the counter to reflect that.
|
|
|
|
=cut
|
|
|
|
sub sumThreads {
|
|
my $self = shift;
|
|
$self->update({threads=>$self->_computeThreadCount});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 subscribe ( )
|
|
|
|
Subscribes a user to this collaboration system.
|
|
|
|
=cut
|
|
|
|
sub subscribe {
|
|
my $self = shift;
|
|
my $group;
|
|
my $subscriptionGroup = $self->get('subscriptionGroupId');
|
|
if ($subscriptionGroup) {
|
|
$group = WebGUI::Group->new($self->session,$subscriptionGroup);
|
|
}
|
|
if (!$group) {
|
|
$self->createSubscriptionGroup;
|
|
$group = WebGUI::Group->new($self->session,$self->get('subscriptionGroupId'));
|
|
}
|
|
$group->addUsers([$self->session->user->userId]);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 unsubscribe ( )
|
|
|
|
Unsubscribes a user from this collaboration system
|
|
|
|
=cut
|
|
|
|
sub unsubscribe {
|
|
my $self = shift;
|
|
my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId"));
|
|
return
|
|
unless $group;
|
|
$group->deleteUsers([$self->session->user->userId],[$self->get("subscriptionGroupId")]);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
sub view {
|
|
my $self = shift;
|
|
if ($self->_visitorCacheOk) {
|
|
my $out = WebGUI::Cache->new($self->session,$self->_visitorCacheKey)->get;
|
|
$self->session->errorHandler->debug("HIT") if $out;
|
|
return $out if $out;
|
|
}
|
|
|
|
# If the asset is not called through the normal prepareView/view cycle, first call prepareView.
|
|
# This happens for instance in the viewDetail method in the Matrix. In that case the Collaboration
|
|
# is called through the api.
|
|
$self->prepareView unless ($self->{_viewTemplate});
|
|
my $out = $self->processTemplate($self->getViewTemplateVars,undef,$self->{_viewTemplate});
|
|
if ($self->_visitorCacheOk) {
|
|
WebGUI::Cache->new($self->session,$self->_visitorCacheKey)->set($out,$self->get("visitorCacheTimeout"));
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_search ( )
|
|
|
|
The web method to display and use the forum search interface.
|
|
|
|
=cut
|
|
|
|
sub www_search {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $i18n = WebGUI::International->new($session, 'Asset_Collaboration');
|
|
my $var = {};
|
|
|
|
my $query = $self->session->form->process("query","text");
|
|
$var->{'form.header'} = WebGUI::Form::formHeader($self->session,{
|
|
action=>$self->getUrl("func=search;doit=1")
|
|
});
|
|
$var->{'query.form'} = WebGUI::Form::text($self->session,{
|
|
name => 'query',
|
|
value => $query
|
|
});
|
|
$var->{'form.search'} = WebGUI::Form::submit($self->session,{
|
|
value => $i18n->get(170,'WebGUI')
|
|
});
|
|
$var->{'form.footer'} = WebGUI::Form::formFooter($self->session);
|
|
$var->{'back.url' } = $self->getUrl;
|
|
|
|
$self->appendTemplateLabels($var);
|
|
$var->{'doit' } = $self->session->form->process("doit");
|
|
if ($self->session->form->process("doit")) {
|
|
my $search = WebGUI::Search->new($self->session);
|
|
$search->search({
|
|
keywords=>$query,
|
|
lineage=>[$self->get("lineage")],
|
|
classes=>["WebGUI::Asset::Post", "WebGUI::Asset::Post::Thread"]
|
|
});
|
|
my $p = $search->getPaginatorResultSet($self->getUrl("func=search;doit=1;query=".$query), $self->get("threadsPerPage"));
|
|
$self->appendPostListTemplateVars($var, $p);
|
|
}
|
|
return $self->processStyle($self->processTemplate($var, $self->get("searchTemplateId")));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_subscribe ( )
|
|
|
|
The web method to subscribe to a collaboration.
|
|
|
|
=cut
|
|
|
|
sub www_subscribe {
|
|
my $self = shift;
|
|
$self->subscribe if $self->canSubscribe;
|
|
return $self->www_view;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_unsubscribe ( )
|
|
|
|
The web method to unsubscribe from a collaboration.
|
|
|
|
=cut
|
|
|
|
sub www_unsubscribe {
|
|
my $self = shift;
|
|
if($self->canSubscribe){
|
|
$self->unsubscribe;
|
|
return $self->www_view;
|
|
}else{
|
|
return $self->session->privilege->noAccess;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub www_view {
|
|
my $self = shift;
|
|
my $disableCache = ($self->session->form->process("sortBy") ne "");
|
|
$self->session->http->setCacheControl($self->get("visitorCacheTimeout")) if ($self->session->user->isVisitor && !$disableCache);
|
|
return $self->SUPER::www_view(@_);
|
|
}
|
|
|
|
1;
|
|
|