Added Newsletter Asset (Funded by United Knowledge)
This commit is contained in:
parent
245c7b947e
commit
9248570f79
16 changed files with 1295 additions and 149 deletions
|
|
@ -35,7 +35,11 @@
|
|||
- Added a simple Single Sign On mechanism.
|
||||
- Added the SessionId macro.
|
||||
- fix: Package deploy: hidden assets become visible (Yung Han Khoe, United Knowledge)
|
||||
- RFE: Added Private Messaging to WebGUI (United Knowledge)
|
||||
- Added Private Messaging (Funded by United Knowledge)
|
||||
- Added Newsletter Asset (Funded by United Knowledge)
|
||||
- Extended content profiling to CS Threads (Funded by United Knowledge)
|
||||
- Added User Invitations (Funded by United Knowledge)
|
||||
|
||||
|
||||
7.3.19
|
||||
- Fixed a formatting problem in the workflow editor screen.
|
||||
|
|
|
|||
90
docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl
Normal file
90
docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#PBtmpl0000000000000029
|
||||
<a name="id<tmpl_var assetId>" id="id<tmpl_var assetId>"></a>
|
||||
|
||||
<tmpl_if preview.title>
|
||||
<p><b><tmpl_var preview.title></b></p>
|
||||
</tmpl_if>
|
||||
|
||||
<tmpl_if preview.content>
|
||||
<p><tmpl_var preview.content></p>
|
||||
</tmpl_if>
|
||||
|
||||
<h2><tmpl_var message.header.label></h2>
|
||||
|
||||
<tmpl_var form.header>
|
||||
<table class="defaultPostForm">
|
||||
<tmpl_if isNewPost>
|
||||
<tmpl_if user.isVisitor>
|
||||
<tr>
|
||||
<td><tmpl_var visitorName.label></td>
|
||||
<td><tmpl_var visitorName.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
<tr>
|
||||
<td><tmpl_var subject.label></td>
|
||||
<td><tmpl_var title.form></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tmpl_var message.label></td>
|
||||
<td><tmpl_var content.form></td>
|
||||
</tr>
|
||||
<tmpl_unless isReply>
|
||||
<tmpl_loop meta_loop>
|
||||
<tr>
|
||||
<td><tmpl_var name></td>
|
||||
<td><tmpl_var field></td>
|
||||
</tr>
|
||||
</tmpl_loop>
|
||||
</tmpl_unless>
|
||||
<tmpl_if attachment.form>
|
||||
<tr>
|
||||
<td><tmpl_var attachment.label></td>
|
||||
<td><tmpl_var attachment.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
<tmpl_if isNewPost>
|
||||
<tmpl_unless user.isVisitor>
|
||||
<tr>
|
||||
<td><tmpl_var subscribe.label></td>
|
||||
<td><tmpl_var subscribe.form></td>
|
||||
</tr>
|
||||
</tmpl_unless>
|
||||
<tmpl_if isNewThread>
|
||||
<tmpl_if user.isModerator>
|
||||
<tr>
|
||||
<td><tmpl_var lock.label></td>
|
||||
<td><tmpl_var lock.form></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tmpl_var stick.label></td>
|
||||
<td><tmpl_var sticky.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><tmpl_if usePreview><tmpl_var form.preview></tmpl_if><tmpl_var form.submit></td>
|
||||
</tr>
|
||||
</table>
|
||||
<tmpl_var form.footer>
|
||||
|
||||
<tmpl_if isReply>
|
||||
<p><b><tmpl_var reply.title></b></p>
|
||||
<tmpl_var reply.content>
|
||||
</tmpl_if>
|
||||
|
||||
|
||||
~~~
|
||||
<style type="text/css">
|
||||
table.defaultPostForm td
|
||||
{
|
||||
font-family:arial;
|
||||
font-size:9pt;
|
||||
}
|
||||
h2
|
||||
{
|
||||
font-family:arial;
|
||||
}
|
||||
</style>
|
||||
103
docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl
Normal file
103
docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#PBtmpl0000000000000068
|
||||
<a name="id<tmpl_var assetId>" id="id<tmpl_var assetId>"></a>
|
||||
|
||||
<tmpl_if preview.title><p><b><tmpl_var preview.title></b></p></tmpl_if>
|
||||
<tmpl_unless isReply><tmpl_if preview.synopsis><p><i><tmpl_var preview.synopsis></i></p></tmpl_if></tmpl_unless>
|
||||
<tmpl_if preview.content><p><tmpl_var preview.content></p></tmpl_if>
|
||||
|
||||
<tmpl_if isReply>
|
||||
<h1><tmpl_var message.header.label></h1>
|
||||
<tmpl_else>
|
||||
<h1><tmpl_var submission.header.label></h1>
|
||||
</tmpl_if>
|
||||
|
||||
<tmpl_var form.header>
|
||||
<table class="defaultSubmissionForm">
|
||||
<tmpl_if isNewPost>
|
||||
<tmpl_if user.isVisitor>
|
||||
<tr>
|
||||
<td><tmpl_var visitorName.label></td>
|
||||
<td><tmpl_var visitorName.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
<tr>
|
||||
<td><tmpl_var title.label></td>
|
||||
<td><tmpl_var title.form></td>
|
||||
</tr>
|
||||
<tmpl_unless isReply>
|
||||
<tr>
|
||||
<td><tmpl_var synopsis.label></td>
|
||||
<td><tmpl_var synopsis.form></td>
|
||||
</tr>
|
||||
</tmpl_unless>
|
||||
<tr>
|
||||
<td><tmpl_var body.label></td>
|
||||
<td><tmpl_var content.form></td>
|
||||
</tr>
|
||||
<tmpl_unless isReply>
|
||||
<tmpl_loop meta_loop>
|
||||
<tr>
|
||||
<td><tmpl_var name></td>
|
||||
<td><tmpl_var field></td>
|
||||
</tr>
|
||||
</tmpl_loop>
|
||||
<tmpl_if attachment.form>
|
||||
<tr>
|
||||
<td><tmpl_var attachment.label></td>
|
||||
<td><tmpl_var attachment.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
</tmpl_unless>
|
||||
<tmpl_if isNewPost>
|
||||
<tmpl_unless user.isVisitor>
|
||||
<tr>
|
||||
<td><tmpl_var subscribe.label></td>
|
||||
<td><tmpl_var subscribe.form></td>
|
||||
</tr>
|
||||
</tmpl_unless>
|
||||
<tmpl_if isNewThread>
|
||||
<tmpl_if user.isModerator>
|
||||
<tr>
|
||||
<td><tmpl_var lock.label></td>
|
||||
<td><tmpl_var lock.form></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tmpl_var stick.label></td>
|
||||
<td><tmpl_var sticky.form></td>
|
||||
</tr>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
</tmpl_if>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><tmpl_if usePreview><tmpl_var form.preview></tmpl_if><tmpl_var form.submit></td>
|
||||
</tr>
|
||||
</table>
|
||||
<tmpl_var form.footer>
|
||||
|
||||
<tmpl_if isReply>
|
||||
<div class="defaultSubmissionFormContent">
|
||||
<b><tmpl_var reply.title></b><br /><br />
|
||||
<tmpl_var reply.content>
|
||||
</div>
|
||||
</tmpl_if>
|
||||
|
||||
~~~
|
||||
<style type="text/css">
|
||||
table.defaultSubmissionForm td
|
||||
{
|
||||
font-family:arial;
|
||||
font-size:9pt;
|
||||
}
|
||||
.defaultSubmissionFormContent
|
||||
{
|
||||
font-family:arial;
|
||||
font-size:9pt;
|
||||
}
|
||||
h2
|
||||
{
|
||||
font-family:arial;
|
||||
}
|
||||
|
||||
</style>
|
||||
18
docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl
Normal file
18
docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#newsletter000000000001
|
||||
#url: newsletterdefaulttemplate
|
||||
#title: Summary Newsletter (default)
|
||||
#menuTitle: Summary Newsletter
|
||||
#namespace:newsletter
|
||||
#create
|
||||
|
||||
<p><tmpl_var header></p>
|
||||
|
||||
<tmpl_loop thread_loop>
|
||||
<p>
|
||||
<a href="<tmpl_var url>"><tmpl_var title></a><br />
|
||||
<p><tmpl_var synopsis></p>
|
||||
</p>
|
||||
</tmpl_loop>
|
||||
|
||||
<p><tmpl_var footer></p>
|
||||
|
||||
67
docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl
Normal file
67
docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#newslettercs0000000001
|
||||
#url: newslettercstemplate
|
||||
#title: Newsletter Manager (default)
|
||||
#menuTitle: Newsletter Manager
|
||||
#namespace:Collaboration
|
||||
#create
|
||||
<a name="id<tmpl_var assetId>" id="id<tmpl_var assetId>"></a>
|
||||
|
||||
<tmpl_if session.var.adminOn>
|
||||
<p><tmpl_var controls></p>
|
||||
</tmpl_if>
|
||||
|
||||
<tmpl_if displayTitle>
|
||||
<h2><tmpl_var title></h2>
|
||||
</tmpl_if>
|
||||
|
||||
<tmpl_if description>
|
||||
<tmpl_var description>
|
||||
</tmpl_if>
|
||||
|
||||
<p class="pagination">
|
||||
<tmpl_if user.canPost>
|
||||
<a href="<tmpl_var add.url>"><tmpl_var add.label></a>
|
||||
|
|
||||
</tmpl_if>
|
||||
<tmpl_unless user.isVisitor>
|
||||
<a href="<tmpl_var mySubscriptionsUrl>">^International("my subscriptions","Asset_Newsletter");</a>
|
||||
|
|
||||
</tmpl_unless>
|
||||
<a href="<tmpl_var search.url>"><tmpl_var search.label></a>
|
||||
</p>
|
||||
|
||||
<p />
|
||||
|
||||
<tmpl_loop post_loop>
|
||||
<p><b><a href="<tmpl_var url>"><tmpl_var title></a></b><br />
|
||||
<tmpl_var synopsis></p>
|
||||
</tmpl_loop>
|
||||
|
||||
<tmpl_if pagination.pageCount.isMultiple>
|
||||
<div class="pagination">
|
||||
<tmpl_var pagination.previousPage> • <tmpl_var pagination.pageList.upTo10> • <tmpl_var pagination.nextPage>
|
||||
</div>
|
||||
</tmpl_if>
|
||||
~~~
|
||||
<style type="text/css">
|
||||
.pagination {
|
||||
-moz-box-sizing:border-box;
|
||||
background:#676767;
|
||||
color:#C0C0C0;
|
||||
width:100%;
|
||||
text-align:right;
|
||||
padding:3px;
|
||||
font-size:9pt;
|
||||
font-family:arial;
|
||||
}
|
||||
.pagination a {
|
||||
color:white;
|
||||
font-size:8pt;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
.pagination a:hover {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
</style>
|
||||
22
docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl
Normal file
22
docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#newslettersubscrip0001
|
||||
#url: newslettermysubscriptionstemplate
|
||||
#title: My Subscriptions (default)
|
||||
#menuTitle: My Subscriptions
|
||||
#namespace:newsletter/mysubscriptions
|
||||
#create
|
||||
|
||||
<h1>^International("my subscriptions","Asset_Newsletter");</h1>
|
||||
|
||||
<tmpl_var formHeader>
|
||||
<h2>^International("newsletter categories","Asset_Newsletter");</h2>
|
||||
<tmpl_loop categoriesLoop>
|
||||
<p><b><tmpl_var categoryName></b><br />
|
||||
<blockquote>
|
||||
<tmpl_loop optionsLoop>
|
||||
<label><tmpl_var optionForm> <tmpl_var optionName></label><br />
|
||||
</tmpl_loop>
|
||||
</blockquote></p>
|
||||
</tmpl_loop>
|
||||
<tmpl_var formSubmit>
|
||||
<tmpl_var formFooter>
|
||||
|
||||
|
|
@ -28,10 +28,41 @@ addAttachmentsToEvents($session);
|
|||
addMetaDataPostsToCS($session);
|
||||
addUserInvitations($session);
|
||||
addPrivateMessaging($session);
|
||||
addNewsletter($session);
|
||||
|
||||
finish($session); # this line required
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
sub addNewsletter {
|
||||
my $session = shift;
|
||||
print "\tAdding a newsletter management system.\n" unless ($quiet);
|
||||
$session->config->addToArray("assets","WebGUI::Asset::Wobject::Collaboration::Newsletter");
|
||||
my $db = $session->db;
|
||||
$db->write("create table Newsletter (
|
||||
assetId varchar(22) binary not null,
|
||||
revisionDate bigint not null,
|
||||
newsletterTemplateId varchar(22) binary not null default 'newsletter000000000001',
|
||||
mySubscriptionsTemplateId varchar(22) binary not null default 'newslettersubscrip0001',
|
||||
newsletterHeader mediumtext,
|
||||
newsletterFooter mediumtext,
|
||||
newsletterCategories text,
|
||||
primary key (assetId, revisionDate)
|
||||
)");
|
||||
$db->write("create table Newsletter_subscriptions (
|
||||
assetId varchar(22) binary not null,
|
||||
userId varchar(22) binary not null,
|
||||
subscriptions text,
|
||||
lastTimeSent bigint not null default 0,
|
||||
primary key (assetId, userId)
|
||||
)");
|
||||
$db->write("alter table Newsletter_subscriptions add index lastTimeSent_assetId_userId
|
||||
(lastTimeSent,assetId,userId)");
|
||||
my $workflow = WebGUI::Workflow->new($session, "pbworkflow000000000002");
|
||||
my $activity = $workflow->addActivity("WebGUI::Workflow::Activity::SendNewsletters","newslettersendactivity");
|
||||
$activity->set("title","Send Newsletters For Newsletter Assets");
|
||||
}
|
||||
|
||||
#-------------------------------------------------
|
||||
sub addRealtimeWorkflow {
|
||||
my $session = shift;
|
||||
|
|
|
|||
|
|
@ -1694,10 +1694,11 @@ anything.
|
|||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my %data;
|
||||
my $form = $self->session->form;
|
||||
foreach my $definition (@{$self->definition($self->session)}) {
|
||||
foreach my $property (keys %{$definition->{properties}}) {
|
||||
if ($definition->{properties}{$property}{noFormPost}) {
|
||||
if ($self->session->form->process("assetId") eq "new" && $self->get($property) eq "") {
|
||||
if ($form->process("assetId") eq "new" && $self->get($property) eq "") {
|
||||
$data{$property} = $definition->{properties}{$property}{defaultValue};
|
||||
}
|
||||
next;
|
||||
|
|
@ -1705,7 +1706,7 @@ sub processPropertiesFromFormPost {
|
|||
my %params = %{$definition->{properties}{$property}};
|
||||
$params{name} = $property;
|
||||
$params{value} = $self->get($property);
|
||||
$data{$property} = $self->session->form->process(
|
||||
$data{$property} = $form->process(
|
||||
$property,
|
||||
$definition->{properties}{$property}{fieldType},
|
||||
$definition->{properties}{$property}{defaultValue},
|
||||
|
|
@ -1713,11 +1714,13 @@ sub processPropertiesFromFormPost {
|
|||
);
|
||||
}
|
||||
}
|
||||
foreach my $form ($self->session->form->param) {
|
||||
if ($form =~ /^metadata_(.*)$/) {
|
||||
$self->updateMetaData($1,$self->session->form->process($form));
|
||||
}
|
||||
}
|
||||
if ($self->session->setting->get("metaDataEnabled")) {
|
||||
my $meta = $self->getMetaDataFields;
|
||||
foreach my $field (keys %{$meta}) {
|
||||
my $value = $form->process("metadata_".$field, $meta->{$field}{fieldType}, $meta->{$field}{defaultValue});
|
||||
$self->updateMetaData($field, $value);
|
||||
}
|
||||
}
|
||||
$self->session->db->beginTransaction;
|
||||
$self->update(\%data);
|
||||
$self->session->db->commit;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,54 @@ 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->userId eq '1'
|
||||
&& !$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;
|
||||
|
|
@ -554,7 +602,7 @@ sub definition {
|
|||
fieldType=>"template",
|
||||
namespace=>"Collaboration/Notification",
|
||||
defaultValue=>'PBtmpl0000000000000027',
|
||||
tab=>'display',
|
||||
tab=>'mail',
|
||||
label=>$i18n->get('notification template'),
|
||||
hoverHelp=>$i18n->get('notification template description'),
|
||||
},
|
||||
|
|
@ -664,6 +712,27 @@ sub duplicate {
|
|||
return $newAsset;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getEditTabs {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Collaboration");
|
||||
|
||||
return (['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;
|
||||
|
|
@ -726,27 +795,6 @@ SQL
|
|||
return @posts;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getEditTabs {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Collaboration");
|
||||
|
||||
return (['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");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getSearchUrl ( )
|
||||
|
|
@ -806,14 +854,78 @@ sub getUnsubscribeUrl {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _computeThreadCount {
|
||||
sub getViewTemplateVars {
|
||||
my $self = shift;
|
||||
return scalar @{$self->getLineage(['children'], {includeOnlyClasses => ['WebGUI::Asset::Post::Thread']})};
|
||||
}
|
||||
|
||||
sub _computePostCount {
|
||||
my $self = shift;
|
||||
return scalar @{$self->getLineage(['descendants'], {includeOnlyClasses => ['WebGUI::Asset::Post']})};
|
||||
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 ||= "dateUpdated";
|
||||
$sortOrder ||= "desc";
|
||||
my %var;
|
||||
$var{'user.canPost'} = $self->canPost;
|
||||
$var{"add.url"} = $self->getNewThreadUrl;
|
||||
$var{"rss.url"} = $self->getRssUrl;
|
||||
$var{'user.isModerator'} = $self->canModerate;
|
||||
$var{'user.isVisitor'} = ($self->session->user->userId eq '1');
|
||||
$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("dateSubmitted");
|
||||
$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;
|
||||
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);
|
||||
$self->appendPostListTemplateVars(\%var, $p);
|
||||
$self->appendTemplateLabels(\%var);
|
||||
return \%var;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1053,18 +1165,6 @@ sub unsubscribe {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _visitorCacheOk {
|
||||
my $self = shift;
|
||||
return ($self->session->user->userId eq '1'
|
||||
&& !$self->session->form->process('sortBy'));
|
||||
}
|
||||
|
||||
sub _visitorCacheKey {
|
||||
my $self = shift;
|
||||
my $pn = $self->session->form->process('pn');
|
||||
return "view_".$self->getId."?pn=".$pn;
|
||||
}
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
if ($self->_visitorCacheOk) {
|
||||
|
|
@ -1072,87 +1172,16 @@ sub view {
|
|||
$self->session->errorHandler->debug("HIT") if $out;
|
||||
return $out if $out;
|
||||
}
|
||||
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 ||= "dateUpdated";
|
||||
$sortOrder ||= "desc";
|
||||
my %var;
|
||||
$var{'user.canPost'} = $self->canPost;
|
||||
$var{"add.url"} = $self->getNewThreadUrl;
|
||||
$var{"rss.url"} = $self->getRssUrl;
|
||||
$var{'user.isModerator'} = $self->canModerate;
|
||||
$var{'user.isVisitor'} = ($self->session->user->userId eq '1');
|
||||
$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("dateSubmitted");
|
||||
$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;
|
||||
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);
|
||||
$self->appendPostListTemplateVars(\%var, $p);
|
||||
$self->appendTemplateLabels(\%var);
|
||||
|
||||
# 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(\%var,undef,$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"));
|
||||
$self->session->errorHandler->debug("MISS");
|
||||
WebGUI::Cache->new($self->session,$self->_visitorCacheKey)->set($out,$self->get("visitorCacheTimeout"));
|
||||
}
|
||||
return $out;
|
||||
return $out;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1221,28 +1250,6 @@ sub www_unsubscribe {
|
|||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# 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);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# 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 www_view {
|
||||
my $self = shift;
|
||||
|
|
|
|||
242
lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm
Normal file
242
lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
package WebGUI::Asset::Wobject::Collaboration::Newsletter;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2006 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::Form;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Utility;
|
||||
use base 'WebGUI::Asset::Wobject::Collaboration';
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( )
|
||||
|
||||
defines wobject properties for Newsletter instances. You absolutely need
|
||||
this method in your new Wobjects. If you choose to "autoGenerateForms", the
|
||||
getEditForm method is unnecessary/redundant/useless.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Newsletter');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
newsletterHeader => {
|
||||
defaultValue=>undef,
|
||||
fieldType=>"HTMLArea",
|
||||
tab=>"mail",
|
||||
label=>$i18n->get("newsletter header"),
|
||||
hoverHelp=>$i18n->get("newsletter header help"),
|
||||
},
|
||||
newsletterFooter => {
|
||||
defaultValue=>undef,
|
||||
fieldType=>"HTMLArea",
|
||||
tab=>"mail",
|
||||
label=>$i18n->get("newsletter footer"),
|
||||
hoverHelp=>$i18n->get("newsletter footer help"),
|
||||
},
|
||||
newsletterTemplateId => {
|
||||
defaultValue=>'newsletter000000000001',
|
||||
fieldType=>"template",
|
||||
namespace=>"newsletter",
|
||||
tab=>"mail",
|
||||
label=>$i18n->get("newsletter template"),
|
||||
hoverHelp=>$i18n->get("newsletter template help"),
|
||||
},
|
||||
mySubscriptionsTemplateId => {
|
||||
defaultValue=>'newslettersubscrip0001',
|
||||
fieldType=>"template",
|
||||
namespace=>"newsletter/mysubscriptions",
|
||||
tab=>"display",
|
||||
label=>$i18n->get("my subscriptions template"),
|
||||
hoverHelp=>$i18n->get("my subscriptions template help"),
|
||||
},
|
||||
);
|
||||
if ($session->setting->get("metaDataEnabled")) {
|
||||
$properties{newsletterCategories} = {
|
||||
defaultValue=>undef,
|
||||
fieldType=>"checkList",
|
||||
tab=>"properties",
|
||||
options=>$session->db->buildHashRef("select fieldId, fieldName from metaData_properties where
|
||||
fieldType in ('selectBox', 'checkList', 'radioList') order by fieldName"),
|
||||
label=>$i18n->get("newsletter categories"),
|
||||
hoverHelp=>$i18n->get("newsletter categories help"),
|
||||
vertical=>1,
|
||||
};
|
||||
}
|
||||
else {
|
||||
$properties{newsletterCategories} = {
|
||||
fieldType=>"readOnly",
|
||||
value=>'<b style="color: #800000;">'.$i18n->get("content profiling needed").'</b>',
|
||||
};
|
||||
}
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'newsletter.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'Newsletter',
|
||||
className=>'WebGUI::Asset::Wobject::Collaboration::Newsletter',
|
||||
properties=>\%properties
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
duplicates a Newsletter. This method is unnecessary, but if you have
|
||||
auxiliary, ancillary, or "collateral" data or files related to your
|
||||
wobject instances, you will need to duplicate them here.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getUserSubscriptions {
|
||||
my $self = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
my ($subscriptionString) = $self->session->db->quickArray("select subscriptions from Newsletter_subscriptions where
|
||||
assetId=? and userId=?", [$self->getId, $userId]);
|
||||
return split("\n", $subscriptionString);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub getViewTemplateVars {
|
||||
my $self = shift;
|
||||
my $var = $self->SUPER::getViewTemplateVars;
|
||||
$var->{mySubscriptionsUrl} = $self->getUrl("func=mySubscriptions");
|
||||
return $var;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
$self->session->db->write("delete from Newsletter_subscriptions where assetId=?", [$self->getId]);
|
||||
$self->SUPER::purge(@_);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub setUserSubscriptions {
|
||||
my $self = shift;
|
||||
my $subscriptions = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
$self->session->db->write("replace into Newsletter_subscriptions (assetId, userId, subscriptions, lastSendTime)
|
||||
values (?,?,?,?)", [$self->getId, $userId, $subscriptions, time()]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
method called by the www_view method. Returns a processed template
|
||||
to be displayed within the page style.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $var = $self->getViewTemplateVars;
|
||||
|
||||
#This is an example of debugging code to help you diagnose problems.
|
||||
#WebGUI::ErrorHandler::warn($self->get("templateId"));
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
||||
Web facing method which is the default edit page. This method is entirely
|
||||
optional. Take it out unless you specifically want to set a submenu in your
|
||||
adminConsole views.
|
||||
|
||||
=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_Newsletter");
|
||||
return $self->getAdminConsole->render($self->getEditForm->print, $i18n->get("edit title"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_mySubscriptions {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient unless ($self->canView && $self->session->user->userId ne "1");
|
||||
my %var = ();
|
||||
my $meta = $self->getMetaDataFields;
|
||||
my @categories = ();
|
||||
my @userPrefs = $self->getUserSubscriptions;
|
||||
foreach my $id (keys %{$meta}) {
|
||||
my @options = ();
|
||||
if (isIn($id, split("\n", $self->get("newsletterCategories")))) {
|
||||
foreach my $option (split("\n", $meta->{$id}{possibleValues})) {
|
||||
$option =~ s/\s+$//; # remove trailing spaces
|
||||
next if $option eq ""; # skip blank values
|
||||
my $preferenceName = $id."~".$option;
|
||||
push(@options, {
|
||||
optionName => $option,
|
||||
optionForm => WebGUI::Form::checkbox($self->session, {
|
||||
name => "subscriptions",
|
||||
value => $preferenceName,
|
||||
checked => isIn($preferenceName, @userPrefs),
|
||||
})
|
||||
});
|
||||
}
|
||||
push (@categories, {
|
||||
categoryName => $meta->{$id}{fieldName},
|
||||
optionsLoop => \@options
|
||||
});
|
||||
}
|
||||
}
|
||||
$var{categoriesLoop} = \@categories;
|
||||
if (scalar(@categories)) {
|
||||
$var{formHeader} = WebGUI::Form::formHeader($self->session, {action=>$self->getUrl, method=>"post"})
|
||||
.WebGUI::Form::hidden($self->session, {name=>"func", value=>"mySubscriptionsSave"});
|
||||
$var{formFooter} = WebGUI::Form::formFooter($self->session);
|
||||
$var{formSubmit} = WebGUI::Form::submit($self->session);
|
||||
}
|
||||
return $self->processStyle($self->processTemplate(\%var, $self->get("mySubscriptionsTemplateId")));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_mySubscriptionsSave {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient unless ($self->canView && $self->session->user->userId ne "1");
|
||||
my $subscriptions = $self->session->form->process("subscriptions", "checkList");
|
||||
$self->setUserSubscriptions($subscriptions);
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -60,7 +60,7 @@ wasting space in the db for this field.
|
|||
|
||||
=head3 fieldType
|
||||
|
||||
The form field type for metaData, select list, text, integer.
|
||||
The form field type for metaData: selectBox, text, integer, or checkList, yesNo, radioList.
|
||||
|
||||
=head3 possibleValues
|
||||
|
||||
|
|
@ -251,13 +251,14 @@ sub www_editMetaDataField {
|
|||
-name=>"description",
|
||||
-label=>$i18n->get(85),
|
||||
-hoverHelp=>$i18n->get('Metadata Description description'),
|
||||
-value=>$fieldInfo->{description});
|
||||
-value=>$fieldInfo->{description}
|
||||
);
|
||||
$f->fieldType(
|
||||
-name=>"fieldType",
|
||||
-label=>$i18n->get(486),
|
||||
-hoverHelp=>$i18n->get('Data Type description'),
|
||||
-value=>$fieldInfo->{fieldType} || "text",
|
||||
-types=> [ qw /text integer yesNo selectList radioList/ ]
|
||||
-types=> [ qw /text integer yesNo selectBox radioList checkList/ ]
|
||||
);
|
||||
$f->textarea(
|
||||
-name=>"possibleValues",
|
||||
|
|
@ -265,6 +266,12 @@ sub www_editMetaDataField {
|
|||
-hoverHelp=>$i18n->get('Possible Values description'),
|
||||
-value=>$fieldInfo->{possibleValues}
|
||||
);
|
||||
$f->textarea(
|
||||
-name=>"defaultValue",
|
||||
-label=>$i18n->get('default value'),
|
||||
-hoverHelp=>$i18n->get('default value description'),
|
||||
-value=>$fieldInfo->{defaultValue}
|
||||
);
|
||||
$f->submit();
|
||||
$ac->setHelp("metadata edit property","Asset");
|
||||
return $ac->render($f->print, $i18n->get('Edit Metadata'));
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ sub AUTOLOAD {
|
|||
my $name = ucfirst((split /::/, $AUTOLOAD)[-1]);
|
||||
my %params = @_;
|
||||
$params{uiLevelOverride} ||= $self->{_uiLevelOverride};
|
||||
$params{rowClass} = $self->{_class};
|
||||
$params{rowClass} ||= $self->{_class};
|
||||
my $cmd = "use WebGUI::Form::".$name;
|
||||
eval ($cmd);
|
||||
if ($@) {
|
||||
|
|
|
|||
128
lib/WebGUI/Help/Asset_Newsletter.pm
Normal file
128
lib/WebGUI/Help/Asset_Newsletter.pm
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package WebGUI::Help::Asset_Newsletter; ## Be sure to change the package name to match your filename.
|
||||
|
||||
##Stub document for creating help documents.
|
||||
|
||||
our $HELP = { ##hashref of hashes
|
||||
'newsletter add/edit' => {
|
||||
title => 'newsletter add/edit',
|
||||
body => 'newsletter add/edit desc',
|
||||
isa => [
|
||||
{
|
||||
tag => 'collaboration add/edit',
|
||||
namespace => 'Asset_Collaboration',
|
||||
},
|
||||
],
|
||||
fields => [
|
||||
{
|
||||
title => 'newsletter header',
|
||||
description => 'newsletter header help',
|
||||
namespace => 'Asset_Newsletter',
|
||||
},
|
||||
{
|
||||
title => 'newsletter footer',
|
||||
description => 'newsletter footer help',
|
||||
namespace => 'Asset_Newsletter',
|
||||
},
|
||||
{
|
||||
title => 'newsletter template',
|
||||
description => 'newsletter template help',
|
||||
namespace => 'Asset_Newsletter',
|
||||
},
|
||||
{
|
||||
title => 'my subscriptions template',
|
||||
description => 'my subscriptions template help',
|
||||
namespace => 'Asset_Newsletter',
|
||||
},
|
||||
{
|
||||
title => 'newsletter categories',
|
||||
description => 'newsletter categories help',
|
||||
namespace => 'Asset_Newsletter',
|
||||
},
|
||||
],
|
||||
variables => [
|
||||
{
|
||||
name => "mySubscriptionsUrl",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
'my subscriptions template' => {
|
||||
title => 'my subscriptions template',
|
||||
body => 'my subscriptions template help',
|
||||
variables => [
|
||||
{
|
||||
name => "formHeader",
|
||||
},
|
||||
{
|
||||
name => "formFooter",
|
||||
},
|
||||
{
|
||||
name => "formSubmit",
|
||||
},
|
||||
{
|
||||
name => "categoriesLoop",
|
||||
variables => [
|
||||
{
|
||||
name => "categoryName",
|
||||
},
|
||||
{
|
||||
name => "optionsLoop",
|
||||
variables => [
|
||||
{
|
||||
name => "optionName",
|
||||
},
|
||||
{
|
||||
name => "optionForm",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
'newsletter template' => {
|
||||
title => 'newsletter template',
|
||||
body => 'newsletter template help',
|
||||
variables => [
|
||||
{
|
||||
name => "title",
|
||||
description => "newsletterTitle",
|
||||
},
|
||||
{
|
||||
name => "description",
|
||||
description => "newsletterDescription",
|
||||
},
|
||||
{
|
||||
name => "header",
|
||||
description => "newsletter header",
|
||||
},
|
||||
{
|
||||
name => "footer",
|
||||
description => "newsletter header",
|
||||
},
|
||||
{
|
||||
name => "thread_loop",
|
||||
variables => [
|
||||
{
|
||||
name => "title",
|
||||
description => "threadTitle",
|
||||
},
|
||||
{
|
||||
name => "synopsis",
|
||||
description => "threadSynopsis",
|
||||
},
|
||||
{
|
||||
name => "body",
|
||||
description => "threadBody",
|
||||
},
|
||||
{
|
||||
name => "url",
|
||||
description => "threadUrl",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1; ##All perl modules must return true
|
||||
207
lib/WebGUI/Workflow/Activity/SendNewsletters.pm
Normal file
207
lib/WebGUI/Workflow/Activity/SendNewsletters.pm
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
package WebGUI::Workflow::Activity::SendNewsletters;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2006 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
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::Mail::Send;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::Skeleton
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Tell a little about what this activity does.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Asset_Newsletter");
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get("send activity name"),
|
||||
properties=> { }
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( [ object ] )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
my $object = shift;
|
||||
my $instance = shift;
|
||||
my ($db,$eh) = $self->session->quick(qw(db errorHandler));
|
||||
|
||||
my $time = time();
|
||||
my $newsletter = undef;
|
||||
|
||||
$eh->info("Getting subscriptions");
|
||||
my $subscriptionResultSet = $db->read("select assetId, userId, subscriptions, lastTimeSent
|
||||
from Newsletter_subscriptions where lastTimeSent < unix_timestamp() - 60*60*23
|
||||
order by assetId, userId"); # only sending to people who haven't been sent to in the past 23 hours
|
||||
while (my ($assetId, $userId, $subscriptions, $lastTimeSent) = $subscriptionResultSet->array) {
|
||||
|
||||
# get user object
|
||||
$eh->info("Getting user $userId");
|
||||
my $user = WebGUI::User->new($self->session, $userId);
|
||||
next if ($user->userId eq "1");
|
||||
my $emailAddress = $user->profileField("email");
|
||||
next if ($emailAddress eq "");
|
||||
|
||||
|
||||
# get newsletter asset
|
||||
unless (defined $newsletter && $newsletter->getId eq $assetId) { # cache newsletter object
|
||||
$eh->info("Getting newsletter asset $assetId");
|
||||
$newsletter = WebGUI::Asset->new($self->session, $assetId);
|
||||
}
|
||||
|
||||
# find matching threads
|
||||
my @threads = ();
|
||||
$eh->info("Find threads in $assetId matching $userId subscriptions.");
|
||||
foreach my $subscription (split("\n", $subscriptions)) {
|
||||
$eh->info("Found subscription $subscription");
|
||||
my ($fieldId, $value) = split("~", $subscription);
|
||||
$eh->info("Searching for threads that match $subscription");
|
||||
my $matchingThreads = $db->read("select metaData_values.assetId from metaData_values
|
||||
left join asset using (assetId) where fieldId=? and value like ? and creationDate > ?
|
||||
and className like ? and lineage like ?",
|
||||
[$fieldId, '%'.$value.'%', $lastTimeSent, 'WebGUI::Asset::Post::Thread%', $newsletter->get("lineage").'%']);
|
||||
while (my ($threadId) = $matchingThreads->array) {
|
||||
my $thread = WebGUI::Asset->new($self->session, $threadId);
|
||||
if (defined $thread) {
|
||||
$eh->info("Found thread $threadId");
|
||||
push(@threads, $thread);
|
||||
}
|
||||
else {
|
||||
$eh->error("Couldn't instanciate thread $threadId");
|
||||
}
|
||||
}
|
||||
}
|
||||
unless (scalar(@threads)) { # don't send a message if there aren't matching threads
|
||||
$eh->info("No threads found matching $userId subscriptions.");
|
||||
next;
|
||||
}
|
||||
|
||||
# build newsletter
|
||||
$eh->info("Building newsletter for $userId.");
|
||||
my $siteurl = $self->session->url->getSiteURL();
|
||||
my @threadLoop = ();
|
||||
foreach my $thread (@threads) {
|
||||
push(@threadLoop, {
|
||||
title => $thread->getTitle,
|
||||
synopsis => $thread->get("synopsis"),
|
||||
body => $thread->get("body"),
|
||||
url => $siteurl.$thread->getUrl,
|
||||
});
|
||||
}
|
||||
my %var = (
|
||||
title => $newsletter->getTitle,
|
||||
description => $newsletter->get("description"),
|
||||
header => $newsletter->get("newsletterHeader"),
|
||||
footer => $newsletter->get("newsletterFooter"),
|
||||
thread_loop => \@threadLoop,
|
||||
);
|
||||
my $template = WebGUI::Asset->new($self->session, $newsletter->get("newsletterTemplateId"));
|
||||
my $content = $template->process(\%var);
|
||||
|
||||
# send newsletter
|
||||
$eh->info("Sending newsletter for $userId.");
|
||||
my $setting = $self->session->setting;
|
||||
my $returnAddress = $setting->get("mailReturnPath");
|
||||
my $companyAddress = $setting->get("companyEmail");
|
||||
my $listAddress = $newsletter->get("mailAddress");
|
||||
my $from = $listAddress || $companyAddress;
|
||||
my $replyTo = $listAddress || $returnAddress || $companyAddress;
|
||||
my $sender = $listAddress || $companyAddress;
|
||||
my $returnPath = $returnAddress || $sender;
|
||||
my $listId = $sender;
|
||||
$listId =~ s/\@/\./;
|
||||
my $domain = $newsletter->get("mailAddress");
|
||||
$domain =~ s/.*\@(.*)/$1/;
|
||||
my $messageId = "cs-".$self->getId.'@'.$domain;
|
||||
my $subject = $newsletter->get("mailPrefix").$newsletter->getTitle;
|
||||
my $mail = WebGUI::Mail::Send->create($self->session, {
|
||||
to => "<".$emailAddress.">",
|
||||
from => "<".$from.">",
|
||||
returnPath => "<".$returnPath.">",
|
||||
replyTo => "<".$replyTo.">",
|
||||
subject => $subject,
|
||||
messageId => '<'.$messageId.'>'
|
||||
});
|
||||
$mail->addHeaderField("List-ID", $newsletter->getTitle." <".$listId.">");
|
||||
$mail->addHeaderField("List-Help", "<mailto:".$companyAddress.">, <".$setting->get("companyURL").">");
|
||||
$mail->addHeaderField("List-Unsubscribe", "<".$siteurl.$newsletter->getUrl("func=mySubscriptions").">");
|
||||
$mail->addHeaderField("List-Owner", "<mailto:".$companyAddress.">, <".$setting->get("companyURL")."> (".$setting->get("companyName").")");
|
||||
$mail->addHeaderField("Sender", "<".$sender.">");
|
||||
if ($listAddress eq "") {
|
||||
$mail->addHeaderField("List-Post", "No");
|
||||
} else {
|
||||
$mail->addHeaderField("List-Post", "<mailto:".$listAddress.">");
|
||||
}
|
||||
$mail->addHeaderField("List-Archive", "<".$siteurl.$newsletter->getUrl.">");
|
||||
$mail->addHeaderField("X-Unsubscribe-Web", "<".$siteurl.$newsletter->getUrl("func=mySubscriptions").">");
|
||||
$mail->addHeaderField("X-Archives", "<".$siteurl.$newsletter->getUrl.">");
|
||||
$mail->addHtml($content);
|
||||
$mail->queue;
|
||||
|
||||
# mark sent
|
||||
$eh->info("Email sent.");
|
||||
$db->write("update Newsletter_subscriptions set lastTimeSent = ?", [time()]);
|
||||
|
||||
# timeout if we're taking too long
|
||||
if (time() - $time > 50) {
|
||||
$eh->info("Oops. Ran out of time. Will continue building newsletters in a bit.");
|
||||
$subscriptionResultSet->finish;
|
||||
return $self->WAITING;
|
||||
}
|
||||
}
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
@ -723,6 +723,15 @@ each asset under the tab "Meta" in the asset properties.</p>
|
|||
lastUpdated => 1031514049,
|
||||
message => q|Possible Values|
|
||||
},
|
||||
'default value' => {
|
||||
lastUpdated => 0,
|
||||
message => q|Default Value(s)|
|
||||
},
|
||||
'default value description' => {
|
||||
lastUpdated => 0,
|
||||
message => q|The default value for this field. If there are multiple default values, as in the
|
||||
case of the check box list, then enter one per line.|
|
||||
},
|
||||
'Depth' => {
|
||||
lastUpdated => 1089039511,
|
||||
context => q|Field label for the Export Page operation|,
|
||||
|
|
|
|||
208
lib/WebGUI/i18n/English/Asset_Newsletter.pm
Normal file
208
lib/WebGUI/i18n/English/Asset_Newsletter.pm
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
package WebGUI::i18n::English::Asset_Newsletter;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'newsletterTitle' => {
|
||||
message => q|Whatever this newsletter is called.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'newsletterDescription' => {
|
||||
message => q|Whatever is in the description field of this newsletter.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'thread_loop' => {
|
||||
message => q|A loop containing all the matching threads for this user's personalized newsletter.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'threadTitle' => {
|
||||
message => q|The title of this thread.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'threadSynopsis' => {
|
||||
message => q|The short version of this story.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'threadBody' => {
|
||||
message => q|The full version of this story.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'threadUrl' => {
|
||||
message => q|The fully qualified URL that points to this thread.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'categoriesLoop' => {
|
||||
message => q|A loop containing all the categories of data the users may choose from.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'optionsLoop' => {
|
||||
message => q|A loop containing all the options in a given category.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'categoryName' => {
|
||||
message => q|The name of this specific category within the loop.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'optionName' => {
|
||||
message => q|The name of this specific option within this category.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'optionForm' => {
|
||||
message => q|The checkbox form control for this specific option within this category.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'formSubmit' => {
|
||||
message => q|The save button for the form.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'formHeader' => {
|
||||
message => q|The top of the subscription form.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'formFooter' => {
|
||||
message => q|The bottom of the subscription form.|,
|
||||
lastUpdated => 0,
|
||||
context => q|template variable|
|
||||
},
|
||||
|
||||
'newsletter add/edit' => {
|
||||
message => q|Newsletter, Add/Edit|,
|
||||
lastUpdated => 0,
|
||||
context => q|help title|
|
||||
},
|
||||
|
||||
'newsletter add/edit desc' => {
|
||||
message => q|The Newsletter asset is used to create news stories and then send subscribed users an email
|
||||
based upon their chosen interests. This asset requires content profiling to be enabled in order to
|
||||
function.|,
|
||||
lastUpdated => 0,
|
||||
context => q|help description|
|
||||
},
|
||||
|
||||
'mySubscriptionsUrl' => {
|
||||
message => q|The URL for a user to click on to manage their subscriptions.|,
|
||||
lastUpdated => 0,
|
||||
context => q|newsletter template variable|
|
||||
},
|
||||
|
||||
'content profiling needed' => {
|
||||
message => q|WARNING: You need to enable content profiling for this asset to work.|,
|
||||
lastUpdated => 0,
|
||||
context => q|title for edit screen|
|
||||
},
|
||||
|
||||
'edit title' => {
|
||||
message => q|Edit Newsletter|,
|
||||
lastUpdated => 0,
|
||||
context => q|title for edit screen|
|
||||
},
|
||||
|
||||
'newsletter categories' => {
|
||||
message => q|Newsletter Categories|,
|
||||
lastUpdated => 0,
|
||||
context => q|asset property|
|
||||
},
|
||||
|
||||
'newsletter categories help' => {
|
||||
message => q|Choose the metadata fields you wish to use as categories. Only select box, check list, and
|
||||
radio list categories may be used.|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for asset property|
|
||||
},
|
||||
|
||||
'newsletter template' => {
|
||||
message => q|Newsletter Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|asset property|
|
||||
},
|
||||
|
||||
'newsletter template help' => {
|
||||
message => q|Which template would you like to use for the newsletter when it is sent out to users?|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for asset property|
|
||||
},
|
||||
|
||||
'my subscriptions' => {
|
||||
message => q|My Subscriptions|,
|
||||
lastUpdated => 0,
|
||||
context => q|label for user to click on to manage their subscriptions|
|
||||
},
|
||||
|
||||
'my subscriptions template' => {
|
||||
message => q|My Subscriptions Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|asset property|
|
||||
},
|
||||
|
||||
'my subscriptions template help' => {
|
||||
message => q|Which template would you like to use for users selecting which cateogries they will subscribe
|
||||
to?|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for asset property|
|
||||
},
|
||||
|
||||
'newsletter header' => {
|
||||
message => q|Newsletter Header|,
|
||||
lastUpdated => 0,
|
||||
context => q|asset property|
|
||||
},
|
||||
|
||||
'newsletteer header help' => {
|
||||
message => q|A message the will be placed at the top of the newsletter; like a greeting.|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for asset property|
|
||||
},
|
||||
|
||||
'newsletter footer' => {
|
||||
message => q|Newsletter Footer|,
|
||||
lastUpdated => 0,
|
||||
context => q|asset property|
|
||||
},
|
||||
|
||||
'newsletteer footer help' => {
|
||||
message => q|A message the will be placed at the bottom of the newsletter; like a salutation.|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for asset property|
|
||||
},
|
||||
|
||||
'send activity name' => {
|
||||
message => q|Send Newsletters|,
|
||||
lastUpdated => 0,
|
||||
context => q|the name of the workflow activity that sends out the newsletters|
|
||||
},
|
||||
|
||||
'assetName' => {
|
||||
message => q|Newsletter|,
|
||||
lastUpdated => 1131394072,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
Loading…
Add table
Add a link
Reference in a new issue