From 9248570f79736bd0199edcc0bfcab4e799e7296f Mon Sep 17 00:00:00 2001
From: JT Smith
Date: Sat, 16 Jun 2007 19:33:12 +0000
Subject: [PATCH] Added Newsletter Asset (Funded by United Knowledge)
---
docs/changelog/7.x.x.txt | 6 +-
.../PBtmpl0000000000000029.tmpl | 90 ++++++
.../PBtmpl0000000000000068.tmpl | 103 +++++++
.../newsletter0000000000001.tmpl | 18 ++
.../newslettercs000000001.tmpl | 67 +++++
.../newslettersubscrip00001.tmpl | 22 ++
docs/upgrades/upgrade_7.3.19-7.4.0.pl | 31 ++
lib/WebGUI/Asset.pm | 17 +-
lib/WebGUI/Asset/Wobject/Collaboration.pm | 281 +++++++++---------
.../Asset/Wobject/Collaboration/Newsletter.pm | 242 +++++++++++++++
lib/WebGUI/AssetMetaData.pm | 13 +-
lib/WebGUI/HTMLForm.pm | 2 +-
lib/WebGUI/Help/Asset_Newsletter.pm | 128 ++++++++
.../Workflow/Activity/SendNewsletters.pm | 207 +++++++++++++
lib/WebGUI/i18n/English/Asset.pm | 9 +
lib/WebGUI/i18n/English/Asset_Newsletter.pm | 208 +++++++++++++
16 files changed, 1295 insertions(+), 149 deletions(-)
create mode 100644 docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl
create mode 100644 docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl
create mode 100644 docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl
create mode 100644 docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl
create mode 100644 docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl
create mode 100644 lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm
create mode 100644 lib/WebGUI/Help/Asset_Newsletter.pm
create mode 100644 lib/WebGUI/Workflow/Activity/SendNewsletters.pm
create mode 100644 lib/WebGUI/i18n/English/Asset_Newsletter.pm
diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt
index 05e690a53..ac5147624 100644
--- a/docs/changelog/7.x.x.txt
+++ b/docs/changelog/7.x.x.txt
@@ -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.
diff --git a/docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl b/docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl
new file mode 100644
index 000000000..43b07672e
--- /dev/null
+++ b/docs/upgrades/templates-7.4.0/PBtmpl0000000000000029.tmpl
@@ -0,0 +1,90 @@
+#PBtmpl0000000000000029
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+
+
+ |
+ |
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+
+
+
+~~~
+
diff --git a/docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl b/docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl
new file mode 100644
index 000000000..7326180f1
--- /dev/null
+++ b/docs/upgrades/templates-7.4.0/PBtmpl0000000000000068.tmpl
@@ -0,0 +1,103 @@
+#PBtmpl0000000000000068
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+~~~
+
diff --git a/docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl b/docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl
new file mode 100644
index 000000000..fbcee1fb9
--- /dev/null
+++ b/docs/upgrades/templates-7.4.0/newsletter0000000000001.tmpl
@@ -0,0 +1,18 @@
+#newsletter000000000001
+#url: newsletterdefaulttemplate
+#title: Summary Newsletter (default)
+#menuTitle: Summary Newsletter
+#namespace:newsletter
+#create
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl b/docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl
new file mode 100644
index 000000000..8cf6419b1
--- /dev/null
+++ b/docs/upgrades/templates-7.4.0/newslettercs000000001.tmpl
@@ -0,0 +1,67 @@
+#newslettercs0000000001
+#url: newslettercstemplate
+#title: Newsletter Manager (default)
+#menuTitle: Newsletter Manager
+#namespace:Collaboration
+#create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+~~~
+
diff --git a/docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl b/docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl
new file mode 100644
index 000000000..90a62d772
--- /dev/null
+++ b/docs/upgrades/templates-7.4.0/newslettersubscrip00001.tmpl
@@ -0,0 +1,22 @@
+#newslettersubscrip0001
+#url: newslettermysubscriptionstemplate
+#title: My Subscriptions (default)
+#menuTitle: My Subscriptions
+#namespace:newsletter/mysubscriptions
+#create
+
+^International("my subscriptions","Asset_Newsletter");
+
+
+^International("newsletter categories","Asset_Newsletter");
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/upgrades/upgrade_7.3.19-7.4.0.pl b/docs/upgrades/upgrade_7.3.19-7.4.0.pl
index 2e805c39f..5f04d1bd1 100644
--- a/docs/upgrades/upgrade_7.3.19-7.4.0.pl
+++ b/docs/upgrades/upgrade_7.3.19-7.4.0.pl
@@ -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;
diff --git a/lib/WebGUI/Asset.pm b/lib/WebGUI/Asset.pm
index 02ae08444..bb59baf71 100644
--- a/lib/WebGUI/Asset.pm
+++ b/lib/WebGUI/Asset.pm
@@ -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;
diff --git a/lib/WebGUI/Asset/Wobject/Collaboration.pm b/lib/WebGUI/Asset/Wobject/Collaboration.pm
index 00dc6e14b..05fa20de4 100644
--- a/lib/WebGUI/Asset/Wobject/Collaboration.pm
+++ b/lib/WebGUI/Asset/Wobject/Collaboration.pm
@@ -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;
diff --git a/lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm b/lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm
new file mode 100644
index 000000000..c6713205a
--- /dev/null
+++ b/lib/WebGUI/Asset/Wobject/Collaboration/Newsletter.pm
@@ -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=>''.$i18n->get("content profiling needed").'',
+ };
+ }
+ 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;
diff --git a/lib/WebGUI/AssetMetaData.pm b/lib/WebGUI/AssetMetaData.pm
index dba0547c7..9fb82d79c 100644
--- a/lib/WebGUI/AssetMetaData.pm
+++ b/lib/WebGUI/AssetMetaData.pm
@@ -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'));
diff --git a/lib/WebGUI/HTMLForm.pm b/lib/WebGUI/HTMLForm.pm
index 32df308fc..9a0824012 100644
--- a/lib/WebGUI/HTMLForm.pm
+++ b/lib/WebGUI/HTMLForm.pm
@@ -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 ($@) {
diff --git a/lib/WebGUI/Help/Asset_Newsletter.pm b/lib/WebGUI/Help/Asset_Newsletter.pm
new file mode 100644
index 000000000..1f9cd9e78
--- /dev/null
+++ b/lib/WebGUI/Help/Asset_Newsletter.pm
@@ -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
diff --git a/lib/WebGUI/Workflow/Activity/SendNewsletters.pm b/lib/WebGUI/Workflow/Activity/SendNewsletters.pm
new file mode 100644
index 000000000..2858595cc
--- /dev/null
+++ b/lib/WebGUI/Workflow/Activity/SendNewsletters.pm
@@ -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", ", <".$setting->get("companyURL").">");
+ $mail->addHeaderField("List-Unsubscribe", "<".$siteurl.$newsletter->getUrl("func=mySubscriptions").">");
+ $mail->addHeaderField("List-Owner", ", <".$setting->get("companyURL")."> (".$setting->get("companyName").")");
+ $mail->addHeaderField("Sender", "<".$sender.">");
+ if ($listAddress eq "") {
+ $mail->addHeaderField("List-Post", "No");
+ } else {
+ $mail->addHeaderField("List-Post", "");
+ }
+ $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;
+
+
diff --git a/lib/WebGUI/i18n/English/Asset.pm b/lib/WebGUI/i18n/English/Asset.pm
index 912911cef..47cc44559 100644
--- a/lib/WebGUI/i18n/English/Asset.pm
+++ b/lib/WebGUI/i18n/English/Asset.pm
@@ -723,6 +723,15 @@ each asset under the tab "Meta" in the asset properties.
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|,
diff --git a/lib/WebGUI/i18n/English/Asset_Newsletter.pm b/lib/WebGUI/i18n/English/Asset_Newsletter.pm
new file mode 100644
index 000000000..79eca13b7
--- /dev/null
+++ b/lib/WebGUI/i18n/English/Asset_Newsletter.pm
@@ -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;