incorporating
r1628 | chrisg23 | 2007-09-17 10:10:40 +0200 (Mo, 17 Sep 2007) | 1 line Sourceforge patch 1689988 - rather a large commit, but in fact causes very little visible change. Large single commit is necessary because all these changes are essentially atomic. git-svn-id: https://svn.libreccm.org/ccm/trunk@8 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
0885de7620
commit
ffa005c685
|
|
@ -2,11 +2,12 @@
|
||||||
<ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project"
|
<ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project"
|
||||||
name="ccm-forum"
|
name="ccm-forum"
|
||||||
prettyName="Forum"
|
prettyName="Forum"
|
||||||
version="6.5.0"
|
version="6.5.2"
|
||||||
release="1">
|
release="1">
|
||||||
<ccm:dependencies>
|
<ccm:dependencies>
|
||||||
<ccm:requires name="ccm-core" version="6.2.0" relation="ge"/>
|
|
||||||
<ccm:requires name="ccm-cms" version="6.2.0" relation="ge"/>
|
<ccm:requires name="ccm-core" version="6.5.3"/>
|
||||||
|
<ccm:requires name="ccm-cms" version="6.5.3"/>
|
||||||
</ccm:dependencies>
|
</ccm:dependencies>
|
||||||
<ccm:contacts>
|
<ccm:contacts>
|
||||||
<ccm:contact uri="http://www.redhat.com/software/rhea" type="website"/>
|
<ccm:contact uri="http://www.redhat.com/software/rhea" type="website"/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
Main new features included in this release are:
|
||||||
|
|
||||||
|
Fine grained forum permissions
|
||||||
|
Allow file attachments and images in posts
|
||||||
|
Contents of posts are searchable
|
||||||
|
New portlet type lising links to all forums user has read access to
|
||||||
|
Allow automatic thread subscription for thread starter (useful for noticeboard type forums)
|
||||||
|
Forum admin can prevent posts with no topic
|
||||||
|
Expiry can be specified for all types of forum
|
||||||
|
Reply count calculation fixed
|
||||||
|
HTML Editor can be used for posts
|
||||||
|
Subscription emails can (and should) be sent as html emails)
|
||||||
|
|
||||||
|
Other minor changes, fixes and configurable features are also included.
|
||||||
|
Check new config parameter descriptions in com.arsdigita.forum.ForumConfig_parameter.properties
|
||||||
|
|
||||||
|
After deployment, to install new features, either get rid of existing forum app, and load new version, OR
|
||||||
|
|
||||||
|
ccm upgrade ccm-forum --from-version 6.5.0 --to-version 6.5.1
|
||||||
|
ccm upgrade ccm-forum --from-version 6.5.1 --to-version 6.5.2
|
||||||
|
ccm-run com.arsdigita.london.search.Reindexer --object-type com.arsdigita.forum.Post
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
When developing this, I tried to ensure that a basic deployment will not affect the XML
|
||||||
|
that is produced by the current forum application.
|
||||||
|
|
||||||
|
I have tested the new implementation with Coventry's theme. There is one theme amendment required (because of a bug fix).
|
||||||
|
In current release, the drop down list for filtering threads by category has the same name as the drop down list for selecting a category when making a new post. This means that the selected value carries through . ie if you have filtered the threads then make a new post, the new post has the filter category selected as default. More importantly, if you make a post and assign a category, then the thread list is filtered after you complete the post.
|
||||||
|
|
||||||
|
To fix the bug, I renamed the drop down list in the post form from topic to PostTopic. This means the category drop down is not visible until the two references to @name='topic' in the forum:postForm template are changed to @name='postTopic'
|
||||||
|
|
||||||
|
Only other visible changes if the patch is applied without changing config
|
||||||
|
are:
|
||||||
|
|
||||||
|
Reply count only includes posts that have been approved
|
||||||
|
|
||||||
|
Posts are searchable from the main site search. This is a change from the current behaviour . if not desired then it could be made configurable.
|
||||||
|
|
||||||
|
Moderation form and emails are formatted slightly differently
|
||||||
|
|
||||||
|
recent forum postings portlet prevents users creating new forum application .
|
||||||
|
only site admin can do this. Also filters forums to those that the user has
|
||||||
|
read access on.
|
||||||
|
|
||||||
|
New portlet . my forums. Lists links to forums that user has read access to.
|
||||||
|
|
||||||
|
The other non-visble effect is that the wizard uses java session rather than
|
||||||
|
hidden fields. This approach makes it much easier to include links in form
|
||||||
|
steps (eg remove an uploaded file etc). The impact is that users in a load
|
||||||
|
balanced environment need to consider session affinity. In our production
|
||||||
|
environment, this is accomplished by the server that sprays requests to the
|
||||||
|
various back end servers. It identifies each browser session and routes all
|
||||||
|
their requests to the same back end server. Hence there is no replication of
|
||||||
|
session - the user is guaranteed to end up at the server that holds their java
|
||||||
|
session. As a result, when a backend server is stopped, there is a risk that a
|
||||||
|
user with session on that server in the middle of creating a post will lose
|
||||||
|
information entered up to that point. On our site we live with this small risk
|
||||||
|
but mitigate it by restarting servers at unsociable hours where possible.
|
||||||
|
|
||||||
|
I have put examle theme files in
|
||||||
|
ccm-ldn-aplaws/web/__ccm__/themes/aplaws/forum-example: forum-index.xsl,
|
||||||
|
forum-index.css and the contents of images/forum
|
||||||
|
|
||||||
|
To have a look at a forum using these files, copy the xsl and css to the top
|
||||||
|
level of your theme and make a new forum directory in images and copy the
|
||||||
|
images there. I.m afraid these files have continued the existing format of
|
||||||
|
putting all the templates in a single file, so they are not the most easily
|
||||||
|
maintained, and I make no guarantees about the content, but they do work. and
|
||||||
|
if required they may be used as a basis for your own look and feel.
|
||||||
|
|
||||||
|
|
||||||
|
There is a separate application - ccm-categorised-forum that adds category path and menu components to the front end,
|
||||||
|
and adds a categorisation tab for admin users. Load this application if you would like this functionality.
|
||||||
|
|
||||||
|
When a forum is created, only site admin can access the admin tabs,
|
||||||
|
until you assign users/groups to the forum admin group under the permissions tab.
|
||||||
|
|
||||||
|
Next things I plan to do are:
|
||||||
|
|
||||||
|
list pending and reapprove posts under the moderation tab
|
||||||
|
create a user info page so users can write a bit about themselves
|
||||||
|
allow thread branching so administrators can split long threads or threads that have strayed from the point.
|
||||||
|
Allow different thread views - paginated full details, or tree of titles with one post visible (a la sourceforge)
|
||||||
|
|
||||||
|
chris.gilbert@westsussex.gov.uk
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// Forum initialization file
|
|
||||||
//
|
|
||||||
// ::replyHostName:: -> example.com
|
|
||||||
// ::digestUserEmail:: -> digests
|
|
||||||
// ::adminCanEditPosts:: -> true
|
|
||||||
// ::authorCanEditPosts:: -> true
|
|
||||||
// ::forums:: -> {}
|
|
||||||
|
|
||||||
init com.arsdigita.forum.LegacyInitializer {
|
|
||||||
// All outbound bboard message will have return address as the
|
|
||||||
// following format: forumID.bboard@hostname
|
|
||||||
replyHostName = "::replyHostName::";
|
|
||||||
// The email address that daily digests come from
|
|
||||||
digestUserEmail = "::digests::";
|
|
||||||
// whether administrators can edit posts
|
|
||||||
adminCanEditPosts = ::adminCanEditPosts::;
|
|
||||||
// whether the author of a post can edit it later
|
|
||||||
authorCanEditPosts = ::authorCanEditPosts::;
|
|
||||||
|
|
||||||
forums = ::forums::;
|
|
||||||
}
|
|
||||||
|
|
||||||
init com.arsdigita.domain.installer.DomainObjectTraversalInitializer {
|
|
||||||
adapters = { "/WEB-INF/resources/forum-adapters.xml" };
|
|
||||||
}
|
|
||||||
|
|
@ -32,8 +32,16 @@ object type Forum extends Application {
|
||||||
|
|
||||||
Boolean [1..1] isModerated = forum_forums.is_moderated;
|
Boolean [1..1] isModerated = forum_forums.is_moderated;
|
||||||
Boolean [1..1] isNoticeboard = forum_forums.is_noticeboard;
|
Boolean [1..1] isNoticeboard = forum_forums.is_noticeboard;
|
||||||
|
component Group [0..1] adminGroup =
|
||||||
|
join forum_forums.admin_group_id to groups.group_id;
|
||||||
component Group [0..1] moderationGroup =
|
component Group [0..1] moderationGroup =
|
||||||
join forum_forums.mod_group_id to groups.group_id;
|
join forum_forums.mod_group_id to groups.group_id;
|
||||||
|
component Group [0..1] threadCreateGroup =
|
||||||
|
join forum_forums.create_group_id to groups.group_id;
|
||||||
|
component Group [0..1] threadRespondGroup =
|
||||||
|
join forum_forums.respond_group_id to groups.group_id;
|
||||||
|
component Group [0..1] readGroup =
|
||||||
|
join forum_forums.read_group_id to groups.group_id;
|
||||||
|
|
||||||
component ForumSubscription[0..n] subscriptions =
|
component ForumSubscription[0..n] subscriptions =
|
||||||
join forum_forums.forum_id to forum_subscriptions.forum_id;
|
join forum_forums.forum_id to forum_subscriptions.forum_id;
|
||||||
|
|
@ -44,7 +52,12 @@ object type Forum extends Application {
|
||||||
join forum_forums.lifecycle_definition_id to lifecycle_definitions.definition_id;
|
join forum_forums.lifecycle_definition_id to lifecycle_definitions.definition_id;
|
||||||
|
|
||||||
BigDecimal [0..1] expireAfter = forum_forums.expire_after;
|
BigDecimal [0..1] expireAfter = forum_forums.expire_after;
|
||||||
|
Boolean [1..1] fileAttachmentsAllowed = forum_forums.file_attachments_allowed;
|
||||||
|
Boolean [1..1] imageUploadsAllowed = forum_forums.image_uploads_allowed;
|
||||||
|
Boolean [1..1] autoSubscribeThreadStarter = forum_forums.subscribe_thread_starter;
|
||||||
|
Boolean [1..1] noCategoryPostsAllowed = forum_forums.no_category_posts_allowed;
|
||||||
|
Boolean [1..1] anonymousPostsAllowed = forum_forums.anonymous_posts_allowed;
|
||||||
|
String [0..1] introduction = forum_forums.introduction VARCHAR(4000);
|
||||||
reference key (forum_forums.forum_id);
|
reference key (forum_forums.forum_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
// $Id: RecentPostingsPortlet.pdl 285 2005-02-22 00:29:02Z sskracic $
|
||||||
|
// $DateTime: 2004/08/17 23:26:27 $
|
||||||
|
model com.arsdigita.forum;
|
||||||
|
|
||||||
|
import com.arsdigita.portal.Portlet;
|
||||||
|
|
||||||
|
// lists links to forums for which user has read access
|
||||||
|
|
||||||
|
object type MyForumsPortlet extends Portlet {
|
||||||
|
|
||||||
|
// no attributes for this one
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,9 @@ model com.arsdigita.forum;
|
||||||
|
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.cms.FileAsset;
|
||||||
|
import com.arsdigita.cms.ImageAsset;
|
||||||
|
|
||||||
|
|
||||||
object type Post extends com.arsdigita.messaging.ThreadedMessage {
|
object type Post extends com.arsdigita.messaging.ThreadedMessage {
|
||||||
|
|
||||||
|
|
@ -29,6 +32,31 @@ object type Post extends com.arsdigita.messaging.ThreadedMessage {
|
||||||
aggressive load(moderator.id);
|
aggressive load(moderator.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object type PostFileAttachment extends FileAsset {
|
||||||
|
Integer[0..1] fileOrder = forum_post_files.file_order INTEGER;
|
||||||
|
reference key (forum_post_files.file_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
object type PostImageAttachment extends ImageAsset {
|
||||||
|
Integer[0..1] imageOrder = forum_post_images.image_order INTEGER;
|
||||||
|
reference key (forum_post_images.image_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
association {
|
||||||
|
|
||||||
|
composite Post[0..1] fileMessage = join forum_post_files.post_id to forum_posts.post_id;
|
||||||
|
component PostFileAttachment[0..n] files = join forum_posts.post_id to forum_post_files.post_id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
association {
|
||||||
|
|
||||||
|
composite Post[0..1] imageMessage = join forum_post_images.post_id to forum_posts.post_id;
|
||||||
|
component PostImageAttachment[0..n] images = join forum_posts.post_id to forum_post_images.post_id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
association {
|
association {
|
||||||
Party [0..1] moderator = join forum_posts.moderator to parties.party_id;
|
Party [0..1] moderator = join forum_posts.moderator to parties.party_id;
|
||||||
Post [0..1] moderatedMessage = join parties.party_id to forum_posts.moderator;
|
Post [0..1] moderatedMessage = join parties.party_id to forum_posts.moderator;
|
||||||
|
|
@ -53,3 +81,20 @@ query threadModerationStatus {
|
||||||
id = message_threads.thread_id;
|
id = message_threads.thread_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subquery for filtering out threads where root post is of a
|
||||||
|
// particular status (eg unconfirmed)
|
||||||
|
//
|
||||||
|
//query threadStatus {
|
||||||
|
// BigDecimal id;
|
||||||
|
//
|
||||||
|
// do {
|
||||||
|
// select m.thread_id
|
||||||
|
// from forum_posts f,
|
||||||
|
// message_threads m
|
||||||
|
// where m.root_id = f.post_id
|
||||||
|
// and f.status <> :status2
|
||||||
|
// } map {
|
||||||
|
// id = message_threads.thread_id;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
alter table forum_forums add (anonymous_posts_allowed CHAR(1));
|
||||||
|
|
||||||
|
update forum_forums set anonymous_posts_allowed = 0;
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
create table forum_post_files
|
||||||
|
(post_id NUMBER,
|
||||||
|
file_id NUMBER not null,
|
||||||
|
file_order NUMBER);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
alter table forum_post_files add
|
||||||
|
constraint FORU_POS_FILES_FILE_ID_F_XBKED foreign key (file_id)
|
||||||
|
references cms_files(file_id);
|
||||||
|
|
||||||
|
alter table forum_post_files add
|
||||||
|
constraint FORU_POS_FILES_POST_ID_F_K0XJQ foreign key (post_id)
|
||||||
|
references forum_posts(post_id);
|
||||||
|
|
||||||
|
alter table forum_forums add (file_attachments_allowed CHAR(1));
|
||||||
|
|
||||||
|
update forum_forums set file_attachments_allowed = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE FORUM_FORUMS ADD (
|
||||||
|
INTRODUCTION VARCHAR2(4000) );
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
alter table forum_forums add (no_category_posts_allowed CHAR(1));
|
||||||
|
|
||||||
|
update forum_forums set no_category_posts_allowed = 1;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
alter table forum_forums
|
||||||
|
add (admin_group_id NUMBER,
|
||||||
|
create_group_id NUMBER,
|
||||||
|
respond_group_id NUMBER,
|
||||||
|
read_group_id NUMBER);
|
||||||
|
|
||||||
|
|
||||||
|
alter table forum_forums add
|
||||||
|
constraint foru_foru_admi_grou_id_f_k0nw6 foreign key (admin_group_id)
|
||||||
|
references groups(group_id);
|
||||||
|
alter table forum_forums add
|
||||||
|
constraint foru_foru_crea_grou_id_f_f7x57 foreign key (create_group_id)
|
||||||
|
references groups(group_id);
|
||||||
|
alter table forum_forums add
|
||||||
|
constraint foru_foru_respo_gro_id_f_rnofz foreign key (respond_group_id)
|
||||||
|
references groups(group_id);
|
||||||
|
alter table forum_forums add
|
||||||
|
constraint foru_forum_rea_grou_id_f_itati foreign key (read_group_id)
|
||||||
|
references groups(group_id);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
create table forum_post_images
|
||||||
|
(post_id NUMBER,
|
||||||
|
image_id NUMBER not null,
|
||||||
|
image_order NUMBER);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
alter table forum_post_images add
|
||||||
|
constraint FORU_POS_IMAGE_IMAG_ID_F_WYRXA foreign key (image_id)
|
||||||
|
references cms_images(image_id);
|
||||||
|
|
||||||
|
alter table forum_post_images add
|
||||||
|
constraint FORU_POS_IMAGE_POST_ID_F_1HH02 foreign key (post_id)
|
||||||
|
references forum_posts(post_id);
|
||||||
|
|
||||||
|
alter table forum_forums add (image_uploads_allowed CHAR(1));
|
||||||
|
|
||||||
|
update forum_forums set image_uploads_allowed = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
insert into acs_privileges (privilege)
|
||||||
|
values ('forum_read');
|
||||||
|
|
||||||
|
insert into acs_privileges (privilege)
|
||||||
|
values ('forum_create_thread');
|
||||||
|
|
||||||
|
insert into acs_privileges (privilege)
|
||||||
|
values ('forum_respond');
|
||||||
|
|
||||||
|
insert into acs_privilege_hierarchy (privilege, child_privilege)
|
||||||
|
values ('forum_moderation', 'forum_create_thread');
|
||||||
|
|
||||||
|
insert into acs_privilege_hierarchy (privilege, child_privilege)
|
||||||
|
values ('forum_create_thread', 'forum_respond');
|
||||||
|
|
||||||
|
insert into acs_privilege_hierarchy (privilege, child_privilege)
|
||||||
|
values ('forum_respond', 'forum_read');
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
alter table forum_forums add (subscribe_thread_starter CHAR(1));
|
||||||
|
|
||||||
|
update forum_forums set subscribe_thread_starter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_privileges.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_groups.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_thread_subscriber.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_file_attachments.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_forum_introduction.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_image_uploads.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_forum_no_category_posts.sql
|
||||||
|
@@ ../default/upgrade/6.5.0-6.5.1/add_anonymous_option.sql
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_thread_subscriber.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_privileges.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_groups.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_privileges.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_file_attachments.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_forum_introduction.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_image_uploads.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_forum_no_category_posts.sql
|
||||||
|
\i ../default/upgrade/6.5.0-6.5.1/add_anonymous_option.sql
|
||||||
|
|
||||||
|
|
@ -79,6 +79,8 @@
|
||||||
<xrd:property name="/object/root"/>
|
<xrd:property name="/object/root"/>
|
||||||
<xrd:property name="/object/categories"/>
|
<xrd:property name="/object/categories"/>
|
||||||
<xrd:property name="/object/sender"/>
|
<xrd:property name="/object/sender"/>
|
||||||
|
<xrd:property name="/object/images"/>
|
||||||
|
<xrd:property name="/object/files"/>
|
||||||
</xrd:associations>
|
</xrd:associations>
|
||||||
</xrd:adapter>
|
</xrd:adapter>
|
||||||
</xrd:context>
|
</xrd:context>
|
||||||
|
|
@ -132,4 +134,77 @@
|
||||||
</xrd:adapter>
|
</xrd:adapter>
|
||||||
</xrd:context>
|
</xrd:context>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<xrd:context name="com.arsdigita.forum.ui.ConfirmStep">
|
||||||
|
<xrd:adapter objectType="com.arsdigita.forum.PostFileAttachment">
|
||||||
|
<xrd:attributes rule="exclude"/>
|
||||||
|
</xrd:adapter>
|
||||||
|
|
||||||
|
<xrd:adapter objectType="com.arsdigita.forum.PostImageAttachment">
|
||||||
|
<xrd:attributes rule="exclude"/>
|
||||||
|
</xrd:adapter>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <xrd:adapter objectType="com.arsdigita.forum.Post"
|
||||||
|
formatter="com.arsdigita.forum.ui.MessageXMLFormatter">
|
||||||
|
|
||||||
|
<xrd:attributes rule="exclude">
|
||||||
|
<xrd:property name="/object/id"/>
|
||||||
|
<xrd:property name="/object/objectType"/>
|
||||||
|
<xrd:property name="/object/defaultDomainClass"/>
|
||||||
|
<xrd:property name="/object/displayName"/>
|
||||||
|
<xrd:property name="/object/replyTo"/>
|
||||||
|
<xrd:property name="/object/objectID"/>
|
||||||
|
<xrd:property name="/object/messageID"/>
|
||||||
|
<xrd:property name="/object/root"/>
|
||||||
|
<xrd:property name="/object/inReplyTo"/>
|
||||||
|
|
||||||
|
<xrd:property name="/object/categories/objectType"/>
|
||||||
|
<xrd:property name="/object/categories/defaultDomainClass"/>
|
||||||
|
<xrd:property name="/object/categories/displayName"/>
|
||||||
|
<xrd:property name="/object/categories/isAbstract"/>
|
||||||
|
<xrd:property name="/object/categories/isEnabled"/>
|
||||||
|
<xrd:property name="/object/categories/defaultAncestors"/>
|
||||||
|
|
||||||
|
<xrd:property name="/object/sender/id"/>
|
||||||
|
<xrd:property name="/object/sender/objectType"/>
|
||||||
|
<xrd:property name="/object/sender/defaultDomainClass"/>
|
||||||
|
</xrd:attributes>
|
||||||
|
|
||||||
|
<xrd:associations rule="include">
|
||||||
|
<xrd:property name="/object/root"/>
|
||||||
|
<xrd:property name="/object/categories"/>
|
||||||
|
<xrd:property name="/object/sender"/>
|
||||||
|
<xrd:property name="/object/images"/>
|
||||||
|
<xrd:property name="/object/files"/>
|
||||||
|
</xrd:associations>
|
||||||
|
</xrd:adapter> -->
|
||||||
|
</xrd:context>
|
||||||
|
|
||||||
|
<xrd:context name="com.arsdigita.forum.search.PostMetadataProvider">
|
||||||
|
<xrd:adapter objectType="com.arsdigita.forum.Post">
|
||||||
|
<xrd:attributes rule="include">
|
||||||
|
<xrd:property name="/object/subject"/>
|
||||||
|
<xrd:property name="/object/body"/>
|
||||||
|
<xrd:property name="/object/images/description"/>
|
||||||
|
|
||||||
|
</xrd:attributes>
|
||||||
|
<xrd:associations rule="include">
|
||||||
|
<xrd:property name="/object/images"/>
|
||||||
|
</xrd:associations>
|
||||||
|
</xrd:adapter>
|
||||||
|
</xrd:context>
|
||||||
|
|
||||||
|
<xrd:context name="com.arsdigita.forum.search.FileAttachmentMetadataProvider">
|
||||||
|
<xrd:adapter objectType="com.arsdigita.forum.PostFileAttachment">
|
||||||
|
<xrd:attributes rule="exclude">
|
||||||
|
|
||||||
|
</xrd:attributes>
|
||||||
|
|
||||||
|
</xrd:adapter>
|
||||||
|
</xrd:context>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</xrd:adapters>
|
</xrd:adapters>
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,11 @@
|
||||||
<version from="1.4.3" to="1.4.4">
|
<version from="1.4.3" to="1.4.4">
|
||||||
<script sql="ccm-forum/upgrade/::database::-1.4.3-1.4.4.sql"/>
|
<script sql="ccm-forum/upgrade/::database::-1.4.3-1.4.4.sql"/>
|
||||||
</version>
|
</version>
|
||||||
|
<version from="6.5.0" to="6.5.1">
|
||||||
|
<script sql="ccm-forum/upgrade/::database::-6.5.0-6.5.1.sql"/>
|
||||||
|
<script class="com.arsdigita.forum.upgrade.CreateGroupsAndPortletType"/>
|
||||||
|
</version>
|
||||||
|
<version from="6.5.1" to="6.5.2">
|
||||||
|
<script class="com.arsdigita.forum.upgrade.CreateContainerGroups"/>
|
||||||
|
</version>
|
||||||
</upgrade>
|
</upgrade>
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.forum;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageFactory;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.page.BebopMapDispatcher;
|
|
||||||
import com.arsdigita.bebop.event.RequestEvent;
|
|
||||||
import com.arsdigita.bebop.event.RequestListener;
|
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
||||||
import com.arsdigita.forum.ui.Constants;
|
|
||||||
import com.arsdigita.forum.ui.ForumComponent;
|
|
||||||
import com.arsdigita.forum.ui.ThreadComponent;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps the bboard user interface onto "index.jsp" and "thread.jsp".
|
|
||||||
*
|
|
||||||
* @author Kevin Scaldeferri
|
|
||||||
* @author Vadim Nasardinov (vadimn@redhat.com)
|
|
||||||
*
|
|
||||||
* @version $Revision: #18 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
|
||||||
*/
|
|
||||||
public class BboardDispatcher extends BebopMapDispatcher
|
|
||||||
implements Constants {
|
|
||||||
public static final String versionId =
|
|
||||||
"$Id: BboardDispatcher.java 287 2005-02-22 00:29:02Z sskracic $" +
|
|
||||||
"$Author: sskracic $" +
|
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
|
||||||
|
|
||||||
private static final String XSL_HOOK = "forum";
|
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger
|
|
||||||
(BboardDispatcher.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. Instantiates the subsite url/page mapping.
|
|
||||||
*/
|
|
||||||
public BboardDispatcher() {
|
|
||||||
s_log.warn("BboardDispatcher created!");
|
|
||||||
|
|
||||||
Page index = buildForumPage(new BigDecimalParameter(TOPIC_PARAM));
|
|
||||||
addPage("", index);
|
|
||||||
addPage("index.jsp", index);
|
|
||||||
addPage("thread.jsp", buildThreadPage(
|
|
||||||
new BigDecimalParameter(THREAD_PARAM)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static Page buildThreadPage(BigDecimalParameter stateParam) {
|
|
||||||
Page threadPage = PageFactory.buildPage(XSL_HOOK, "Threads", "forumThreadPage");
|
|
||||||
threadPage.add(new ThreadComponent());
|
|
||||||
// Register the thread id parameter as a global state parameter.
|
|
||||||
threadPage.addGlobalStateParam(stateParam);
|
|
||||||
threadPage.addRequestListener
|
|
||||||
(new ThreadPageRequestListener(stateParam));
|
|
||||||
threadPage.lock();
|
|
||||||
return threadPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Page buildForumPage(BigDecimalParameter stateParam) {
|
|
||||||
Page page = PageFactory.buildPage(XSL_HOOK, "Forum", "forumPage");
|
|
||||||
ForumComponent forumComp = new ForumComponent();
|
|
||||||
page.add(forumComp);
|
|
||||||
page.addGlobalStateParam(stateParam);
|
|
||||||
page.addRequestListener(new ForumPageRequestListener(stateParam, forumComp));
|
|
||||||
page.lock();
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ThreadPageRequestListener implements RequestListener {
|
|
||||||
private BigDecimalParameter m_threadID;
|
|
||||||
|
|
||||||
public ThreadPageRequestListener(BigDecimalParameter threadID) {
|
|
||||||
m_threadID = threadID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void pageRequested(RequestEvent event) {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
ForumContext context = ForumContext.getContext(state);
|
|
||||||
context.setThreadID
|
|
||||||
((BigDecimal) event.getPageState().getValue(m_threadID));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ForumPageRequestListener implements RequestListener {
|
|
||||||
private BigDecimalParameter m_categorySelection;
|
|
||||||
private ForumComponent m_forumComp;
|
|
||||||
|
|
||||||
public ForumPageRequestListener(BigDecimalParameter categorySelection,
|
|
||||||
ForumComponent forumComp) {
|
|
||||||
m_categorySelection = categorySelection;
|
|
||||||
m_forumComp = forumComp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pageRequested(RequestEvent event) {
|
|
||||||
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
ForumContext context = ForumContext.getContext(state);
|
|
||||||
|
|
||||||
context.setCategorySelection
|
|
||||||
((BigDecimal) event.getPageState().getValue(m_categorySelection));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -36,7 +36,7 @@ import java.math.BigDecimal;
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision: #8 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision: 1.1 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DailySubscription extends ForumSubscription {
|
public class DailySubscription extends ForumSubscription {
|
||||||
|
|
@ -94,6 +94,11 @@ public class DailySubscription extends ForumSubscription {
|
||||||
return BASE_DATA_OBJECT_TYPE;
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getSubscriptionGroupName() {
|
||||||
|
return "Daily Digest Subscription Group";
|
||||||
|
}
|
||||||
|
|
||||||
private Digest getDigest() {
|
private Digest getDigest() {
|
||||||
if (m_digest == null) {
|
if (m_digest == null) {
|
||||||
DataObject digestData = (DataObject) get(DIGEST);
|
DataObject digestData = (DataObject) get(DIGEST);
|
||||||
|
|
@ -115,6 +120,11 @@ public class DailySubscription extends ForumSubscription {
|
||||||
public void sendNotification(Post post) {
|
public void sendNotification(Post post) {
|
||||||
Notification notification = new Notification(getGroup(), post);
|
Notification notification = new Notification(getGroup(), post);
|
||||||
notification.setDigest(getDigest());
|
notification.setDigest(getDigest());
|
||||||
|
if (Forum.getConfig().deleteNotifications()) {
|
||||||
|
// make sure we don't delete the post itself!!!
|
||||||
|
notification.setMessageDelete(Boolean.FALSE);
|
||||||
|
notification.setIsPermanent(Boolean.FALSE);
|
||||||
|
}
|
||||||
notification.save();
|
notification.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.arsdigita.categorization.Category;
|
import com.arsdigita.categorization.Category;
|
||||||
import com.arsdigita.cms.lifecycle.LifecycleDefinition;
|
import com.arsdigita.cms.lifecycle.LifecycleDefinition;
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
|
|
@ -37,27 +41,27 @@ import com.arsdigita.persistence.DataCollection;
|
||||||
import com.arsdigita.persistence.DataObject;
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.persistence.DataQuery;
|
import com.arsdigita.persistence.DataQuery;
|
||||||
import com.arsdigita.persistence.Filter;
|
import com.arsdigita.persistence.Filter;
|
||||||
|
import com.arsdigita.persistence.FilterFactory;
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.Session;
|
import com.arsdigita.persistence.Session;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.persistence.SessionManager;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
import com.arsdigita.web.Application;
|
import com.arsdigita.web.Application;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Forum class represents a discussion forum.
|
* The Forum class represents a discussion forum.
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision: #25 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision: 1.7 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Forum extends Application {
|
public class Forum extends Application {
|
||||||
|
public static final String THREAD_SUBSCRIPTION_GROUPS_NAME = "Thread Subscription Groups";
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: Forum.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: Forum.java 1628 2007-09-17 08:10:40Z chrisg23 $"
|
||||||
"$Author: sskracic $" +
|
+ "$Author: chrisg23 $"
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
+ "$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static ForumConfig s_config = new ForumConfig();
|
private static ForumConfig s_config = new ForumConfig();
|
||||||
|
|
||||||
|
|
@ -76,18 +80,48 @@ public class Forum extends Application {
|
||||||
"com.arsdigita.forum.Forum";
|
"com.arsdigita.forum.Forum";
|
||||||
|
|
||||||
public static final String PACKAGE_TYPE = "forum";
|
public static final String PACKAGE_TYPE = "forum";
|
||||||
|
//////
|
||||||
public static final String FORUM_MODERATION_PRIVILEGE
|
//Forum specific privileges
|
||||||
= "forum_moderation";
|
/////
|
||||||
|
public static final String FORUM_MODERATION_PRIVILEGE = "forum_moderation";
|
||||||
|
public static final String CREATE_THREAD_PRIVILEGE = "forum_create_thread";
|
||||||
|
public static final String RESPOND_TO_THREAD_PRIVILEGE = "forum_respond";
|
||||||
|
// separate read privilege required because all public users
|
||||||
|
// have READ on homepage, which is parent of forum, hence
|
||||||
|
// everyone inherits READ cg
|
||||||
|
//
|
||||||
|
// note in hindsight, I have stopped homepage being set as
|
||||||
|
// permission context for forum, because site search checks
|
||||||
|
// for READ privilege anyway, and so search results were being
|
||||||
|
// returned for non public posts. This means there is no longer
|
||||||
|
// any need for a separate forum_read privilege, though it
|
||||||
|
// does no harm. Now removed
|
||||||
|
// public static final String FORUM_READ_PRIVILEGE = "forum_read";
|
||||||
|
|
||||||
|
///////
|
||||||
|
// pdl forum attribute/association names
|
||||||
|
///////
|
||||||
private static final String POSTS = "posts";
|
private static final String POSTS = "posts";
|
||||||
private static final String SUBSCRIPTIONS = "subscriptions";
|
private static final String SUBSCRIPTIONS = "subscriptions";
|
||||||
private static final String MODERATION = "isModerated";
|
private static final String MODERATION = "isModerated";
|
||||||
private static final String NOTICEBOARD = "isNoticeboard";
|
private static final String NOTICEBOARD = "isNoticeboard";
|
||||||
|
private static final String ADMIN_GROUP = "adminGroup";
|
||||||
private static final String MODERATION_GROUP = "moderationGroup";
|
private static final String MODERATION_GROUP = "moderationGroup";
|
||||||
|
private static final String THREAD_CREATE_GROUP = "threadCreateGroup";
|
||||||
|
private static final String THREAD_RESPONDER_GROUP = "threadRespondGroup";
|
||||||
|
private static final String READ_GROUP = "readGroup";
|
||||||
private static final String CATEGORY = "category";
|
private static final String CATEGORY = "category";
|
||||||
private static final String EXPIRE_AFTER = "expireAfter";
|
private static final String EXPIRE_AFTER = "expireAfter";
|
||||||
private static final String LIFECYCLE_DEFINITION = "lifecycleDefinition";
|
private static final String LIFECYCLE_DEFINITION = "lifecycleDefinition";
|
||||||
|
// additional attributes added chris.gilbert@westsussex.gov.uk
|
||||||
|
private static final String ALLOW_FILE_ATTACHMENTS =
|
||||||
|
"fileAttachmentsAllowed";
|
||||||
|
private static final String ALLOW_IMAGE_UPLOADS = "imageUploadsAllowed";
|
||||||
|
private static final String AUTOSUBSCRIBE_THREAD_STARTER =
|
||||||
|
"autoSubscribeThreadStarter";
|
||||||
|
private static final String INTRODUCTION = "introduction";
|
||||||
|
private static final String NO_CATEGORY_POSTS = "noCategoryPostsAllowed";
|
||||||
|
private static final String ANONYMOUS_POSTS = "anonymousPostsAllowed";
|
||||||
|
|
||||||
public Forum(DataObject data) {
|
public Forum(DataObject data) {
|
||||||
super(data);
|
super(data);
|
||||||
|
|
@ -113,16 +147,26 @@ public class Forum extends Application {
|
||||||
* category for the Forum in the event that the Forum should be
|
* category for the Forum in the event that the Forum should be
|
||||||
* categorized.
|
* categorized.
|
||||||
* This also sets up instant and daily subscriptions on the Forum.
|
* This also sets up instant and daily subscriptions on the Forum.
|
||||||
* The default for moderation is false
|
* The default for moderation is false.
|
||||||
|
*
|
||||||
|
* Also sets default values for other forum settings. These can be
|
||||||
|
* amended under the setup tab in the ui
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static Forum create(String urlName, String title,
|
public static Forum create(String urlName, String title,
|
||||||
Application parent, boolean moderated) {
|
Application parent, boolean moderated) {
|
||||||
s_log.debug("creating forum " + title);
|
s_log.debug("creating forum " + title);
|
||||||
Forum forum = (Forum) Application.createApplication
|
Forum forum = (Forum) Application.createApplication
|
||||||
(BASE_DATA_OBJECT_TYPE, urlName, title, parent);
|
(BASE_DATA_OBJECT_TYPE, urlName, title, parent, true);
|
||||||
|
|
||||||
forum.setModerated(moderated);
|
forum.setModerated(moderated);
|
||||||
|
// default settings ensure legacy forum users do not
|
||||||
|
// see any change chris.gilbert@westsussex.gov.uk
|
||||||
|
forum.setAllowFileAttachments(false);
|
||||||
|
forum.setAllowImageUploads(false);
|
||||||
|
forum.setAutoSubscribeThreadCreator(false);
|
||||||
|
forum.setNoCategoryPostsAllowed(true);
|
||||||
|
forum.setAnonymousPostsAllowed(false);
|
||||||
|
|
||||||
return forum;
|
return forum;
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +195,22 @@ public class Forum extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Set introduction
|
||||||
|
*/
|
||||||
|
public void setIntroduction(String introduction) {
|
||||||
|
set(INTRODUCTION, introduction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return introduction
|
||||||
|
*/
|
||||||
|
|
||||||
|
public String getIntroduction() {
|
||||||
|
return (String) get(INTRODUCTION);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* creates a Root Category for the forum.
|
* creates a Root Category for the forum.
|
||||||
*/
|
*/
|
||||||
private Category createRootCategory() {
|
private Category createRootCategory() {
|
||||||
|
|
@ -162,7 +222,11 @@ public class Forum extends Application {
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createModerationGroup() {
|
private void createGroups() {
|
||||||
|
Group administrators = new Group();
|
||||||
|
administrators.setName(getTitle() + " Administrators");
|
||||||
|
setAssociation(ADMIN_GROUP, administrators);
|
||||||
|
|
||||||
Group moderators = new Group();
|
Group moderators = new Group();
|
||||||
moderators.setName(getTitle() + " Moderators");
|
moderators.setName(getTitle() + " Moderators");
|
||||||
setAssociation( MODERATION_GROUP, moderators );
|
setAssociation( MODERATION_GROUP, moderators );
|
||||||
|
|
@ -176,6 +240,37 @@ public class Forum extends Application {
|
||||||
// Actually, the only hack involved is making the email address unique.
|
// Actually, the only hack involved is making the email address unique.
|
||||||
String email = "forum-moderator-" + getID() + "-" + moderators.getID() + "@" + s_config.getReplyHostName();
|
String email = "forum-moderator-" + getID() + "-" + moderators.getID() + "@" + s_config.getReplyHostName();
|
||||||
moderators.setPrimaryEmail(new EmailAddress(email));
|
moderators.setPrimaryEmail(new EmailAddress(email));
|
||||||
|
|
||||||
|
// chris.gilbert@westsussex.gov.uk create additional groups for privilege
|
||||||
|
// assignment - could have assigned privileges directly without having associated
|
||||||
|
// groups, but this reduces rows in the (already enormous) dnm_permissions
|
||||||
|
// table
|
||||||
|
Group threadCreators = new Group();
|
||||||
|
threadCreators.setName(getTitle() + " Thread Creators");
|
||||||
|
setAssociation(THREAD_CREATE_GROUP, threadCreators);
|
||||||
|
|
||||||
|
Group threadResponders = new Group();
|
||||||
|
threadResponders.setName(getTitle() + " Thread Responders");
|
||||||
|
setAssociation(THREAD_RESPONDER_GROUP, threadResponders);
|
||||||
|
|
||||||
|
Group forumReaders = new Group();
|
||||||
|
forumReaders.setName(getTitle() + " Readers");
|
||||||
|
setAssociation(READ_GROUP, forumReaders);
|
||||||
|
|
||||||
|
Group container = getGroup();
|
||||||
|
|
||||||
|
container.addSubgroup(administrators);
|
||||||
|
container.addSubgroup(moderators);
|
||||||
|
container.addSubgroup(threadCreators);
|
||||||
|
container.addSubgroup(threadResponders);
|
||||||
|
container.addSubgroup(forumReaders);
|
||||||
|
Group threadSubscriptions = new Group();
|
||||||
|
threadSubscriptions.setName(THREAD_SUBSCRIPTION_GROUPS_NAME);
|
||||||
|
container.addSubgroup(threadSubscriptions);
|
||||||
|
container.save();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
@ -184,8 +279,13 @@ public class Forum extends Application {
|
||||||
if (isNew()) {
|
if (isNew()) {
|
||||||
setModerated(false);
|
setModerated(false);
|
||||||
setNoticeboard(false);
|
setNoticeboard(false);
|
||||||
|
setAllowFileAttachments(false);
|
||||||
|
setAllowImageUploads(false);
|
||||||
|
setAutoSubscribeThreadCreator(false);
|
||||||
|
setNoCategoryPostsAllowed(true);
|
||||||
|
setAnonymousPostsAllowed(false);
|
||||||
createRootCategory();
|
createRootCategory();
|
||||||
createModerationGroup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,14 +299,71 @@ public class Forum extends Application {
|
||||||
protected void afterSave() {
|
protected void afterSave() {
|
||||||
if (m_wasNew) {
|
if (m_wasNew) {
|
||||||
PermissionService.setContext(getRootCategory(), this);
|
PermissionService.setContext(getRootCategory(), this);
|
||||||
|
createGroups();
|
||||||
|
if (getAdminGroup() != null) {
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.ADMIN,
|
||||||
|
this,
|
||||||
|
getAdminGroup()));
|
||||||
|
s_log.debug(
|
||||||
|
"Current user : "
|
||||||
|
+ Kernel.getContext().getParty().getPrimaryEmail()
|
||||||
|
+ " class is "
|
||||||
|
+ Kernel.getContext().getParty().getClass());
|
||||||
|
//
|
||||||
|
// chris.gilbert@westsussex.gov.uk Original plan was that creator of forum
|
||||||
|
// is administrator by default, but party from Kernel at this point in code is
|
||||||
|
// acs-system-party - creation must happen in a KernelExcersion somewhere
|
||||||
|
// though I can't immediately see where.
|
||||||
|
// as a consequence, code below justs causes a classcast exception,
|
||||||
|
//
|
||||||
|
// revisit, but in meantime, only site admin can administer new forum
|
||||||
|
// until forum admin permissions set in UI
|
||||||
|
//
|
||||||
|
// User creator = (User) Kernel.getContext().getParty();
|
||||||
|
// can't be null but let's be supercautious
|
||||||
|
// if (creator != null) {
|
||||||
|
// getAdminGroup().addMember(creator);
|
||||||
|
// }
|
||||||
|
///
|
||||||
|
}
|
||||||
|
|
||||||
if (getModerationGroup() != null ) {
|
if (getModerationGroup() != null ) {
|
||||||
PermissionService.grantPermission(
|
PermissionService.grantPermission(
|
||||||
new PermissionDescriptor(
|
new PermissionDescriptor(
|
||||||
PrivilegeDescriptor.get(FORUM_MODERATION_PRIVILEGE),
|
PrivilegeDescriptor.get(FORUM_MODERATION_PRIVILEGE),
|
||||||
this,
|
this,
|
||||||
getModerationGroup())
|
getModerationGroup()));
|
||||||
);
|
}
|
||||||
|
if (getThreadCreateGroup() != null) {
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.get(CREATE_THREAD_PRIVILEGE),
|
||||||
|
this,
|
||||||
|
getThreadCreateGroup()));
|
||||||
|
// chris.gilbert@westsussex.gov.uk
|
||||||
|
// wouldn't do this normally, but this enables legacy implementations
|
||||||
|
// to use new version without any side effects
|
||||||
|
// public can view forum by default and see create thread link - existing
|
||||||
|
// code forces login if link is selected
|
||||||
|
getThreadCreateGroup().addMember(Kernel.getPublicUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getThreadResponderGroup() != null) {
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.get(RESPOND_TO_THREAD_PRIVILEGE),
|
||||||
|
this,
|
||||||
|
getThreadResponderGroup()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getReadGroup() != null) {
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.READ,
|
||||||
|
this,
|
||||||
|
getReadGroup()));
|
||||||
}
|
}
|
||||||
KernelExcursion excursion = new KernelExcursion() {
|
KernelExcursion excursion = new KernelExcursion() {
|
||||||
protected void excurse() {
|
protected void excurse() {
|
||||||
|
|
@ -243,7 +400,15 @@ public class Forum extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
super.afterSave();
|
// chris.gilbert@westsussex.gov.uk line removed.
|
||||||
|
// afterSave in Application sets permission
|
||||||
|
// context of forum to parent app (portal homepage)
|
||||||
|
// don't want to inherit permissions of portal,
|
||||||
|
// as public users have 'READ' privilege on this
|
||||||
|
// and so get shown postings in search results.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// super.afterSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getBaseDataObjectType() {
|
protected String getBaseDataObjectType() {
|
||||||
|
|
@ -287,6 +452,38 @@ public class Forum extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* gets all pending messages and messages for reapproval - allows
|
||||||
|
* moderators to see which messages require their attention
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DataAssociation getPendingPosts() {
|
||||||
|
// doesn't use getPosts in view of the warning that it
|
||||||
|
// may disappear
|
||||||
|
DataAssociation posts = (DataAssociation) get(POSTS);
|
||||||
|
FilterFactory factory = posts.getFilterFactory();
|
||||||
|
Filter pending = factory.equals(Post.STATUS, Post.PENDING);
|
||||||
|
Filter reapprove = factory.equals(Post.STATUS, Post.REAPPROVE);
|
||||||
|
;
|
||||||
|
|
||||||
|
posts.addFilter(factory.or().addFilter(pending).addFilter(reapprove));
|
||||||
|
|
||||||
|
return posts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets all suppressed messages - allows moderators to see which messages
|
||||||
|
* heve been rejectedrequire their attention
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DataAssociation getSuppressedPosts() {
|
||||||
|
// doesn't use getPosts in view of the warning that it
|
||||||
|
// may disappear
|
||||||
|
DataAssociation posts = (DataAssociation) get(POSTS);
|
||||||
|
posts.addEqualsFilter(Post.STATUS, Post.SUPPRESSED);
|
||||||
|
return posts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Gets a ThreadCollection of the threads in this forum. I.e. the
|
* Gets a ThreadCollection of the threads in this forum. I.e. the
|
||||||
* top-level posts which are not replies to any other post.
|
* top-level posts which are not replies to any other post.
|
||||||
*/
|
*/
|
||||||
|
|
@ -358,9 +555,9 @@ public class Forum extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
return threads;
|
return threads;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up instant and daily subscriptions for the forum. Daily
|
* Sets up instant and daily subscriptions for the forum. Daily
|
||||||
|
|
@ -527,6 +724,12 @@ public class Forum extends Application {
|
||||||
return Boolean.TRUE.equals(get(NOTICEBOARD));
|
return Boolean.TRUE.equals(get(NOTICEBOARD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the administrator group. Null if it doesn't exist */
|
||||||
|
public Group getAdminGroup() {
|
||||||
|
DataObject dObj = (DataObject) get(ADMIN_GROUP);
|
||||||
|
Assert.exists(dObj, DataObject.class);
|
||||||
|
return (Group) DomainObjectFactory.newInstance(dObj);
|
||||||
|
}
|
||||||
/** Returns the moderator group. Null if it doesn't exist */
|
/** Returns the moderator group. Null if it doesn't exist */
|
||||||
public Group getModerationGroup() {
|
public Group getModerationGroup() {
|
||||||
DataObject dObj = (DataObject) get( MODERATION_GROUP );
|
DataObject dObj = (DataObject) get( MODERATION_GROUP );
|
||||||
|
|
@ -534,6 +737,27 @@ public class Forum extends Application {
|
||||||
return (Group)DomainObjectFactory.newInstance(dObj);
|
return (Group)DomainObjectFactory.newInstance(dObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the thread create group. Null if it doesn't exist */
|
||||||
|
public Group getThreadCreateGroup() {
|
||||||
|
DataObject dObj = (DataObject) get(THREAD_CREATE_GROUP);
|
||||||
|
Assert.exists(dObj, DataObject.class);
|
||||||
|
return (Group) DomainObjectFactory.newInstance(dObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the thread reply group. Null if it doesn't exist */
|
||||||
|
public Group getThreadResponderGroup() {
|
||||||
|
DataObject dObj = (DataObject) get(THREAD_RESPONDER_GROUP);
|
||||||
|
Assert.exists(dObj, DataObject.class);
|
||||||
|
return (Group) DomainObjectFactory.newInstance(dObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the read group. Null if it doesn't exist */
|
||||||
|
public Group getReadGroup() {
|
||||||
|
DataObject dObj = (DataObject) get(READ_GROUP);
|
||||||
|
Assert.exists(dObj, DataObject.class);
|
||||||
|
return (Group) DomainObjectFactory.newInstance(dObj);
|
||||||
|
}
|
||||||
|
|
||||||
public String getContextPath() {
|
public String getContextPath() {
|
||||||
return "/ccm-forum";
|
return "/ccm-forum";
|
||||||
}
|
}
|
||||||
|
|
@ -555,7 +779,7 @@ public class Forum extends Application {
|
||||||
}
|
}
|
||||||
LifecycleDefinition newLife = new LifecycleDefinition();
|
LifecycleDefinition newLife = new LifecycleDefinition();
|
||||||
newLife.setLabel("Delete expired noticeboard postings");
|
newLife.setLabel("Delete expired noticeboard postings");
|
||||||
newLife.addPhaseDefinition("Noticeboard posting lifespan",
|
newLife.addPhaseDefinition("Forum posting lifespan",
|
||||||
null,
|
null,
|
||||||
new Integer(0),
|
new Integer(0),
|
||||||
new Integer(1440 * value), // in minutes
|
new Integer(1440 * value), // in minutes
|
||||||
|
|
@ -565,13 +789,20 @@ public class Forum extends Application {
|
||||||
// have the same expiration policy.
|
// have the same expiration policy.
|
||||||
DataAssociationCursor posts = getPosts().cursor();
|
DataAssociationCursor posts = getPosts().cursor();
|
||||||
while (posts.next()) {
|
while (posts.next()) {
|
||||||
Post post
|
Post post =
|
||||||
= (Post)DomainObjectFactory.newInstance(
|
(Post) DomainObjectFactory.newInstance(posts.getDataObject());
|
||||||
posts.getDataObject());
|
if (post
|
||||||
s_log.debug("Resetting expiration lifecycle for " + post.getOID());
|
.getThread()
|
||||||
|
.getRootMessage()
|
||||||
|
.getID()
|
||||||
|
.equals(post.getID())) {
|
||||||
|
|
||||||
|
s_log.debug(
|
||||||
|
"Resetting expiration lifecycle for " + post.getOID());
|
||||||
post.setLifecycle(newLife);
|
post.setLifecycle(newLife);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getExpireAfter() {
|
public int getExpireAfter() {
|
||||||
BigDecimal expire = (BigDecimal) get(EXPIRE_AFTER);
|
BigDecimal expire = (BigDecimal) get(EXPIRE_AFTER);
|
||||||
|
|
@ -594,5 +825,119 @@ public class Forum extends Application {
|
||||||
set(LIFECYCLE_DEFINITION, life);
|
set(LIFECYCLE_DEFINITION, life);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method required for upgrade - normally groups are set during forum creation and so
|
||||||
|
* there is no need to invoke a setter
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setAdminGroup(Group group) {
|
||||||
|
setAssociation(ADMIN_GROUP, group);
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, this, group));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* method required for upgrade - normally groups are set during forum creation and so
|
||||||
|
* there is no need to invoke a setter
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setThreadCreatorGroup(Group group) {
|
||||||
|
setAssociation(THREAD_CREATE_GROUP, group);
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.get(CREATE_THREAD_PRIVILEGE),
|
||||||
|
this,
|
||||||
|
group));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* method required for upgrade - normally groups are set during forum creation and so
|
||||||
|
* there is no need to invoke a setter
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setThreadResponderGroup(Group group) {
|
||||||
|
setAssociation(THREAD_RESPONDER_GROUP, group);
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(
|
||||||
|
PrivilegeDescriptor.get(RESPOND_TO_THREAD_PRIVILEGE),
|
||||||
|
this,
|
||||||
|
group));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* method required for upgrade - normally groups are set during forum creation and so
|
||||||
|
* there is no need to invoke a setter
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setReaderGroup(Group group) {
|
||||||
|
setAssociation(READ_GROUP, group);
|
||||||
|
PermissionService.grantPermission(
|
||||||
|
new PermissionDescriptor(PrivilegeDescriptor.READ, this, group));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean allowFileAttachments() {
|
||||||
|
return ((Boolean) get(ALLOW_FILE_ATTACHMENTS)).booleanValue();
|
||||||
|
}
|
||||||
|
public boolean allowImageUploads() {
|
||||||
|
return ((Boolean) get(ALLOW_IMAGE_UPLOADS)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean autoSubscribeThreadStarter() {
|
||||||
|
return ((Boolean) get(AUTOSUBSCRIBE_THREAD_STARTER)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean noCategoryPostsAllowed() {
|
||||||
|
return ((Boolean) get(NO_CATEGORY_POSTS)).booleanValue();
|
||||||
|
}
|
||||||
|
public boolean anonymousPostsAllowed() {
|
||||||
|
return ((Boolean) get(ANONYMOUS_POSTS)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowFileAttachments(boolean allow) {
|
||||||
|
set(ALLOW_FILE_ATTACHMENTS, new Boolean(allow));
|
||||||
|
}
|
||||||
|
public void setAllowImageUploads(boolean allow) {
|
||||||
|
set(ALLOW_IMAGE_UPLOADS, new Boolean(allow));
|
||||||
|
}
|
||||||
|
public void setAutoSubscribeThreadCreator(boolean subscribe) {
|
||||||
|
set(AUTOSUBSCRIBE_THREAD_STARTER, new Boolean(subscribe));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNoCategoryPostsAllowed(boolean allow) {
|
||||||
|
set(NO_CATEGORY_POSTS, new Boolean(allow));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnonymousPostsAllowed(boolean allow) {
|
||||||
|
set(ANONYMOUS_POSTS, new Boolean(allow));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle (String title) {
|
||||||
|
String oldTitle = getTitle();
|
||||||
|
super.setTitle(title);
|
||||||
|
if (!oldTitle.equals(title)) {
|
||||||
|
// 1. rename permission groups
|
||||||
|
getAdminGroup().setName(title + " Administrators");
|
||||||
|
getModerationGroup().setName(title + " Moderators");
|
||||||
|
getThreadCreateGroup().setName(title + " Thread Creators");
|
||||||
|
getThreadResponderGroup().setName(title + " Thread Responders");
|
||||||
|
getReadGroup().setName(title + " Readers");
|
||||||
|
DataCollection subscriptions = getSubscriptions();
|
||||||
|
while (subscriptions.next()) {
|
||||||
|
ForumSubscription subscription = (ForumSubscription)DomainObjectFactory.newInstance(subscriptions.getDataObject());
|
||||||
|
subscription.getGroup().setName(subscription.getGroupName(this));
|
||||||
|
}
|
||||||
|
ThreadCollection threads = getThreads();
|
||||||
|
while (threads.next()) {
|
||||||
|
ThreadSubscription threadSub = ThreadSubscription.getThreadSubscription(threads.getMessageThread());
|
||||||
|
threadSub.getGroup().setName(threadSub.getSubscriptionGroupName(this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,33 +18,34 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.User;
|
||||||
|
import com.arsdigita.kernel.UserCollection;
|
||||||
import com.arsdigita.runtime.AbstractConfig;
|
import com.arsdigita.runtime.AbstractConfig;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
import com.arsdigita.util.parameter.BooleanParameter;
|
import com.arsdigita.util.parameter.BooleanParameter;
|
||||||
|
import com.arsdigita.util.parameter.IntegerParameter;
|
||||||
import com.arsdigita.util.parameter.Parameter;
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
import com.arsdigita.util.parameter.URLParameter;
|
|
||||||
import com.arsdigita.util.parameter.StringParameter;
|
import com.arsdigita.util.parameter.StringParameter;
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
import com.arsdigita.util.parameter.URLParameter;
|
||||||
|
|
||||||
import com.arsdigita.kernel.UserCollection;
|
|
||||||
import com.arsdigita.kernel.User;
|
|
||||||
import com.arsdigita.web.Web;
|
import com.arsdigita.web.Web;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of configuration parameters for forums.
|
* A set of configuration parameters for forums.
|
||||||
*
|
*
|
||||||
* @author Justin Ross <jross@redhat.com>
|
* @author Justin Ross <jross@redhat.com>
|
||||||
* @version $Id: ForumConfig.java 1377 2006-11-17 10:39:41Z sskracic $
|
* @version $Id: ForumConfig.java 1628 2007-09-17 08:10:40Z chrisg23 $
|
||||||
*/
|
*/
|
||||||
public class ForumConfig extends AbstractConfig {
|
public class ForumConfig extends AbstractConfig {
|
||||||
public final static String versionId =
|
public final static String versionId =
|
||||||
"$Id: ForumConfig.java 1377 2006-11-17 10:39:41Z sskracic $" +
|
"$Id: ForumConfig.java 1628 2007-09-17 08:10:40Z chrisg23 $" +
|
||||||
"$Author: sskracic $" +
|
"$Author: chrisg23 $" +
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
"$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(ForumConfig.class);
|
private static final Logger s_log = Logger.getLogger(ForumConfig.class);
|
||||||
|
|
@ -53,7 +54,18 @@ public class ForumConfig extends AbstractConfig {
|
||||||
private Parameter m_authorEditPosts;
|
private Parameter m_authorEditPosts;
|
||||||
private Parameter m_digestUserEmail;
|
private Parameter m_digestUserEmail;
|
||||||
private Parameter m_replyHostName;
|
private Parameter m_replyHostName;
|
||||||
|
private Parameter m_disablePageCaching;
|
||||||
|
private Parameter m_adminOnlyCreateTopics;
|
||||||
|
private Parameter m_maxImageSize;
|
||||||
|
private Parameter m_maxFileSize;
|
||||||
private final Parameter m_adapters;
|
private final Parameter m_adapters;
|
||||||
|
private Parameter m_showAllThreadAlerts;
|
||||||
|
private Parameter m_showNewTabs;
|
||||||
|
private Parameter m_useWysiwygEditor;
|
||||||
|
private Parameter m_rejectionMessage;
|
||||||
|
private Parameter m_threadPageSize;
|
||||||
|
private Parameter m_quickFinish;
|
||||||
|
private Parameter m_deleteSentSubscriptionNotifications;
|
||||||
|
|
||||||
public ForumConfig() {
|
public ForumConfig() {
|
||||||
m_adminEditPosts = new BooleanParameter(
|
m_adminEditPosts = new BooleanParameter(
|
||||||
|
|
@ -72,6 +84,49 @@ public class ForumConfig extends AbstractConfig {
|
||||||
"com.arsdigita.forum.digest_user_email",
|
"com.arsdigita.forum.digest_user_email",
|
||||||
Parameter.OPTIONAL,
|
Parameter.OPTIONAL,
|
||||||
null);
|
null);
|
||||||
|
m_disablePageCaching = new BooleanParameter (
|
||||||
|
"com.arsdigita.forum.disable_page_caching",
|
||||||
|
Parameter.REQUIRED,
|
||||||
|
Boolean.FALSE);
|
||||||
|
|
||||||
|
m_adminOnlyCreateTopics = new BooleanParameter (
|
||||||
|
"com.arsdigita.forum.admin_only_to_create_topics",
|
||||||
|
Parameter.REQUIRED,
|
||||||
|
Boolean.FALSE);
|
||||||
|
m_maxImageSize = new IntegerParameter (
|
||||||
|
"com.arsdigita.forum.maximum_image_size",
|
||||||
|
Parameter.OPTIONAL, null);
|
||||||
|
m_maxFileSize = new IntegerParameter (
|
||||||
|
"com.arsdigita.forum.maximum_file_size",
|
||||||
|
Parameter.OPTIONAL, null);
|
||||||
|
|
||||||
|
m_showNewTabs = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.show_new_tabs",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
Boolean.FALSE);
|
||||||
|
m_showAllThreadAlerts = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.show_all_forum_thread_alerts",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
Boolean.TRUE);
|
||||||
|
m_useWysiwygEditor = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.use_wysiwyg_editor",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
Boolean.FALSE);
|
||||||
|
m_rejectionMessage = new StringParameter(
|
||||||
|
"com.arsdigita.forum.rejection_form_message.example",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
null);
|
||||||
|
m_threadPageSize = new IntegerParameter (
|
||||||
|
"com.arsdigita.forum.thread_page_size",
|
||||||
|
Parameter.REQUIRED, new Integer(10));
|
||||||
|
m_quickFinish = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.allow_quick_finish",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
Boolean.FALSE);
|
||||||
|
m_deleteSentSubscriptionNotifications = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.delete_sent_subscription_notifications",
|
||||||
|
Parameter.OPTIONAL,
|
||||||
|
Boolean.FALSE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_adapters = new URLParameter
|
m_adapters = new URLParameter
|
||||||
|
|
@ -88,6 +143,17 @@ public class ForumConfig extends AbstractConfig {
|
||||||
register(m_authorEditPosts);
|
register(m_authorEditPosts);
|
||||||
register(m_replyHostName);
|
register(m_replyHostName);
|
||||||
register(m_adapters);
|
register(m_adapters);
|
||||||
|
register(m_disablePageCaching);
|
||||||
|
register(m_adminOnlyCreateTopics);
|
||||||
|
register(m_maxImageSize);
|
||||||
|
register(m_maxFileSize);
|
||||||
|
register(m_showAllThreadAlerts);
|
||||||
|
register(m_showNewTabs);
|
||||||
|
register(m_useWysiwygEditor);
|
||||||
|
register(m_rejectionMessage);
|
||||||
|
register(m_threadPageSize);
|
||||||
|
register(m_quickFinish);
|
||||||
|
register(m_deleteSentSubscriptionNotifications);
|
||||||
loadInfo();
|
loadInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,6 +189,28 @@ public class ForumConfig extends AbstractConfig {
|
||||||
return hostName;
|
return hostName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports prevention of client and middleware caching -
|
||||||
|
* use in situations where users with different
|
||||||
|
* permissions share machines
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean disableClientPageCaching () {
|
||||||
|
return ((Boolean)get(m_disablePageCaching)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, disables topic tab for non admin users. Topic
|
||||||
|
* tab does not access control topic creation, so set this
|
||||||
|
* to true to maintain control of the topics on the forum.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean topicCreationByAdminOnly () {
|
||||||
|
return ((Boolean)get(m_adminOnlyCreateTopics)).booleanValue();
|
||||||
|
}
|
||||||
public User getDigestUser() {
|
public User getDigestUser() {
|
||||||
String email = getDigestUserEmail();
|
String email = getDigestUserEmail();
|
||||||
|
|
||||||
|
|
@ -138,4 +226,85 @@ public class ForumConfig extends AbstractConfig {
|
||||||
users.close();
|
users.close();
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* returns the maximum allowed size (in bytes) of
|
||||||
|
* image files attached to posts. Any larger
|
||||||
|
* files are rejected by UI validation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getMaxImageSize() {
|
||||||
|
Integer size = (Integer)get(m_maxImageSize);
|
||||||
|
long longSize = Long.MAX_VALUE;
|
||||||
|
if (size != null) {
|
||||||
|
longSize = size.longValue();
|
||||||
|
}
|
||||||
|
return longSize;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* returns the maximum allowed size (in bytes) of
|
||||||
|
* files attached to posts. Any larger
|
||||||
|
* files are rejected by UI validation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getMaxFileSize() {
|
||||||
|
Integer size = (Integer)get(m_maxFileSize);
|
||||||
|
long longSize = Long.MAX_VALUE;
|
||||||
|
if (size != null) {
|
||||||
|
longSize = size.longValue();
|
||||||
|
}
|
||||||
|
return longSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, alerts tab displays thread alerts for this and all other
|
||||||
|
* forums. If false, only display thread subscriptions for current
|
||||||
|
* forum.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* If true, the thread alert page lists thread alerts from
|
||||||
|
* all forums - alerts not from the current forum have
|
||||||
|
* links to the thread displayed within the context of
|
||||||
|
* the current forum. Looks weird and needs to be sorted out
|
||||||
|
* presumably the correct forum needs to be set in the ForumContext
|
||||||
|
* when a link is selected
|
||||||
|
*/
|
||||||
|
public boolean showThreadAlertsForAllForums () {
|
||||||
|
return ((Boolean)get(m_showAllThreadAlerts)).booleanValue();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* if true, displays setup and permissions tabs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean showNewTabs () {
|
||||||
|
return ((Boolean)get(m_showNewTabs)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean useWysiwygEditor () {
|
||||||
|
return ((Boolean)get(m_useWysiwygEditor)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message added to the bottom of the moderation reection email.
|
||||||
|
* May give details about what the poster can do if not happy
|
||||||
|
* with rejection
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getRejectionMessage () {
|
||||||
|
return (String)get(m_rejectionMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getThreadPageSize () {
|
||||||
|
return ((Integer)get(m_threadPageSize)).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean quickFinishAllowed () {
|
||||||
|
return ((Boolean)get(m_quickFinish)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean deleteNotifications () {
|
||||||
|
return ((Boolean)get(m_deleteSentSubscriptionNotifications)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,62 @@ com.arsdigita.forum.admin_can_edit_posts.purpose=Whether administrators can edit
|
||||||
com.arsdigita.forum.admin_can_edit_posts.format=[boolean]
|
com.arsdigita.forum.admin_can_edit_posts.format=[boolean]
|
||||||
com.arsdigita.forum.admin_can_edit_posts.example=true|false
|
com.arsdigita.forum.admin_can_edit_posts.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.admin_only_to_create_topics.title=Prevent other users creating new topics
|
||||||
|
com.arsdigita.forum.admin_only_to_create_topics.purpose=Whether only admin can create (true) topics or all users (false)
|
||||||
|
com.arsdigita.forum.admin_only_to_create_topics.format=[boolean]
|
||||||
|
com.arsdigita.forum.admin_only_to_create_topics.example=true|false
|
||||||
|
|
||||||
com.arsdigita.forum.author_can_edit_posts.title=Authors can edit posts
|
com.arsdigita.forum.author_can_edit_posts.title=Authors can edit posts
|
||||||
com.arsdigita.forum.author_can_edit_posts.purpose=Whether authors can edijt their posts
|
com.arsdigita.forum.author_can_edit_posts.purpose=Whether authors can edijt their posts
|
||||||
com.arsdigita.forum.author_can_edit_posts.format=[boolean]
|
com.arsdigita.forum.author_can_edit_posts.format=[boolean]
|
||||||
com.arsdigita.forum.author_can_edit_posts.example=true|false
|
com.arsdigita.forum.author_can_edit_posts.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.disable_page_caching.title=Disable client & middleware page caching
|
||||||
|
com.arsdigita.forum.disable_page_caching.purpose=Disable caching, particularly for situations where users share PCs
|
||||||
|
com.arsdigita.forum.disable_page_caching.format=[boolean]
|
||||||
|
com.arsdigita.forum.disable_page_caching.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.maximum_image_size.title=Maximum size of image uploads in bytes
|
||||||
|
com.arsdigita.forum.maximum_image_size.purpose=Prevent huge images from being uploaded
|
||||||
|
com.arsdigita.forum.maximum_image_size.format=[integer]
|
||||||
|
com.arsdigita.forum.maximum_image_size.example=1048576
|
||||||
|
|
||||||
|
com.arsdigita.forum.maximum_file_size.title=Maximum size of file uploads in bytes
|
||||||
|
com.arsdigita.forum.maximum_file_size.purpose=prevent huge files from being uploaded
|
||||||
|
com.arsdigita.forum.maximum_file_size.format=[integer]
|
||||||
|
com.arsdigita.forum.maximum_file_size.example=1048576
|
||||||
|
|
||||||
|
com.arsdigita.forum.show_all_forum_thread_alerts.title=Display thread alerts from all forums
|
||||||
|
com.arsdigita.forum.show_all_forum_thread_alerts.purpose=decide whether to display thread alerts for this forum only or all alerts for user
|
||||||
|
com.arsdigita.forum.show_all_forum_thread_alerts.format=[boolean]
|
||||||
|
com.arsdigita.forum.show_all_forum_thread_alerts.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.show_new_tabs.title=Display permissions and setup tabs
|
||||||
|
com.arsdigita.forum.show_new_tabs.purpose=to allow forum users to completely hide new functionality
|
||||||
|
com.arsdigita.forum.show_new_tabs.format=[boolean]
|
||||||
|
com.arsdigita.forum.show_new_tabs.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.use_wysiwyg_editor.title=Use HTML Editor, or stick with legacy version
|
||||||
|
com.arsdigita.forum.use_wysiwyg_editor.purpose=to allow legacy implementations to stick with existing stylesheets
|
||||||
|
com.arsdigita.forum.use_wysiwyg_editor.format=[boolean]
|
||||||
|
com.arsdigita.forum.use_wysiwyg_editor.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.rejection_form_message.title=Instructions to poster added to bottom of email
|
||||||
|
com.arsdigita.forum.rejection_form_message.purpose=tail of email that may contain site specific information - who to contact etc
|
||||||
|
com.arsdigita.forum.rejection_form_message.format=[string]
|
||||||
|
com.arsdigita.forum.rejection_form_message.example=Please do not reply to this email. If you have any comments, please email webmaster@example.com
|
||||||
|
|
||||||
|
com.arsdigita.forum.thread_page_size.title=Number of threads displayed per page
|
||||||
|
com.arsdigita.forum.thread_page_size.purpose=balance page loading time against number of key preses
|
||||||
|
com.arsdigita.forum.thread_page_size.format=[integer]
|
||||||
|
com.arsdigita.forum.thread_page_size.example=10
|
||||||
|
|
||||||
|
com.arsdigita.forum.allow_quick_finish.title=Allow quick finish on posts
|
||||||
|
com.arsdigita.forum.allow_quick_finish.purpose=To give users the option of omitting post steps if they have a quick text post
|
||||||
|
com.arsdigita.forum.allow_quick_finish.format=[boolean]
|
||||||
|
com.arsdigita.forum.allow_quick_finish.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.delete_sent_subscription_notifications.title=Delete Sent Subscription Notifications
|
||||||
|
com.arsdigita.forum.delete_sent_subscription_notifications.purpose=Enable deletion of successfully sent notifications to save space in DB
|
||||||
|
com.arsdigita.forum.delete_sent_subscription_notifications.format=[boolean]
|
||||||
|
com.arsdigita.forum.delete_sent_subscription_notifications.example=true|false
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,11 @@ import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -103,6 +106,15 @@ public final class ForumContext {
|
||||||
// thread.assertPrivilege(PrivilegeDescriptor.READ);
|
// thread.assertPrivilege(PrivilegeDescriptor.READ);
|
||||||
m_thread = thread;
|
m_thread = thread;
|
||||||
} catch (DataObjectNotFoundException ex) {
|
} catch (DataObjectNotFoundException ex) {
|
||||||
|
PageState state = PageState.getPageState();
|
||||||
|
if (state != null) {
|
||||||
|
try {
|
||||||
|
state.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {
|
||||||
|
s_log.warn("Thread not found, but failed to send a response to user");
|
||||||
|
}
|
||||||
|
}
|
||||||
throw new UncheckedWrapperException(
|
throw new UncheckedWrapperException(
|
||||||
"Couldn't find a MessageThread for " + threadID, ex);
|
"Couldn't find a MessageThread for " + threadID, ex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.PageFactory;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
|
import com.arsdigita.bebop.event.RequestEvent;
|
||||||
|
import com.arsdigita.bebop.event.RequestListener;
|
||||||
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
|
import com.arsdigita.forum.ui.ForumComponent;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.toolbox.ui.ApplicationAuthenticationListener;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Implementation of com.arsdigita.forum.PageBuilder that creates a basic forum page with read access check
|
||||||
|
*/
|
||||||
|
public class ForumPageBuilder implements PageBuilder, Constants {
|
||||||
|
|
||||||
|
|
||||||
|
public Page buildPage() {
|
||||||
|
Page page = PageFactory.buildPage(Constants.FORUM_XML_PREFIX, "Forum", "forumPage");
|
||||||
|
//Output the title in an easy to find place
|
||||||
|
page.add(new SimpleComponent(){
|
||||||
|
public void generateXML(PageState state, Element parent) {
|
||||||
|
Element nameElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":name", Constants.FORUM_XML_NS);
|
||||||
|
nameElement.setText(ForumContext.getContext(state).getForum().getTitle());
|
||||||
|
Element introductionElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":introduction", Constants.FORUM_XML_NS);
|
||||||
|
introductionElement.setText(ForumContext.getContext(state).getForum().getIntroduction());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ForumComponent forumComp = getForumComponent();
|
||||||
|
page.add(forumComp);
|
||||||
|
BigDecimalParameter topic = new BigDecimalParameter(TOPIC_PARAM);
|
||||||
|
page.addGlobalStateParam(topic);
|
||||||
|
page.addRequestListener(new ApplicationAuthenticationListener(PrivilegeDescriptor.READ));
|
||||||
|
page.addRequestListener(new ForumPageRequestListener(topic, forumComp));
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ForumComponent getForumComponent() {
|
||||||
|
return new ForumComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ForumPageRequestListener implements RequestListener {
|
||||||
|
private BigDecimalParameter m_categorySelection;
|
||||||
|
private ForumComponent m_forumComp;
|
||||||
|
|
||||||
|
public ForumPageRequestListener(BigDecimalParameter topicSelection, ForumComponent forumComp) {
|
||||||
|
m_categorySelection = topicSelection;
|
||||||
|
m_forumComp = forumComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pageRequested(RequestEvent event) {
|
||||||
|
|
||||||
|
PageState state = event.getPageState();
|
||||||
|
ForumContext context = ForumContext.getContext(state);
|
||||||
|
|
||||||
|
context.setCategorySelection
|
||||||
|
((BigDecimal) event.getPageState().getValue(m_categorySelection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Factory class that enables projects to provide their own page creators.
|
||||||
|
* A reason for doing this is that a particular forum project may wish to
|
||||||
|
* include components on the page that introduce dependencies on other projects
|
||||||
|
*/
|
||||||
|
public class ForumPageFactory {
|
||||||
|
|
||||||
|
public static final String THREAD_PAGE = "thread";
|
||||||
|
public static final String FORUM_PAGE = "forum";
|
||||||
|
|
||||||
|
private static Map pageBuilders = new HashMap();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// default pageBuilders are those provided with this project
|
||||||
|
pageBuilders.put(THREAD_PAGE, new ThreadPageBuilder());
|
||||||
|
pageBuilders.put(FORUM_PAGE, new ForumPageBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Page getPage(String pageType) {
|
||||||
|
Assert.truth(pageBuilders.containsKey(pageType), "Requested page type (" + pageType + ") does not have a builder registered" );
|
||||||
|
PageBuilder builder = (PageBuilder)pageBuilders.get(pageType);
|
||||||
|
Page page = builder.buildPage();
|
||||||
|
page.lock();
|
||||||
|
return page;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterator getPages () {
|
||||||
|
return pageBuilders.keySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void registerPageBuilder (String pageType, PageBuilder builder) {
|
||||||
|
pageBuilders.put(pageType, builder);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,36 +18,67 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.arsdigita.forum.ui.Constants;
|
import com.arsdigita.forum.ui.Constants;
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.page.BebopApplicationServlet;
|
import com.arsdigita.bebop.page.BebopApplicationServlet;
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Justin Ross <<a href="mailto:jross@redhat.com">jross@redhat.com</a>>
|
* @author Justin Ross <<a href="mailto:jross@redhat.com">jross@redhat.com</a>>
|
||||||
* @version $Id: ForumServlet.java 287 2005-02-22 00:29:02Z sskracic $
|
* @version $Id: ForumServlet.java 1628 2007-09-17 08:10:40Z chrisg23 $
|
||||||
|
*
|
||||||
|
* Updated chris.gilbert@westsussex.gov.uk to make use of PageFactory and to enable
|
||||||
|
* disablement of client/middleware caching
|
||||||
*/
|
*/
|
||||||
public class ForumServlet extends BebopApplicationServlet
|
public class ForumServlet extends BebopApplicationServlet
|
||||||
implements Constants {
|
implements Constants {
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: ForumServlet.java 287 2005-02-22 00:29:02Z sskracic $" +
|
"$Id: ForumServlet.java 1628 2007-09-17 08:10:40Z chrisg23 $" +
|
||||||
"$Author: sskracic $" +
|
"$Author: chrisg23 $" +
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
"$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(ForumServlet.class);
|
private static final Logger s_log = Logger.getLogger(ForumServlet.class);
|
||||||
|
|
||||||
public void init() throws ServletException {
|
public void init() throws ServletException {
|
||||||
super.init();
|
super.init();
|
||||||
|
s_log.debug("creating forum page");
|
||||||
final Page forum = BboardDispatcher.buildForumPage
|
final Page forum = ForumPageFactory.getPage(ForumPageFactory.FORUM_PAGE);
|
||||||
(new BigDecimalParameter(TOPIC_PARAM));
|
s_log.debug("creating thread page");
|
||||||
final Page thread = BboardDispatcher.buildThreadPage
|
final Page thread = ForumPageFactory.getPage(ForumPageFactory.THREAD_PAGE);
|
||||||
(new BigDecimalParameter(THREAD_PARAM));
|
|
||||||
|
|
||||||
put("/", forum);
|
put("/", forum);
|
||||||
put("/index.jsp", forum);
|
put("/index.jsp", forum);
|
||||||
put("/thread.jsp", thread);
|
put("/thread.jsp", thread);
|
||||||
|
if (Forum.getConfig().disableClientPageCaching()) {
|
||||||
|
s_log.debug("caching disabled");
|
||||||
|
disableClientCaching("/");
|
||||||
|
disableClientCaching("/index.jsp");
|
||||||
|
disableClientCaching("/thread.jsp");
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow other pages to be added
|
||||||
|
// eg - allows categorised forum to add load-category page
|
||||||
|
// for AJAX category asignment
|
||||||
|
Iterator it = ForumPageFactory.getPages();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Object key = (Object)it.next();
|
||||||
|
if (!key.equals(ForumPageFactory.FORUM_PAGE) && !key.equals(ForumPageFactory.THREAD_PAGE)) {
|
||||||
|
put("/" + key, ForumPageFactory.getPage((String)key));
|
||||||
|
if (Forum.getConfig().disableClientPageCaching()) {
|
||||||
|
disableClientCaching("/" + key);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
import com.arsdigita.kernel.permissions.PermissionService;
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.mail.Mail;
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.persistence.DataCollection;
|
import com.arsdigita.persistence.DataCollection;
|
||||||
import com.arsdigita.persistence.DataObject;
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
|
@ -40,7 +41,7 @@ import org.apache.log4j.Logger;
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision: #8 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision: 1.3 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ForumSubscription extends Subscription {
|
public class ForumSubscription extends Subscription {
|
||||||
|
|
@ -89,6 +90,10 @@ public class ForumSubscription extends Subscription {
|
||||||
return BASE_DATA_OBJECT_TYPE;
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSubscriptionGroupName() {
|
||||||
|
return "Instant Alert Subscription Group";
|
||||||
|
}
|
||||||
|
|
||||||
public Forum getForum() {
|
public Forum getForum() {
|
||||||
if (m_forum == null) {
|
if (m_forum == null) {
|
||||||
DataObject forumData = (DataObject) get(FORUM);
|
DataObject forumData = (DataObject) get(FORUM);
|
||||||
|
|
@ -106,6 +111,17 @@ public class ForumSubscription extends Subscription {
|
||||||
private void setForum(Forum forum) {
|
private void setForum(Forum forum) {
|
||||||
m_forum = forum;
|
m_forum = forum;
|
||||||
setAssociation(FORUM, m_forum);
|
setAssociation(FORUM, m_forum);
|
||||||
|
if (getGroup() != null) {
|
||||||
|
// in the case of moderation alert this is null - good, because
|
||||||
|
// mod group has already been placed in the group hierarchy
|
||||||
|
|
||||||
|
getGroup().setName(getGroupName(forum));
|
||||||
|
forum.getGroup().addSubgroup(getGroup());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName(Forum forum) {
|
||||||
|
return forum.getTitle() + " " + getSubscriptionGroupName();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void afterSave() {
|
protected void afterSave() {
|
||||||
|
|
@ -120,15 +136,18 @@ public class ForumSubscription extends Subscription {
|
||||||
public String getSignature(ThreadedMessage post) {
|
public String getSignature(ThreadedMessage post) {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
// XXX
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
/*
|
|
||||||
sb.append(SEPARATOR);
|
sb.append(HTML_SEPARATOR);
|
||||||
|
sb.append(getReturnURLMessage((Post)post));
|
||||||
|
sb.append(HTML_SEPARATOR);
|
||||||
sb.append(ALERT_BLURB);
|
sb.append(ALERT_BLURB);
|
||||||
sb.append("You are receiving this email because you subscribed to ");
|
sb.append("You are receiving this email because you subscribed to ");
|
||||||
sb.append("alerts on this forum.\n\n");
|
sb.append("alerts on this forum. To unsubscribe, follow the link above, return to the thread list and change the settings under the alerts tab.\n");
|
||||||
sb.append(REPLY_BLURB);
|
sb.append("</font>");
|
||||||
*/
|
} else {
|
||||||
sb.append(getReturnURLMessage((Post)post));
|
sb.append(getReturnURLMessage((Post)post));
|
||||||
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,55 +18,47 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
import com.arsdigita.db.DbHelper;
|
import org.apache.log4j.Logger;
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.RequestLocal;
|
||||||
|
import com.arsdigita.db.DbHelper;
|
||||||
|
import com.arsdigita.domain.DomainObject;
|
||||||
import com.arsdigita.domain.xml.TraversalHandler;
|
import com.arsdigita.domain.xml.TraversalHandler;
|
||||||
|
import com.arsdigita.forum.portlet.MyForumsPortlet;
|
||||||
import com.arsdigita.persistence.pdl.ManifestSource;
|
import com.arsdigita.forum.portlet.RecentPostingsPortlet;
|
||||||
import com.arsdigita.persistence.pdl.NameFilter;
|
import com.arsdigita.forum.search.FileAttachmentMetadataProvider;
|
||||||
|
import com.arsdigita.forum.search.PostMetadataProvider;
|
||||||
import com.arsdigita.runtime.CompoundInitializer;
|
import com.arsdigita.forum.ui.portlet.RecentPostingsPortletEditor;
|
||||||
import com.arsdigita.runtime.RuntimeConfig;
|
|
||||||
import com.arsdigita.runtime.PDLInitializer;
|
|
||||||
import com.arsdigita.runtime.DomainInitEvent;
|
|
||||||
|
|
||||||
import com.arsdigita.xml.XML;
|
|
||||||
|
|
||||||
import com.arsdigita.kernel.URLFinder;
|
|
||||||
import com.arsdigita.kernel.URLService;
|
|
||||||
import com.arsdigita.kernel.NoValidURLException;
|
|
||||||
import com.arsdigita.kernel.ACSObjectInstantiator;
|
import com.arsdigita.kernel.ACSObjectInstantiator;
|
||||||
import com.arsdigita.kernel.ResourceTypeConfig;
|
|
||||||
import com.arsdigita.kernel.ResourceType;
|
import com.arsdigita.kernel.ResourceType;
|
||||||
|
import com.arsdigita.kernel.ResourceTypeConfig;
|
||||||
|
import com.arsdigita.kernel.URLService;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
import com.arsdigita.kernel.ui.ResourceConfigFormSection;
|
import com.arsdigita.kernel.ui.ResourceConfigFormSection;
|
||||||
|
|
||||||
import com.arsdigita.domain.DomainObject;
|
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
|
||||||
|
|
||||||
import com.arsdigita.persistence.DataObject;
|
|
||||||
import com.arsdigita.persistence.OID;
|
|
||||||
import com.arsdigita.persistence.SessionManager;
|
|
||||||
import com.arsdigita.web.Application;
|
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.forum.portlet.RecentPostingsPortlet;
|
import com.arsdigita.persistence.pdl.ManifestSource;
|
||||||
import com.arsdigita.forum.ui.portlet.RecentPostingsPortletEditor;
|
import com.arsdigita.persistence.pdl.NameFilter;
|
||||||
|
import com.arsdigita.runtime.CompoundInitializer;
|
||||||
|
import com.arsdigita.runtime.DomainInitEvent;
|
||||||
|
import com.arsdigita.runtime.LegacyInitEvent;
|
||||||
|
import com.arsdigita.runtime.PDLInitializer;
|
||||||
|
import com.arsdigita.runtime.RuntimeConfig;
|
||||||
|
import com.arsdigita.search.MetadataProviderRegistry;
|
||||||
import com.arsdigita.web.ui.ApplicationConfigFormSection;
|
import com.arsdigita.web.ui.ApplicationConfigFormSection;
|
||||||
|
import com.arsdigita.xml.XML;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The forum initializer.
|
* The forum initializer.
|
||||||
*
|
*
|
||||||
* @author Justin Ross <jross@redhat.com>
|
* @author Justin Ross <jross@redhat.com>
|
||||||
* @version $Id: Initializer.java 755 2005-09-02 13:42:47Z sskracic $
|
* @version $Id: Initializer.java 1628 2007-09-17 08:10:40Z chrisg23 $
|
||||||
*/
|
*/
|
||||||
public class Initializer extends CompoundInitializer {
|
public class Initializer extends CompoundInitializer {
|
||||||
public final static String versionId =
|
public final static String versionId =
|
||||||
"$Id: Initializer.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: Initializer.java 1628 2007-09-17 08:10:40Z chrisg23 $"
|
||||||
"$Author: sskracic $" +
|
+ "$Author: chrisg23 $"
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
+ "$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(Initializer.class);
|
private static final Logger s_log = Logger.getLogger(Initializer.class);
|
||||||
|
|
||||||
|
|
@ -91,6 +83,29 @@ public class Initializer extends CompoundInitializer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
e.getFactory().registerInstantiator(
|
e.getFactory().registerInstantiator(
|
||||||
|
Post.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new ACSObjectInstantiator() {
|
||||||
|
public DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
return new Post(dataObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
e.getFactory().registerInstantiator(
|
||||||
|
PostFileAttachment.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new ACSObjectInstantiator() {
|
||||||
|
protected DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
return new PostFileAttachment(dataObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
e.getFactory().registerInstantiator(
|
||||||
|
PostImageAttachment.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new ACSObjectInstantiator() {
|
||||||
|
protected DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
return new PostImageAttachment(dataObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
e.getFactory().registerInstantiator(
|
||||||
"com.arsdigita.forum.Inbox",
|
"com.arsdigita.forum.Inbox",
|
||||||
new ACSObjectInstantiator() {
|
new ACSObjectInstantiator() {
|
||||||
public DomainObject doNewInstance(DataObject dataObject) {
|
public DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
|
@ -107,6 +122,14 @@ public class Initializer extends CompoundInitializer {
|
||||||
});
|
});
|
||||||
|
|
||||||
e.getFactory().registerInstantiator(
|
e.getFactory().registerInstantiator(
|
||||||
|
MyForumsPortlet.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new ACSObjectInstantiator() {
|
||||||
|
protected DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
return new MyForumsPortlet(dataObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
e.getFactory().registerInstantiator(
|
||||||
ForumSubscription.BASE_DATA_OBJECT_TYPE,
|
ForumSubscription.BASE_DATA_OBJECT_TYPE,
|
||||||
new ACSObjectInstantiator() {
|
new ACSObjectInstantiator() {
|
||||||
public DomainObject doNewInstance(DataObject dataObject) {
|
public DomainObject doNewInstance(DataObject dataObject) {
|
||||||
|
|
@ -128,42 +151,12 @@ public class Initializer extends CompoundInitializer {
|
||||||
XML.parse(Forum.getConfig().getTraversalAdapters(),
|
XML.parse(Forum.getConfig().getTraversalAdapters(),
|
||||||
new TraversalHandler());
|
new TraversalHandler());
|
||||||
|
|
||||||
URLFinder messageFinder = new URLFinder() {
|
|
||||||
public String find(OID oid, String context)
|
|
||||||
throws NoValidURLException {
|
|
||||||
|
|
||||||
return find(oid);
|
|
||||||
}
|
|
||||||
public String find(OID oid) throws NoValidURLException {
|
|
||||||
DataObject dobj = SessionManager.getSession().retrieve(oid);
|
|
||||||
|
|
||||||
if (dobj == null) {
|
|
||||||
throw new NoValidURLException("No such data object " + oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Application app = Application.retrieveApplication(dobj);
|
|
||||||
|
|
||||||
if (app == null) {
|
|
||||||
throw new NoValidURLException
|
|
||||||
("Could not find application instance for " + dobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
ThreadedMessage message = new ThreadedMessage(oid);
|
|
||||||
|
|
||||||
String url = app.getPath() +
|
|
||||||
"/thread.jsp?threadID=" +
|
|
||||||
message.getThread().getID().toString();
|
|
||||||
|
|
||||||
return url;
|
|
||||||
} catch(DataObjectNotFoundException e) {
|
|
||||||
throw new NoValidURLException
|
|
||||||
("Could not find application instance for " + dobj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
URLService.registerFinder(
|
URLService.registerFinder(
|
||||||
ThreadedMessage.BASE_DATA_OBJECT_TYPE, messageFinder);
|
ThreadedMessage.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new PostFinder());
|
||||||
|
URLService.registerFinder(PostFileAttachment.BASE_DATA_OBJECT_TYPE, new PostFileAttachmentURLFinder());
|
||||||
|
|
||||||
new ResourceTypeConfig(RecentPostingsPortlet.BASE_DATA_OBJECT_TYPE) {
|
new ResourceTypeConfig(RecentPostingsPortlet.BASE_DATA_OBJECT_TYPE) {
|
||||||
public ResourceConfigFormSection getCreateFormSection
|
public ResourceConfigFormSection getCreateFormSection
|
||||||
|
|
@ -183,15 +176,20 @@ public class Initializer extends CompoundInitializer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new ResourceTypeConfig(Forum.BASE_DATA_OBJECT_TYPE) {
|
// chris.gilbert@westsussex.gov.uk use new constructor that allows create form to be hidden from users other than those
|
||||||
|
// with admin rights on parent app. Particularly appropriate for portlet where users
|
||||||
|
// customising their own homepage should NOT be allowed to create new forums
|
||||||
|
new ResourceTypeConfig(Forum.BASE_DATA_OBJECT_TYPE, PrivilegeDescriptor.ADMIN, PrivilegeDescriptor.READ) {
|
||||||
public ResourceConfigFormSection getCreateFormSection
|
public ResourceConfigFormSection getCreateFormSection
|
||||||
(final ResourceType resType, final RequestLocal parentAppRL) {
|
(final ResourceType resType,
|
||||||
|
final RequestLocal parentAppRL) {
|
||||||
final ResourceConfigFormSection config =
|
final ResourceConfigFormSection config =
|
||||||
new ApplicationConfigFormSection(resType, parentAppRL);
|
new ApplicationConfigFormSection(resType, parentAppRL, true);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ResourceConfigFormSection getModifyFormSection
|
public ResourceConfigFormSection getModifyFormSection
|
||||||
(final RequestLocal application) {
|
(final RequestLocal application) {
|
||||||
final ResourceConfigFormSection config =
|
final ResourceConfigFormSection config =
|
||||||
|
|
@ -201,5 +199,20 @@ public class Initializer extends CompoundInitializer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MetadataProviderRegistry.registerAdapter(Post.BASE_DATA_OBJECT_TYPE, new PostMetadataProvider());
|
||||||
|
MetadataProviderRegistry.registerAdapter(PostFileAttachment.BASE_DATA_OBJECT_TYPE, new FileAttachmentMetadataProvider());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(LegacyInitEvent e) {
|
||||||
|
super.init(e);
|
||||||
|
|
||||||
|
if (RuntimeConfig.getConfig().runBackGroundTasks()) {
|
||||||
|
RemoveUnattachedAssetsScheduler.startTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,10 @@ import com.arsdigita.loader.PackageLoader;
|
||||||
|
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.KernelExcursion;
|
import com.arsdigita.kernel.KernelExcursion;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.kernel.User;
|
import com.arsdigita.kernel.User;
|
||||||
import com.arsdigita.kernel.EmailAddress;
|
import com.arsdigita.kernel.EmailAddress;
|
||||||
|
import com.arsdigita.kernel.UserCollection;
|
||||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
|
||||||
|
|
@ -33,6 +35,7 @@ import com.arsdigita.web.ApplicationType;
|
||||||
|
|
||||||
import com.arsdigita.portal.apportlet.AppPortletType;
|
import com.arsdigita.portal.apportlet.AppPortletType;
|
||||||
import com.arsdigita.portal.PortletType;
|
import com.arsdigita.portal.PortletType;
|
||||||
|
import com.arsdigita.forum.portlet.MyForumsPortlet;
|
||||||
import com.arsdigita.forum.portlet.RecentPostingsPortlet;
|
import com.arsdigita.forum.portlet.RecentPostingsPortlet;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -42,12 +45,12 @@ import org.apache.log4j.Logger;
|
||||||
* Loader.
|
* Loader.
|
||||||
*
|
*
|
||||||
* @author Justin Ross <jross@redhat.com>
|
* @author Justin Ross <jross@redhat.com>
|
||||||
* @version $Id: Loader.java 755 2005-09-02 13:42:47Z sskracic $
|
* @version $Id: Loader.java 1628 2007-09-17 08:10:40Z chrisg23 $
|
||||||
*/
|
*/
|
||||||
public class Loader extends PackageLoader {
|
public class Loader extends PackageLoader {
|
||||||
public final static String versionId =
|
public final static String versionId =
|
||||||
"$Id: Loader.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: Loader.java 1628 2007-09-17 08:10:40Z chrisg23 $" +
|
||||||
"$Author: sskracic $" +
|
"$Author: chrisg23 $" +
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
"$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(Loader.class);
|
private static final Logger s_log = Logger.getLogger(Loader.class);
|
||||||
|
|
@ -60,6 +63,7 @@ public class Loader extends PackageLoader {
|
||||||
setupForumAppType();
|
setupForumAppType();
|
||||||
//setupInboxAppType();
|
//setupInboxAppType();
|
||||||
setupRecentPostingsPortletType();
|
setupRecentPostingsPortletType();
|
||||||
|
setupMyForumsPortletType();
|
||||||
setupDigestUser();
|
setupDigestUser();
|
||||||
SessionManager.getSession().flushAll();
|
SessionManager.getSession().flushAll();
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +101,17 @@ public class Loader extends PackageLoader {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PortletType setupMyForumsPortletType() {
|
||||||
|
|
||||||
|
PortletType type = PortletType
|
||||||
|
.createPortletType("My Forums",
|
||||||
|
PortletType.WIDE_PROFILE,
|
||||||
|
MyForumsPortlet.BASE_DATA_OBJECT_TYPE);
|
||||||
|
type.setDescription("Lists forums that user has access to, with last posting date");
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
private static void setupDigestUser() {
|
private static void setupDigestUser() {
|
||||||
s_log.debug("Setting up the digest user");
|
s_log.debug("Setting up the digest user");
|
||||||
|
|
||||||
|
|
@ -104,20 +119,36 @@ public class Loader extends PackageLoader {
|
||||||
// specified in the configuration file.
|
// specified in the configuration file.
|
||||||
|
|
||||||
String email = Forum.getConfig().getDigestUserEmail();
|
String email = Forum.getConfig().getDigestUserEmail();
|
||||||
|
UserCollection users = User.retrieveAll();
|
||||||
|
users.addEqualsFilter("primaryEmail", email);
|
||||||
|
if (users.next()) {
|
||||||
|
s_log.debug("user exists");
|
||||||
|
} else {
|
||||||
|
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Creating a user with the email " + email);
|
s_log.debug("Creating a user with the email " + email);
|
||||||
}
|
|
||||||
|
|
||||||
User user = new User();
|
User user = new User();
|
||||||
user.setPrimaryEmail(new EmailAddress(email));
|
user.setPrimaryEmail(new EmailAddress(email));
|
||||||
user.getPersonName().setGivenName("Forum");
|
user.getPersonName().setGivenName("Forum");
|
||||||
user.getPersonName().setFamilyName("Digest Sender");
|
user.getPersonName().setFamilyName("Digest Sender");
|
||||||
|
users.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setupPrivileges() {
|
public static void setupPrivileges() {
|
||||||
PrivilegeDescriptor.createPrivilege(
|
PrivilegeDescriptor.createPrivilege(
|
||||||
Forum.FORUM_MODERATION_PRIVILEGE);
|
Forum.FORUM_MODERATION_PRIVILEGE);
|
||||||
|
PrivilegeDescriptor.createPrivilege(
|
||||||
|
Forum.CREATE_THREAD_PRIVILEGE);
|
||||||
|
PrivilegeDescriptor.createPrivilege(
|
||||||
|
Forum.RESPOND_TO_THREAD_PRIVILEGE);
|
||||||
|
PrivilegeDescriptor.addChildPrivilege(Forum.FORUM_MODERATION_PRIVILEGE, Forum.CREATE_THREAD_PRIVILEGE);
|
||||||
|
PrivilegeDescriptor.addChildPrivilege(Forum.CREATE_THREAD_PRIVILEGE, Forum.RESPOND_TO_THREAD_PRIVILEGE);
|
||||||
|
PrivilegeDescriptor.addChildPrivilege(Forum.RESPOND_TO_THREAD_PRIVILEGE, PrivilegeDescriptor.READ.getName());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Interface for classes that create forum pages. To build a page different
|
||||||
|
* from the default, provide new implemention and register it with the
|
||||||
|
* com.arsdigita.forum.ForumPageFactory
|
||||||
|
*/
|
||||||
|
public interface PageBuilder {
|
||||||
|
|
||||||
|
public Page buildPage();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.categorization.CategorizedObject;
|
import com.arsdigita.categorization.CategorizedObject;
|
||||||
import com.arsdigita.categorization.Category;
|
import com.arsdigita.categorization.Category;
|
||||||
import com.arsdigita.categorization.CategoryCollection;
|
import com.arsdigita.categorization.CategoryCollection;
|
||||||
|
|
@ -26,6 +31,8 @@ import com.arsdigita.cms.lifecycle.LifecycleDefinition;
|
||||||
import com.arsdigita.cms.lifecycle.LifecycleService;
|
import com.arsdigita.cms.lifecycle.LifecycleService;
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.ui.PostForm;
|
||||||
|
import com.arsdigita.kernel.ACSObject;
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.KernelExcursion;
|
import com.arsdigita.kernel.KernelExcursion;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
|
|
@ -33,18 +40,14 @@ import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
import com.arsdigita.messaging.MessageThread;
|
import com.arsdigita.messaging.MessageThread;
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.notification.Notification;
|
import com.arsdigita.notification.Notification;
|
||||||
|
import com.arsdigita.persistence.DataAssociation;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
import com.arsdigita.persistence.DataCollection;
|
import com.arsdigita.persistence.DataCollection;
|
||||||
import com.arsdigita.persistence.DataObject;
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.persistence.DataOperation;
|
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.PersistenceException;
|
import com.arsdigita.persistence.PersistenceException;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.persistence.SessionManager;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Post represents a single posting to a discussion forum.
|
* A Post represents a single posting to a discussion forum.
|
||||||
|
|
@ -105,7 +108,8 @@ import org.apache.log4j.Logger;
|
||||||
*
|
*
|
||||||
*</ul>
|
*</ul>
|
||||||
*</p>
|
*</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
* @author Nobuko Asakai (nasakai@redhat.com)
|
* @author Nobuko Asakai (nasakai@redhat.com)
|
||||||
*/
|
*/
|
||||||
|
|
@ -121,6 +125,16 @@ public class Post extends ThreadedMessage {
|
||||||
* message */
|
* message */
|
||||||
public static final String MODERATOR = "moderator";
|
public static final String MODERATOR = "moderator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0..n association with PostImageAttachments
|
||||||
|
*/
|
||||||
|
public static final String IMAGE_ATTACHMENTS = "images";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0..n association with PostFileAttachments
|
||||||
|
*/
|
||||||
|
public static final String FILE_ATTACHMENTS = "files";
|
||||||
|
|
||||||
/** The status strings */
|
/** The status strings */
|
||||||
public static final String PENDING = "pending";
|
public static final String PENDING = "pending";
|
||||||
public static final String APPROVED = "approved";
|
public static final String APPROVED = "approved";
|
||||||
|
|
@ -134,6 +148,8 @@ public class Post extends ThreadedMessage {
|
||||||
|
|
||||||
private Party m_moderator;
|
private Party m_moderator;
|
||||||
|
|
||||||
|
// referred to afterSave method
|
||||||
|
private boolean m_wasNew;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The base DomainObject is Post which extends ThreadedMessage. In
|
* The base DomainObject is Post which extends ThreadedMessage. In
|
||||||
|
|
@ -147,7 +163,7 @@ public class Post extends ThreadedMessage {
|
||||||
this(BASE_DATA_OBJECT_TYPE);
|
this(BASE_DATA_OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Post(String typeName) {
|
public Post(String typeName) {
|
||||||
super(typeName);
|
super(typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,52 +171,35 @@ public class Post extends ThreadedMessage {
|
||||||
super(oid);
|
super(oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Post(BigDecimal id) {
|
||||||
|
this(new OID(BASE_DATA_OBJECT_TYPE, id));
|
||||||
|
}
|
||||||
|
|
||||||
public Post(DataObject obj) {
|
public Post(DataObject obj) {
|
||||||
super(obj);
|
super(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Posting in a form. If the forum
|
* Creates a new Posting in a forum. The post is
|
||||||
* is moderated, then the post's status will be
|
* not yet in a fit state to be saved as it needs
|
||||||
* set to PENDING, otherwise it will be set to
|
* it's status to be set, and the subject and message
|
||||||
* APPROVED
|
*
|
||||||
* @param forum the owner forum
|
* @param forum the owner forum
|
||||||
*/
|
*/
|
||||||
public static Post create(Forum forum) {
|
public static Post create(Forum forum) {
|
||||||
return create(forum,
|
|
||||||
forum.isModerated() ? PENDING : APPROVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Posting in a form. The approval
|
|
||||||
* status will be set as specified.
|
|
||||||
* @param forum the owner forum
|
|
||||||
* @param status the approval status
|
|
||||||
*/
|
|
||||||
public static Post create(Forum forum,
|
|
||||||
String status) {
|
|
||||||
Post post = new Post();
|
Post post = new Post();
|
||||||
post.setup(forum, status);
|
post.setForum(forum);
|
||||||
return post;
|
return post;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setup(Forum forum,
|
|
||||||
String status) {
|
|
||||||
setForum(forum);
|
|
||||||
setStatus(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getBaseDataObjectType() {
|
protected String getBaseDataObjectType() {
|
||||||
return BASE_DATA_OBJECT_TYPE;
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use replyTo() instead
|
* overridden version of method in ThreadedMessage
|
||||||
|
* used to create a reply to an existing post
|
||||||
*/
|
*/
|
||||||
public Post replyToPost() {
|
|
||||||
return (Post)replyTo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ThreadedMessage newInstance() {
|
public ThreadedMessage newInstance() {
|
||||||
return create(getForum());
|
return create(getForum());
|
||||||
}
|
}
|
||||||
|
|
@ -210,6 +209,7 @@ public class Post extends ThreadedMessage {
|
||||||
* before saving.
|
* before saving.
|
||||||
*/
|
*/
|
||||||
protected void beforeSave() {
|
protected void beforeSave() {
|
||||||
|
m_wasNew = isNew();
|
||||||
Forum forum = getForum();
|
Forum forum = getForum();
|
||||||
Assert.exists(forum, Forum.class);
|
Assert.exists(forum, Forum.class);
|
||||||
|
|
||||||
|
|
@ -222,14 +222,14 @@ public class Post extends ThreadedMessage {
|
||||||
|
|
||||||
super.beforeSave();
|
super.beforeSave();
|
||||||
|
|
||||||
if (isNew()) {
|
|
||||||
if (forum.isNoticeboard() && forum.getExpireAfter() > 0) {
|
|
||||||
s_log.info("Creating expiration lifecycle for " + getOID());
|
|
||||||
setLifecycle(forum.getLifecycleDefinition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set permission contexts for this post to the root post, and for the root
|
||||||
|
* post to the forum. Additionally create a lifecycle if required for a new
|
||||||
|
* root post
|
||||||
|
*/
|
||||||
|
|
||||||
protected void afterSave() {
|
protected void afterSave() {
|
||||||
super.afterSave();
|
super.afterSave();
|
||||||
Forum forum = getForum();
|
Forum forum = getForum();
|
||||||
|
|
@ -238,22 +238,51 @@ public class Post extends ThreadedMessage {
|
||||||
|
|
||||||
s_log.info("Setting context for " + getOID() + " to " + root.getOID());
|
s_log.info("Setting context for " + getOID() + " to " + root.getOID());
|
||||||
PermissionService.setContext(this, root);
|
PermissionService.setContext(this, root);
|
||||||
s_log.info("Setting context for " + root.getOID() + " to " +
|
s_log.info(
|
||||||
|
"Setting context for " + root.getOID() + " to " +
|
||||||
forum.getOID());
|
forum.getOID());
|
||||||
PermissionService.setContext(root, forum);
|
PermissionService.setContext(root, forum);
|
||||||
|
// originally this was created in beforeSave, but this was when only noticeboard
|
||||||
|
// (reply disabled) forums could have a lifecycle. Now that all forums may
|
||||||
|
// have a lifecycle on root posts, the method needs to be here in order
|
||||||
|
// for persistence to work when users are replying to posts chris.gilbert@westsussex.gov.uk
|
||||||
|
|
||||||
|
if (m_wasNew) {
|
||||||
|
if (getRoot() == null && forum.getExpireAfter() > 0) {
|
||||||
|
s_log.info("Creating expiration lifecycle for " + getOID());
|
||||||
|
setLifecycle(forum.getLifecycleDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_wasNew = false;
|
||||||
|
|
||||||
|
DataAssociationCursor files = getFiles();
|
||||||
|
|
||||||
|
// allow attached files to be returned in search results
|
||||||
|
// by setting their status as live
|
||||||
|
while (files.next()) {
|
||||||
|
PostFileAttachment file =
|
||||||
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
if (getStatus().equals(APPROVED)) {
|
||||||
|
file.setLive();
|
||||||
|
} else {
|
||||||
|
file.setDraft();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends out the notifications for any subscriptions to the forum
|
* Sends out the notifications for any subscriptions to the forum
|
||||||
* or thread to which this message belongs. Only sends
|
* or thread to which this message belongs. Only sends
|
||||||
* notificatios if the post is approved.
|
* notifications if the post is approved.
|
||||||
*/
|
*/
|
||||||
public void sendNotifications() {
|
public void sendNotifications(final String context) {
|
||||||
KernelExcursion ex = new KernelExcursion() {
|
KernelExcursion ex = new KernelExcursion() {
|
||||||
protected void excurse() {
|
protected void excurse() {
|
||||||
setEffectiveParty(Kernel.getSystemParty());
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
doSendNotifications();
|
doSendNotifications(context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ex.run();
|
ex.run();
|
||||||
|
|
@ -264,6 +293,9 @@ public class Post extends ThreadedMessage {
|
||||||
* on for the forum.
|
* on for the forum.
|
||||||
*/
|
*/
|
||||||
public void sendModeratorAlerts() {
|
public void sendModeratorAlerts() {
|
||||||
|
|
||||||
|
if (!getStatus().equals(APPROVED)) {
|
||||||
|
// don't send if pre-approved (ie posted by a moderator)
|
||||||
KernelExcursion ex = new KernelExcursion() {
|
KernelExcursion ex = new KernelExcursion() {
|
||||||
protected void excurse() {
|
protected void excurse() {
|
||||||
setEffectiveParty(Kernel.getSystemParty());
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
|
|
@ -271,17 +303,17 @@ public class Post extends ThreadedMessage {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ex.run();
|
ex.run();
|
||||||
|
} else {
|
||||||
|
s_log.debug("not sending moderator alerts because the post " +
|
||||||
|
"was pre-approved (created by an approver)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSendNotifications() {
|
private void doSendNotifications(String context) {
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("sending user notifications");
|
s_log.debug("sending user notifications");
|
||||||
}
|
|
||||||
Forum forum = getForum();
|
Forum forum = getForum();
|
||||||
if (getStatus().equals(APPROVED)) {
|
if (getStatus().equals(APPROVED)) {
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Sending forum level subsriptions");
|
s_log.debug("Sending forum level subsriptions");
|
||||||
}
|
|
||||||
DataCollection subscriptions = forum.getSubscriptions();
|
DataCollection subscriptions = forum.getSubscriptions();
|
||||||
|
|
||||||
while (subscriptions.next()) {
|
while (subscriptions.next()) {
|
||||||
|
|
@ -290,28 +322,30 @@ public class Post extends ThreadedMessage {
|
||||||
subscriptions.getDataObject());
|
subscriptions.getDataObject());
|
||||||
s_log.debug("notification to " + subscription.getOID());
|
s_log.debug("notification to " + subscription.getOID());
|
||||||
|
|
||||||
subscription.sendNotification(Post.this);
|
subscription.sendNotification(Post.this, Forum.getConfig().deleteNotifications());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Sending thread level subsriptions");
|
s_log.debug("Sending thread level subsriptions");
|
||||||
}
|
if (context == null || !context.equals(PostForm.NEW_CONTEXT)) {
|
||||||
|
|
||||||
ThreadSubscription sub =
|
ThreadSubscription sub =
|
||||||
ThreadSubscription.getThreadSubscription(getThread());
|
ThreadSubscription.getThreadSubscription(getThread());
|
||||||
|
if (sub == null) {
|
||||||
if (sub != null ) {
|
s_log.error(
|
||||||
sub.sendNotification(this);
|
"Got a null ThreadSubscription from "
|
||||||
|
+ "Post # "
|
||||||
|
+ getID());
|
||||||
} else {
|
} else {
|
||||||
s_log.error("Got a null ThreadSubscription from " +
|
sub.sendNotification(this, Forum.getConfig().deleteNotifications());
|
||||||
"Post # " + getID());
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Not sending notifications because the " +
|
s_log.debug("Not sending notifications because the " +
|
||||||
"message is not approved");
|
"message is not approved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void doSendModeratorAlerts() {
|
private void doSendModeratorAlerts() {
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
|
|
@ -327,19 +361,16 @@ public class Post extends ThreadedMessage {
|
||||||
while (alerts.next()) {
|
while (alerts.next()) {
|
||||||
ModerationAlert alert
|
ModerationAlert alert
|
||||||
= (ModerationAlert)
|
= (ModerationAlert)
|
||||||
DomainObjectFactory.newInstance(alerts.getDataObject());
|
DomainObjectFactory.newInstance(
|
||||||
if (s_log.isDebugEnabled()) {
|
alerts.getDataObject());
|
||||||
s_log.debug("Processing moderation alert " + alert.getOID());
|
s_log.debug("Processing moderation alert " + alert.getOID());
|
||||||
}
|
alert.sendNotification(this, Forum.getConfig().deleteNotifications());
|
||||||
alert.sendNotification(this);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Not sending moderator alerts because the " +
|
s_log.debug("Not sending moderator alerts because the " +
|
||||||
"forum is not moderated");
|
"forum is not moderated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Forum that contains this post. Just a wrapper for the
|
* Set the Forum that contains this post. Just a wrapper for the
|
||||||
|
|
@ -382,11 +413,32 @@ public class Post extends ThreadedMessage {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void clearCategories() {
|
public void clearCategories() {
|
||||||
DataOperation clearCategories = SessionManager.getSession()
|
DataCollection categories =
|
||||||
.retrieveDataOperation("com.arsdigita.forum.clearCategories");
|
SessionManager.getSession().retrieve(
|
||||||
|
Category.BASE_DATA_OBJECT_TYPE);
|
||||||
|
categories.addEqualsFilter(
|
||||||
|
Category.CHILD_OBJECTS + "." + ACSObject.ID,
|
||||||
|
getID());
|
||||||
|
while (categories.next()) {
|
||||||
|
Category cat =
|
||||||
|
(Category) DomainObjectFactory.newInstance(
|
||||||
|
categories.getDataObject());
|
||||||
|
cat.removeChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// above is slower than data operation implementation below,
|
||||||
|
// but data op caused problems in persistence. If edited post
|
||||||
|
// had topic unchanged, then attempt was made to assign topic
|
||||||
|
// category before data op had cleared existing. Hence exception
|
||||||
|
// - attempt to map object to same cat twice
|
||||||
|
|
||||||
|
/*
|
||||||
|
DataOperation clearCategories =
|
||||||
|
SessionManager.getSession().retrieveDataOperation(
|
||||||
|
"com.arsdigita.forum.clearCategories");
|
||||||
clearCategories.setParameter("postID", this.getID());
|
clearCategories.setParameter("postID", this.getID());
|
||||||
clearCategories.execute();
|
clearCategories.execute();
|
||||||
return;
|
return;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -397,15 +449,41 @@ public class Post extends ThreadedMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a ThreadSubscription, but only if this is a root
|
* creates a ThreadSubscription, and returns it but only if this is a root,
|
||||||
|
* else return null
|
||||||
* Note, you must save() the Post before calling this method.
|
* Note, you must save() the Post before calling this method.
|
||||||
*/
|
*/
|
||||||
public void createThreadSubscription() {
|
public ThreadSubscription createThreadSubscription() {
|
||||||
|
ThreadSubscription sub = null;
|
||||||
if (getRoot() == null) {
|
if (getRoot() == null) {
|
||||||
ThreadSubscription sub = new ThreadSubscription();
|
sub = new ThreadSubscription();
|
||||||
sub.setThread(getThread());
|
sub.setThread(getThread());
|
||||||
sub.save();
|
sub.save();
|
||||||
}
|
}
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadSubscription getSubscription() {
|
||||||
|
MessageThread thread;
|
||||||
|
if (getRoot() != null) {
|
||||||
|
thread = getRootMsg().getThread();
|
||||||
|
} else {
|
||||||
|
thread = getThread();
|
||||||
|
}
|
||||||
|
DataCollection subscriptions =
|
||||||
|
SessionManager.getSession().retrieve(
|
||||||
|
ThreadSubscription.BASE_DATA_OBJECT_TYPE);
|
||||||
|
subscriptions.addEqualsFilter(
|
||||||
|
ThreadSubscription.THREAD,
|
||||||
|
thread.getID());
|
||||||
|
ThreadSubscription subscription = null;
|
||||||
|
while (subscriptions.next()) {
|
||||||
|
subscription =
|
||||||
|
(ThreadSubscription) DomainObjectFactory.newInstance(
|
||||||
|
subscriptions.getDataObject());
|
||||||
|
|
||||||
|
}
|
||||||
|
return subscription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -416,7 +494,10 @@ public class Post extends ThreadedMessage {
|
||||||
*/
|
*/
|
||||||
public boolean canEdit(Party party) {
|
public boolean canEdit(Party party) {
|
||||||
Party author = getFrom();
|
Party author = getFrom();
|
||||||
return (Forum.getConfig().canAuthorEditPosts()
|
// cg added - for anonymous posts, don't allow editing, else everyone could edit everyone else's posts
|
||||||
|
return (
|
||||||
|
!author.equals(Kernel.getPublicUser())
|
||||||
|
&& Forum.getConfig().canAuthorEditPosts()
|
||||||
&& author.equals(party))
|
&& author.equals(party))
|
||||||
|| getForum().canEdit(party);
|
|| getForum().canEdit(party);
|
||||||
}
|
}
|
||||||
|
|
@ -439,6 +520,38 @@ public class Post extends ThreadedMessage {
|
||||||
set(STATUS, status);
|
set(STATUS, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the status of a new post according to the priviliges of
|
||||||
|
* the current user - used by UI when creating new post or reply
|
||||||
|
* @param state
|
||||||
|
*/
|
||||||
|
public void setStatus(PageState state) {
|
||||||
|
setStatus(state, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the status of an edited post according to the privileges
|
||||||
|
* of the current user and the status of the post that is being
|
||||||
|
* edited - used by the edit post UI
|
||||||
|
* @param state
|
||||||
|
* @param previousStatus
|
||||||
|
*/
|
||||||
|
public void setStatus(PageState state, String previousStatus) {
|
||||||
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
|
Forum forum = ctx.getForum();
|
||||||
|
// set status of edited post
|
||||||
|
if (forum.isModerated() && !ctx.canModerate()) {
|
||||||
|
if (Post.APPROVED.equals(previousStatus)) {
|
||||||
|
setStatus(Post.REAPPROVE);
|
||||||
|
} else {
|
||||||
|
setStatus(Post.PENDING);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setStatus(Post.APPROVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return (String)get(STATUS);
|
return (String)get(STATUS);
|
||||||
}
|
}
|
||||||
|
|
@ -458,24 +571,19 @@ public class Post extends ThreadedMessage {
|
||||||
return m_moderator;
|
return m_moderator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note that the replies to this post are deleted in beforeDelete() of
|
||||||
|
// ThreadedMessage (and hence beforeDelete is called recursively on their replies)
|
||||||
|
|
||||||
protected void beforeDelete() {
|
protected void beforeDelete() {
|
||||||
// First delete associated entries in nt_requests this entry and
|
s_log.debug("Post - before delete " + getID());
|
||||||
// all of its replies (in case of a root message) have
|
|
||||||
List replies = new ArrayList();
|
// threaded message recursively deletes children
|
||||||
List msgIdList = new ArrayList();
|
super.beforeDelete();
|
||||||
msgIdList.add(getID());
|
// remove any nt_requests
|
||||||
if (getRoot() == null) {
|
DataCollection requests =
|
||||||
DataCollection msgs = SessionManager.getSession()
|
SessionManager.getSession().retrieve(
|
||||||
.retrieve(BASE_DATA_OBJECT_TYPE);
|
Notification.BASE_DATA_OBJECT_TYPE);
|
||||||
msgs.addEqualsFilter("root", getID());
|
requests.addEqualsFilter(Notification.MESSAGE_ID, this.getID());
|
||||||
while (msgs.next()) {
|
|
||||||
replies.add(msgs.getDataObject());
|
|
||||||
msgIdList.add( msgs.getDataObject().getOID().get("id"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataCollection requests = SessionManager.getSession()
|
|
||||||
.retrieve(Notification.BASE_DATA_OBJECT_TYPE);
|
|
||||||
requests.addFilter("messageID in :msgIdList").set("msgIdList", msgIdList);
|
|
||||||
while (requests.next()) {
|
while (requests.next()) {
|
||||||
Notification no = new Notification(requests.getDataObject().getOID());
|
Notification no = new Notification(requests.getDataObject().getOID());
|
||||||
no.setMessageDelete(Boolean.FALSE);
|
no.setMessageDelete(Boolean.FALSE);
|
||||||
|
|
@ -483,21 +591,23 @@ public class Post extends ThreadedMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getRoot() == null) {
|
if (getRoot() == null) {
|
||||||
// This posting is the root of the thread. Make sure all postings
|
s_log.debug(
|
||||||
// in this thread are deleted before this very one. Also
|
"Root post - get rid of thread subscription and thread");
|
||||||
// take care of thread subscription.
|
// This posting is the root of the thread. Remove the thread subscription and thread
|
||||||
ThreadSubscription sub = ThreadSubscription.getThreadSubscription(this.getThread());
|
MessageThread thread = getThread();
|
||||||
|
ThreadSubscription sub =
|
||||||
|
ThreadSubscription.getThreadSubscription(thread);
|
||||||
|
if (sub != null) {
|
||||||
|
// if unconfirmed post, then threadsubscription has not been created
|
||||||
sub.delete();
|
sub.delete();
|
||||||
MessageThread thread = MessageThread.getFromRootMessage(this);
|
|
||||||
thread.delete();
|
|
||||||
for (Iterator it = replies.iterator(); it.hasNext(); ) {
|
|
||||||
Post reply = new Post( (DataObject) it.next());
|
|
||||||
reply.delete();
|
|
||||||
}
|
}
|
||||||
|
if (thread != null) {
|
||||||
|
thread.delete();
|
||||||
}
|
}
|
||||||
super.beforeDelete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// package access only
|
// package access only
|
||||||
void setLifecycle(LifecycleDefinition life) {
|
void setLifecycle(LifecycleDefinition life) {
|
||||||
|
|
@ -507,5 +617,91 @@ public class Post extends ThreadedMessage {
|
||||||
cycle.save();
|
cycle.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addImage(PostImageAttachment image) {
|
||||||
|
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
||||||
|
image.addToAssociation(images);
|
||||||
|
long currentImageCount = images.getDataAssociationCursor().size();
|
||||||
|
image.setImageOrder((int) currentImageCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeImage(PostImageAttachment image) {
|
||||||
|
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
||||||
|
image.removeFromAssociation(images);
|
||||||
|
renumberImages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// image order for a new image is based on the count of existing
|
||||||
|
// images, hence necessary to fill in any gaps when images are deleted
|
||||||
|
private void renumberImages() {
|
||||||
|
int count = 1;
|
||||||
|
DataAssociationCursor images = getImages();
|
||||||
|
while (images.next()) {
|
||||||
|
PostImageAttachment image =
|
||||||
|
(PostImageAttachment) DomainObjectFactory.newInstance(
|
||||||
|
images.getDataObject());
|
||||||
|
image.setImageOrder(count);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataAssociationCursor getImages() {
|
||||||
|
DataAssociationCursor images =
|
||||||
|
((DataAssociation) get(Post.IMAGE_ATTACHMENTS))
|
||||||
|
.getDataAssociationCursor();
|
||||||
|
images.addOrder(PostImageAttachment.IMAGE_ORDER);
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFile(PostFileAttachment file) {
|
||||||
|
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
||||||
|
file.addToAssociation(files);
|
||||||
|
PermissionService.setContext(file, this);
|
||||||
|
long currentFileCount = files.getDataAssociationCursor().size();
|
||||||
|
file.setFileOrder((int) currentFileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFile(PostFileAttachment file) {
|
||||||
|
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
||||||
|
file.removeFromAssociation(files);
|
||||||
|
renumberFiles();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// file order for a new file is based on the count of existing
|
||||||
|
// files, hence necessary to fill in any gaps when images are deleted
|
||||||
|
|
||||||
|
private void renumberFiles() {
|
||||||
|
int count = 1;
|
||||||
|
DataAssociationCursor files = getFiles();
|
||||||
|
while (files.next()) {
|
||||||
|
PostFileAttachment file =
|
||||||
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
file.setFileOrder(count);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataAssociationCursor getFiles() {
|
||||||
|
DataAssociationCursor files =
|
||||||
|
((DataAssociation) get(Post.FILE_ATTACHMENTS))
|
||||||
|
.getDataAssociationCursor();
|
||||||
|
files.addOrder(PostFileAttachment.FILE_ORDER);
|
||||||
|
return files;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by thread to prevent counting unapproved posts in the
|
||||||
|
* reply count.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// should really be static - revisit this - refer to MessageThread for use
|
||||||
|
protected void addReplyFilter(DataCollection replies) {
|
||||||
|
replies.addEqualsFilter(STATUS, APPROVED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.auditing.BasicAuditTrail;
|
||||||
|
import com.arsdigita.cms.FileAsset;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Domain object for a file attached to a post. Modelled as domain object
|
||||||
|
* rather than simple association with link attribute because cloning
|
||||||
|
* seems to struggle with link attributes and also this allows files
|
||||||
|
* to be indexed separately for searching
|
||||||
|
*/
|
||||||
|
public class PostFileAttachment extends FileAsset {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(PostFileAttachment.class);
|
||||||
|
|
||||||
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
|
"com.arsdigita.forum.PostFileAttachment";
|
||||||
|
public static final String FILE_OWNER = "fileMessage";
|
||||||
|
public static final String FILE_ORDER = "fileOrder";
|
||||||
|
|
||||||
|
public PostFileAttachment() {
|
||||||
|
super(BASE_DATA_OBJECT_TYPE);
|
||||||
|
setVersion(DRAFT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostFileAttachment(OID oid) {
|
||||||
|
super(oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostFileAttachment(BigDecimal id) {
|
||||||
|
this(new OID(BASE_DATA_OBJECT_TYPE, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostFileAttachment(DataObject obj) {
|
||||||
|
super(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostFileAttachment(String type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseDataObjectType() {
|
||||||
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileOrder(Integer order) {
|
||||||
|
set(FILE_ORDER, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileOrder(int order) {
|
||||||
|
set(FILE_ORDER, new Integer(order));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* forums don't have a full publishing cycle,
|
||||||
|
* so we won't apply a heavyweight publishing to attached files
|
||||||
|
* just switch version tag
|
||||||
|
*/
|
||||||
|
public void setLive () {
|
||||||
|
setVersion(LIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prevent files from being returned in search results -
|
||||||
|
* used after save of post, so that for example if post is unapproved,
|
||||||
|
* files are removed from search results
|
||||||
|
*/
|
||||||
|
public void setDraft () {
|
||||||
|
setVersion(DRAFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Post getOwner() {
|
||||||
|
return (Post)DomainObjectFactory.newInstance((DataObject)get(FILE_OWNER));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void removeUnattachedFiles() {
|
||||||
|
s_log.debug("removing orphaned files created more than a day ago");
|
||||||
|
|
||||||
|
DataCollection files = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
|
||||||
|
Calendar yesterday = Calendar.getInstance();
|
||||||
|
yesterday.add(Calendar.DATE, -1);
|
||||||
|
files.addFilter(files.getFilterFactory().lessThan(AUDITING + "." + BasicAuditTrail.CREATION_DATE,
|
||||||
|
yesterday.getTime(),
|
||||||
|
false));
|
||||||
|
|
||||||
|
files.addEqualsFilter(FILE_OWNER, null);
|
||||||
|
while (files.next()) {
|
||||||
|
s_log.debug("deleting one");
|
||||||
|
|
||||||
|
DomainObjectFactory.newInstance(files.getDataObject()).delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import com.arsdigita.cms.ContentItem;
|
||||||
|
import com.arsdigita.cms.dispatcher.AssetURLFinder;
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.NoValidURLException;
|
||||||
|
import com.arsdigita.kernel.URLFinder;
|
||||||
|
import com.arsdigita.kernel.URLService;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* A URLFinder for PostFileAttachments.
|
||||||
|
*/
|
||||||
|
public class PostFileAttachmentURLFinder implements URLFinder {
|
||||||
|
|
||||||
|
private static final AssetURLFinder s_assetFinder = new AssetURLFinder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* find URL for a file attachment by finding its post
|
||||||
|
*
|
||||||
|
* @param oid the OID of the file attachment
|
||||||
|
* @param content the context of the search (ie draft/live)
|
||||||
|
*/
|
||||||
|
public String find(OID oid, String context) throws NoValidURLException {
|
||||||
|
// a draft attachment is one where the post hasn't been saved yet
|
||||||
|
// the behaviour is the same as far as finding the url goes
|
||||||
|
return find(oid);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* find URL for the context of a file attachment. Delegates to
|
||||||
|
* AssetURLFinder.
|
||||||
|
*
|
||||||
|
* @param oid the OID of the file attachment
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String find(OID oid) throws NoValidURLException {
|
||||||
|
return s_assetFinder.find(oid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
|
import com.arsdigita.kernel.NoValidURLException;
|
||||||
|
import com.arsdigita.kernel.URLFinder;
|
||||||
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.web.Application;
|
||||||
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cgyg9330
|
||||||
|
* (copied from Matt Booth)
|
||||||
|
* A URLFinder for Posts
|
||||||
|
*/
|
||||||
|
public class PostFinder implements URLFinder {
|
||||||
|
|
||||||
|
public String find(OID oid, String context) throws NoValidURLException {
|
||||||
|
return find(oid);
|
||||||
|
}
|
||||||
|
public String find(OID oid) throws NoValidURLException {
|
||||||
|
DataObject dobj = SessionManager.getSession().retrieve(oid);
|
||||||
|
if (dobj == null) {
|
||||||
|
throw new NoValidURLException("No such data object " + oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Application app = Application.retrieveApplication(dobj);
|
||||||
|
|
||||||
|
if (app == null) {
|
||||||
|
throw new NoValidURLException("Could not find application instance for " + dobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ThreadedMessage message = new ThreadedMessage(oid);
|
||||||
|
ParameterMap params = new ParameterMap();
|
||||||
|
params.setParameter("thread", message.getThread().getID().toString());
|
||||||
|
return URL.there("/" + app.getPath() + "/thread.jsp", params).toString();
|
||||||
|
} catch (DataObjectNotFoundException e) {
|
||||||
|
throw new NoValidURLException("Could not find application instance for " + dobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.auditing.BasicAuditTrail;
|
||||||
|
import com.arsdigita.cms.ImageAsset;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Domain object for an image attached to a post. Modelled as domain object
|
||||||
|
* rather than simple association with link attribute because cloning
|
||||||
|
* seems to struggle with link attributes
|
||||||
|
*/
|
||||||
|
public class PostImageAttachment extends ImageAsset {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(PostImageAttachment.class);
|
||||||
|
|
||||||
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
|
"com.arsdigita.forum.PostImageAttachment";
|
||||||
|
|
||||||
|
public static final String IMAGE_OWNER = "imageMessage";
|
||||||
|
public static final String IMAGE_ORDER = "imageOrder";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor. ;
|
||||||
|
**/
|
||||||
|
public PostImageAttachment() {
|
||||||
|
super(BASE_DATA_OBJECT_TYPE);
|
||||||
|
setVersion(DRAFT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. The contained <code>DataObject</code> is retrieved
|
||||||
|
* from the persistent storage mechanism with an <code>OID</code>
|
||||||
|
* specified by <i>oid</i>.
|
||||||
|
*
|
||||||
|
* @param oid The <code>OID</code> for the retrieved
|
||||||
|
* <code>DataObject</code>.
|
||||||
|
**/
|
||||||
|
public PostImageAttachment(OID oid) {
|
||||||
|
super(oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. The contained <code>DataObject</code> is retrieved
|
||||||
|
* from the persistent storage mechanism with an <code>OID</code>
|
||||||
|
* specified by <i>id</i> and <code>ContentPage.BASE_DATA_OBJECT_TYPE</code>.
|
||||||
|
*
|
||||||
|
* @param id The <code>id</code> for the retrieved
|
||||||
|
* <code>DataObject</code>.
|
||||||
|
**/
|
||||||
|
public PostImageAttachment(BigDecimal id) {
|
||||||
|
this(new OID(BASE_DATA_OBJECT_TYPE, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostImageAttachment(DataObject obj) {
|
||||||
|
super(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostImageAttachment(String type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseDataObjectType() {
|
||||||
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageOrder(Integer order) {
|
||||||
|
set(IMAGE_ORDER, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageOrder(int order) {
|
||||||
|
set(IMAGE_ORDER, new Integer(order));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Post getOwner() {
|
||||||
|
return (Post)DomainObjectFactory.newInstance((DataObject)get(IMAGE_OWNER));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected static void removeUnattachedImages() {
|
||||||
|
s_log.debug("removing orphaned images created more than a day ago");
|
||||||
|
DataCollection images = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
|
||||||
|
Calendar yesterday = Calendar.getInstance();
|
||||||
|
yesterday.add(Calendar.DATE, -1);
|
||||||
|
images.addFilter(images.getFilterFactory().lessThan(AUDITING + "." + BasicAuditTrail.CREATION_DATE,
|
||||||
|
yesterday.getTime(),
|
||||||
|
false));
|
||||||
|
|
||||||
|
images.addEqualsFilter(IMAGE_OWNER, null);
|
||||||
|
while (images.next()) {
|
||||||
|
s_log.debug("deleting one");
|
||||||
|
DomainObjectFactory.newInstance(images.getDataObject()).delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.KernelExcursion;
|
||||||
|
import com.arsdigita.persistence.Session;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.persistence.TransactionContext;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduler thread to remove any files or images that are more than a day old
|
||||||
|
* and haven't been attached to a post.
|
||||||
|
* These posts arise if a user starts to create a post and closes their browser
|
||||||
|
* before completing the post. This
|
||||||
|
* process gets rid of them on a daily basis to keep them under control
|
||||||
|
*
|
||||||
|
* nb - We can't just delete all unattached assets, as some may be there because the user is
|
||||||
|
* halfway through making a new post
|
||||||
|
*
|
||||||
|
* @author Chris Gilbert(chris.gilbert@westsussex.gov.uk)
|
||||||
|
* @version $Revision: 1.1 $ $DateTime: 2004/08/17 23:15:09 $
|
||||||
|
*/
|
||||||
|
public class RemoveUnattachedAssetsScheduler {
|
||||||
|
|
||||||
|
public static final String versionId = "$Id: RemoveUnattachedAssetsScheduler.java,v 1.1 2006/07/13 10:19:28 cgyg9330 Exp $ by $Author: cgyg9330 $, $DateTime: 2004/08/17 23:15:09 $";
|
||||||
|
|
||||||
|
// For storing timer which runs a method periodically to fire
|
||||||
|
// begin and end events
|
||||||
|
private static Timer s_Timer;
|
||||||
|
|
||||||
|
// if process runs very very slowly, prevent duplicate attempt fro mrunning before the first one ends
|
||||||
|
private static boolean s_running = false;
|
||||||
|
|
||||||
|
private static Logger s_log =
|
||||||
|
Logger.getLogger( RemoveUnattachedAssetsScheduler.class);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* startTimer - starts the timer
|
||||||
|
*/
|
||||||
|
public static synchronized void startTimer() {
|
||||||
|
if ( s_Timer != null ) {
|
||||||
|
return; // Timer already exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer triggers straight away, and then every 24 hours
|
||||||
|
// don't run timer as a daemon - if server stops, kill this process too, as no one will be creating new posts
|
||||||
|
s_Timer = new Timer(false);
|
||||||
|
|
||||||
|
s_Timer.scheduleAtFixedRate(new RemoveUnattachedAssetsTask(), 0, 1000 * 60 * 60 * 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run - Run the task
|
||||||
|
*/
|
||||||
|
public static synchronized void run() {
|
||||||
|
s_log.debug("Firing off scheduler");
|
||||||
|
Session ssn = SessionManager.getSession();
|
||||||
|
if ( !s_running ) {
|
||||||
|
new KernelExcursion() {
|
||||||
|
protected final void excurse() {
|
||||||
|
s_running = true;
|
||||||
|
try {
|
||||||
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
|
TransactionContext txn =SessionManager.getSession().getTransactionContext();
|
||||||
|
txn.beginTxn();
|
||||||
|
|
||||||
|
PostFileAttachment.removeUnattachedFiles();
|
||||||
|
PostImageAttachment.removeUnattachedImages();
|
||||||
|
txn.commitTxn();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
s_log.error("Attempt to remove unconfirmed forum posts failed", t);
|
||||||
|
throw new UncheckedWrapperException(t);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
s_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @version $Revision: 1.1 $ $DateTime: 2004/08/17 23:15:09 $
|
||||||
|
**/
|
||||||
|
class RemoveUnattachedAssetsTask extends TimerTask {
|
||||||
|
|
||||||
|
public static final String versionId = "$Id: RemoveUnattachedAssetsTask.java,v 1.1 2006/07/13 10:19:28 cgyg9330 Exp $ by $Author: cgyg9330 $, $DateTime: 2004/08/17 23:15:09 $";
|
||||||
|
private static final Logger s_log = Logger.getLogger(RemoveUnattachedAssetsTask.class);
|
||||||
|
public void run() {
|
||||||
|
RemoveUnattachedAssetsScheduler.run();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,16 +18,17 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.mail.Mail;
|
||||||
import com.arsdigita.web.ParameterMap;
|
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.notification.BaseSubscription;
|
import com.arsdigita.notification.BaseSubscription;
|
||||||
import com.arsdigita.persistence.DataObject;
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
import com.arsdigita.util.StringUtils;
|
import com.arsdigita.web.ParameterMap;
|
||||||
import org.apache.log4j.Logger;
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The abstract Subscription class provides the ability for Users
|
* The abstract Subscription class provides the ability for Users
|
||||||
|
|
@ -41,12 +42,13 @@ import org.apache.log4j.Logger;
|
||||||
*/
|
*/
|
||||||
public abstract class Subscription extends BaseSubscription {
|
public abstract class Subscription extends BaseSubscription {
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: Subscription.java 287 2005-02-22 00:29:02Z sskracic $" +
|
"$Id: Subscription.java 1628 2007-09-17 08:10:40Z chrisg23 $" +
|
||||||
"$Author: sskracic $" +
|
"$Author: chrisg23 $" +
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
"$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(Subscription.class);
|
private static final Logger s_log = Logger.getLogger(Subscription.class);
|
||||||
|
|
||||||
|
protected static final String HTML_SEPARATOR = "<br><br>\n<hr>\n<br><br>\n";
|
||||||
public Subscription(String objectType) {
|
public Subscription(String objectType) {
|
||||||
super(objectType);
|
super(objectType);
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +83,17 @@ public abstract class Subscription extends BaseSubscription {
|
||||||
if (author == null) {
|
if (author == null) {
|
||||||
author = "Unknown";
|
author = "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
sb.append("<font size='medium' face='Verdana, Arial, Helvetica, sans-serif'>");
|
||||||
|
sb.append("Forum : ");
|
||||||
|
sb.append(post.getForum().getDisplayName()).append("\n<br>");
|
||||||
|
sb.append("Subject : ");
|
||||||
|
sb.append(post.getSubject()).append("\n<br>");
|
||||||
|
sb.append("Posted by: ");
|
||||||
|
sb.append(author).append("\n<br><br>");
|
||||||
|
} else {
|
||||||
|
|
||||||
sb.append("Forum : ");
|
sb.append("Forum : ");
|
||||||
sb.append(post.getForum().getDisplayName()).append("\n");
|
sb.append(post.getForum().getDisplayName()).append("\n");
|
||||||
sb.append("Subject : ");
|
sb.append("Subject : ");
|
||||||
|
|
@ -90,6 +101,9 @@ public abstract class Subscription extends BaseSubscription {
|
||||||
sb.append("Posted by: ");
|
sb.append("Posted by: ");
|
||||||
sb.append(author).append("\n\n");
|
sb.append(author).append("\n\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,8 +112,12 @@ public abstract class Subscription extends BaseSubscription {
|
||||||
* implementation returns a separator and a generic messages.
|
* implementation returns a separator and a generic messages.
|
||||||
*/
|
*/
|
||||||
public String getSignature(ThreadedMessage post) {
|
public String getSignature(ThreadedMessage post) {
|
||||||
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
return HTML_SEPARATOR + ALERT_BLURB + "</font>";
|
||||||
|
} else {
|
||||||
return SEPARATOR + ALERT_BLURB;
|
return SEPARATOR + ALERT_BLURB;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an appropriate message to direct people back to the
|
* @return an appropriate message to direct people back to the
|
||||||
|
|
@ -115,15 +133,13 @@ public abstract class Subscription extends BaseSubscription {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append("To reply to this message, go to:\n");
|
sb.append("To reply to this message, go to:\n");
|
||||||
|
|
||||||
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
sb.append("<br><a href='" + url.getURL() + "'>" + url.getURL() + "</a>");
|
||||||
|
} else {
|
||||||
sb.append(url.getURL());
|
sb.append(url.getURL());
|
||||||
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @return an appropriate separator for the body and signature of a post.
|
|
||||||
*/
|
|
||||||
private static String getSeparator() {
|
|
||||||
return "\n\n" + StringUtils.repeat('-', 20) + "\n\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.PageFactory;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
|
import com.arsdigita.bebop.event.RequestEvent;
|
||||||
|
import com.arsdigita.bebop.event.RequestListener;
|
||||||
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
|
import com.arsdigita.forum.ui.ThreadComponent;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.toolbox.ui.ApplicationAuthenticationListener;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Implementation of com.arsdigita.forum.PageBuilder that creates a basic thread page with read access check
|
||||||
|
*/
|
||||||
|
public class ThreadPageBuilder implements PageBuilder, Constants {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see com.arsdigita.forum.PageBuilder#buildPage(com.arsdigita.bebop.parameters.ParameterModel)
|
||||||
|
*/
|
||||||
|
public Page buildPage() {
|
||||||
|
Page threadPage = PageFactory.buildPage(Constants.FORUM_XML_PREFIX, "Threads", "forumThreadPage");
|
||||||
|
//Output the title in an easy to find place
|
||||||
|
threadPage.add(new SimpleComponent(){
|
||||||
|
public void generateXML(PageState state, Element parent) {
|
||||||
|
Element nameElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":name", Constants.FORUM_XML_NS);
|
||||||
|
nameElement.setText(ForumContext.getContext(state).getForum().getTitle());
|
||||||
|
Element introductionElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":introduction", Constants.FORUM_XML_NS);
|
||||||
|
introductionElement.setText(ForumContext.getContext(state).getForum().getIntroduction());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
threadPage.add(new ThreadComponent());
|
||||||
|
// Register the thread id parameter as a global state parameter.
|
||||||
|
BigDecimalParameter threadID = new BigDecimalParameter(THREAD_PARAM);
|
||||||
|
threadPage.addGlobalStateParam(threadID);
|
||||||
|
threadPage.addRequestListener(new ApplicationAuthenticationListener(PrivilegeDescriptor.READ));
|
||||||
|
|
||||||
|
threadPage.addRequestListener
|
||||||
|
(new ThreadPageRequestListener(threadID));
|
||||||
|
return threadPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ThreadPageRequestListener implements RequestListener {
|
||||||
|
private BigDecimalParameter m_threadID;
|
||||||
|
|
||||||
|
public ThreadPageRequestListener(BigDecimalParameter threadID) {
|
||||||
|
m_threadID = threadID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void pageRequested(RequestEvent event) {
|
||||||
|
PageState state = event.getPageState();
|
||||||
|
ForumContext context = ForumContext.getContext(state);
|
||||||
|
context.setThreadID
|
||||||
|
((BigDecimal) event.getPageState().getValue(m_threadID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,25 +18,27 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
import com.arsdigita.domain.DomainCollection;
|
import com.arsdigita.domain.DomainCollection;
|
||||||
import com.arsdigita.domain.DomainObject;
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.kernel.GroupCollection;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.kernel.permissions.PermissionService;
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.mail.Mail;
|
||||||
import com.arsdigita.messaging.MessageThread;
|
import com.arsdigita.messaging.MessageThread;
|
||||||
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.notification.Notification;
|
import com.arsdigita.notification.Notification;
|
||||||
import com.arsdigita.persistence.DataCollection;
|
import com.arsdigita.persistence.DataCollection;
|
||||||
import com.arsdigita.persistence.DataObject;
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.persistence.DataQuery;
|
|
||||||
import com.arsdigita.persistence.DataQueryDataCollectionAdapter;
|
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <font color="red">Experimental</font>
|
|
||||||
* Class for managing subscriptions to individual threads in a Forum.
|
* Class for managing subscriptions to individual threads in a Forum.
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
|
|
@ -46,7 +48,7 @@ public class ThreadSubscription extends Subscription {
|
||||||
public static final String BASE_DATA_OBJECT_TYPE =
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
"com.arsdigita.forum.ThreadSubscription";
|
"com.arsdigita.forum.ThreadSubscription";
|
||||||
|
|
||||||
private static final String THREAD = "thread";
|
public static final String THREAD = "thread";
|
||||||
|
|
||||||
private MessageThread m_thread = null;
|
private MessageThread m_thread = null;
|
||||||
|
|
||||||
|
|
@ -66,6 +68,29 @@ public class ThreadSubscription extends Subscription {
|
||||||
super(oid);
|
super(oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSubscriptionGroupName() {
|
||||||
|
// not overridden because group should be based on
|
||||||
|
// thread root post name, but thread hasn't been set when
|
||||||
|
// this is called. Group name is updated in setThread method
|
||||||
|
return super.getSubscriptionGroupName();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubscriptionGroupName(Forum forum) {
|
||||||
|
return forum.getTitle() + ": " + getThreadReal().getRootMessage().getSubject() + " Subscription Group";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Group getParentGroup() {
|
||||||
|
GroupCollection forumGroups = ((Forum)Kernel.getContext().getResource()).getGroup().getSubgroups();
|
||||||
|
forumGroups.addEqualsFilter("name", Forum.THREAD_SUBSCRIPTION_GROUPS_NAME);
|
||||||
|
Group parent = null;
|
||||||
|
if (forumGroups.next()) {
|
||||||
|
parent = forumGroups.getGroup();
|
||||||
|
forumGroups.close();
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
public ThreadSubscription(BigDecimal id)
|
public ThreadSubscription(BigDecimal id)
|
||||||
throws DataObjectNotFoundException {
|
throws DataObjectNotFoundException {
|
||||||
super(new OID(BASE_DATA_OBJECT_TYPE, id));
|
super(new OID(BASE_DATA_OBJECT_TYPE, id));
|
||||||
|
|
@ -107,6 +132,7 @@ public class ThreadSubscription extends Subscription {
|
||||||
public void setThread(MessageThread thread) {
|
public void setThread(MessageThread thread) {
|
||||||
m_thread = thread;
|
m_thread = thread;
|
||||||
setAssociation(THREAD, thread);
|
setAssociation(THREAD, thread);
|
||||||
|
getGroup().setName(getSubscriptionGroupName((Forum)Kernel.getContext().getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void afterSave() {
|
protected void afterSave() {
|
||||||
|
|
@ -158,30 +184,51 @@ public class ThreadSubscription extends Subscription {
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DomainCollection getSubsForUser(Party party) {
|
public static DomainCollection getSubsForUser(Party party, PageState state) {
|
||||||
DataQuery subs = SessionManager.getSession()
|
// chris.gilbert@westsussex.gov.uk replace query with standard filtering
|
||||||
.retrieveQuery("com.arsdigita.forum.getUserThreadSubscriptions");
|
DataCollection subscriptions = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
|
||||||
|
subscriptions.addEqualsFilter("group.allMembers.id", party.getID());
|
||||||
|
|
||||||
|
// currently specified in config, but could be selected from widget on screen
|
||||||
|
// ie show thread subscriptions for this forum/all forums
|
||||||
|
//
|
||||||
|
// Currently, if subscription for a different forum is selected, the thread is displayed within
|
||||||
|
// the context of this forum which is not good. I suspect there is a need to set the forum in the
|
||||||
|
// forum context when thread.jsp is reached. Have not implemented changes as we are only displaying
|
||||||
|
// subscriptions for current forum cg.
|
||||||
|
if (!Forum.getConfig().showThreadAlertsForAllForums()){
|
||||||
|
subscriptions.addEqualsFilter("thread.root.objectID", ForumContext.getContext(state).getForum().getID());
|
||||||
|
}
|
||||||
|
|
||||||
subs.setParameter("userID", party.getID());
|
return new DomainCollection(subscriptions);
|
||||||
|
|
||||||
return new DomainCollection(new DataQueryDataCollectionAdapter(subs, "subscription")) {
|
|
||||||
public DomainObject getDomainObject() {
|
|
||||||
return new ThreadSubscription(m_dataCollection.getDataObject());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a signature with information about replying to the
|
* Returns a signature with information about replying to the
|
||||||
* message
|
* message
|
||||||
*/
|
*/
|
||||||
public String getSignature(Post post) {
|
public String getSignature(ThreadedMessage post) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
sb.append(HTML_SEPARATOR);
|
||||||
|
sb.append(getReturnURLMessage((Post)post));
|
||||||
|
sb.append(HTML_SEPARATOR);
|
||||||
|
sb.append(ALERT_BLURB);
|
||||||
|
sb.append("You are receiving this email because you subscribed to ");
|
||||||
|
sb.append("alerts on this thread. To unsubscribe, follow the link above and click the 'stop watching thread' link at the top of the page.\n");
|
||||||
|
sb.append("</font>");
|
||||||
|
} else {
|
||||||
|
sb.append(SEPARATOR);
|
||||||
|
sb.append(ALERT_BLURB);
|
||||||
|
sb.append("You are receiving this email because you subscribed to ");
|
||||||
|
sb.append("alerts on this thread.\n\n");
|
||||||
|
sb.append(REPLY_BLURB);
|
||||||
|
sb.append(getReturnURLMessage((Post)post));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return SEPARATOR
|
|
||||||
+ ALERT_BLURB
|
|
||||||
+ "You are receiving this email because you subscribed to "
|
|
||||||
+ "alerts on this thread.\n\n"
|
|
||||||
+ REPLY_BLURB
|
|
||||||
+ getReturnURLMessage(post);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.portlet;
|
||||||
|
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ThreadCollection;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
|
import com.arsdigita.forum.ui.ThreadList;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
|
import com.arsdigita.bebop.portal.AbstractPortletRenderer;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.messaging.MessageThread;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
import com.arsdigita.xml.formatters.DateFormatter;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.portal.Portlet;
|
||||||
|
import com.arsdigita.portal.apportlet.AppPortlet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* portlet with no attributes that displays links to all forums that user has read access to
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MyForumsPortlet extends Portlet {
|
||||||
|
public static final String versionId = "$Id: MyForumsPortlet.java,v 1.4 2006/07/13 10:19:28 cgyg9330 Exp $ by $Author: cgyg9330 $, $DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
|
"com.arsdigita.forum.MyForumsPortlet";
|
||||||
|
|
||||||
|
|
||||||
|
protected String getBaseDataObjectType() {
|
||||||
|
return BASE_DATA_OBJECT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyForumsPortlet(DataObject dataObject) {
|
||||||
|
super(dataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected AbstractPortletRenderer doGetPortletRenderer() {
|
||||||
|
return new MyForumsPortletRenderer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyForumsPortletRenderer
|
||||||
|
extends AbstractPortletRenderer
|
||||||
|
implements Constants {
|
||||||
|
|
||||||
|
private MyForumsPortlet m_portlet;
|
||||||
|
|
||||||
|
public MyForumsPortletRenderer(MyForumsPortlet
|
||||||
|
portlet) {
|
||||||
|
m_portlet = portlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void generateBodyXML(PageState pageState,
|
||||||
|
Element parent) {
|
||||||
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":myForumsPortlet",
|
||||||
|
FORUM_XML_NS);
|
||||||
|
|
||||||
|
|
||||||
|
Party party = Kernel.getContext().getParty();
|
||||||
|
if (party == null) {
|
||||||
|
party = Kernel.getPublicUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataCollection forums = SessionManager.getSession().retrieve(Forum.BASE_DATA_OBJECT_TYPE);
|
||||||
|
forums.addOrder("lower(" + Forum.TITLE + ")");
|
||||||
|
PermissionService.filterObjects(forums, PrivilegeDescriptor.READ, party.getOID());
|
||||||
|
|
||||||
|
|
||||||
|
while (forums.next()) {
|
||||||
|
Forum forum = (Forum)DomainObjectFactory.newInstance(forums.getDataObject());
|
||||||
|
Element forumEl = content.newChildElement(FORUM_XML_PREFIX + ":forum", FORUM_XML_NS);
|
||||||
|
URL url = URL.there(forum, "/", null);
|
||||||
|
forumEl.addAttribute("url", url.toString());
|
||||||
|
forumEl.addAttribute("title", forum.getTitle());
|
||||||
|
// display last forum update info
|
||||||
|
ThreadCollection threads = forum.getThreads();
|
||||||
|
threads.addOrder(MessageThread.LAST_UPDATE);
|
||||||
|
if (threads.next()) {
|
||||||
|
MessageThread lastUpdatedThread = threads.getMessageThread();
|
||||||
|
forumEl.addAttribute("lastUpdated", new DateFormatter().format(lastUpdatedThread.getLatestUpdateDate()));
|
||||||
|
threads.close();
|
||||||
|
} else {
|
||||||
|
forumEl.addAttribute("lastUpdated", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ import com.arsdigita.portal.apportlet.AppPortlet;
|
||||||
|
|
||||||
|
|
||||||
public class RecentPostingsPortlet extends AppPortlet {
|
public class RecentPostingsPortlet extends AppPortlet {
|
||||||
public static final String versionId = "$Id: RecentPostingsPortlet.java 755 2005-09-02 13:42:47Z sskracic $ by $Author: sskracic $, $DateTime: 2004/08/17 23:26:27 $";
|
public static final String versionId = "$Id: RecentPostingsPortlet.java 1628 2007-09-17 08:10:40Z chrisg23 $ by $Author: chrisg23 $, $DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
public static final String BASE_DATA_OBJECT_TYPE =
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
"com.arsdigita.forum.RecentPostingsPortlet";
|
"com.arsdigita.forum.RecentPostingsPortlet";
|
||||||
|
|
@ -93,6 +93,7 @@ class RecentPostingsPortletRenderer
|
||||||
Forum forum = (Forum)m_portlet.getParentApplication();
|
Forum forum = (Forum)m_portlet.getParentApplication();
|
||||||
|
|
||||||
content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).toString());
|
content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).toString());
|
||||||
|
content.addAttribute("forumName", forum.getTitle());
|
||||||
|
|
||||||
Party party = Kernel.getContext().getParty();
|
Party party = Kernel.getContext().getParty();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.search;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.cms.search.AssetExtractor;
|
||||||
|
import com.arsdigita.cms.search.AssetMetadataProvider;
|
||||||
|
import com.arsdigita.domain.DomainObject;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.PostFileAttachment;
|
||||||
|
import com.arsdigita.globalization.Globalization;
|
||||||
|
import com.arsdigita.globalization.SystemLocaleProvider;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.kernel.URLService;
|
||||||
|
import com.arsdigita.kernel.User;
|
||||||
|
import com.arsdigita.search.ContentProvider;
|
||||||
|
import com.arsdigita.search.ContentType;
|
||||||
|
import com.arsdigita.search.MetadataProvider;
|
||||||
|
import com.arsdigita.toolbox.util.GlobalizationUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FileAttachmentMetadataProvider extends AssetMetadataProvider {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(FileAttachmentMetadataProvider.class);
|
||||||
|
|
||||||
|
public String getSummary(DomainObject dobj) {
|
||||||
|
PostFileAttachment file = (PostFileAttachment)dobj;
|
||||||
|
s_log.debug("Getting Summary File " + file.getID());
|
||||||
|
Post owner = file.getOwner();
|
||||||
|
//s_log.debug("Owner " + (owner == null ? null : owner.getID()));
|
||||||
|
if (owner == null){
|
||||||
|
//until post is saved, the file doesn't have an owner
|
||||||
|
//file is saved as draft so result will not be returned at front end
|
||||||
|
return "File attached to forum post";
|
||||||
|
}
|
||||||
|
String url = URLService.locate(owner.getOID());
|
||||||
|
String fileDescription = file.getDescription();
|
||||||
|
StringBuffer summary = new StringBuffer();
|
||||||
|
if (fileDescription != null) {
|
||||||
|
summary.append(fileDescription + " - ");
|
||||||
|
}
|
||||||
|
summary.append("A file attached to <a href=\"" + url + "\">" +
|
||||||
|
owner.getSubject() + "</a> - a posting by " +
|
||||||
|
((User)owner.getFrom()).getName() + " to forum " + owner.getForum().getTitle());
|
||||||
|
return summary.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIndexable (DomainObject dobj) {
|
||||||
|
PostFileAttachment file = (PostFileAttachment)dobj;
|
||||||
|
Post owner = file.getOwner();
|
||||||
|
Post root = null;
|
||||||
|
s_log.debug("start:isIndexable");
|
||||||
|
boolean indexable = false;
|
||||||
|
if (owner != null) {
|
||||||
|
// post has been saved
|
||||||
|
s_log.debug("owner = " + owner);
|
||||||
|
BigDecimal rootId = owner.getRoot();
|
||||||
|
if (rootId != null) {
|
||||||
|
root = new Post(owner.getRoot());
|
||||||
|
// else this is a root post
|
||||||
|
}
|
||||||
|
indexable = owner.getStatus().equals(Post.APPROVED) && (root == null ? true : root.getStatus().equals(Post.APPROVED));
|
||||||
|
}
|
||||||
|
return indexable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.search;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DomainObject;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.globalization.Globalization;
|
||||||
|
import com.arsdigita.globalization.SystemLocaleProvider;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.search.ContentProvider;
|
||||||
|
import com.arsdigita.search.ContentType;
|
||||||
|
import com.arsdigita.search.MetadataProvider;
|
||||||
|
import com.arsdigita.toolbox.util.GlobalizationUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PostMetadataProvider implements MetadataProvider {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(PostMetadataProvider.class);
|
||||||
|
/**
|
||||||
|
* No specific information is provided for a forum post
|
||||||
|
*/
|
||||||
|
public String getTypeSpecificInfo(DomainObject dobj) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the default system Locale
|
||||||
|
*/
|
||||||
|
public Locale getLocale(DomainObject dobj) {
|
||||||
|
return new SystemLocaleProvider().getLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the subject of the post
|
||||||
|
* @see com.arsdigita.search.MetadataProvider#getTitle(com.arsdigita.domain.DomainObject)
|
||||||
|
*/
|
||||||
|
public String getTitle(DomainObject dobj) {
|
||||||
|
Post post = (Post)dobj;
|
||||||
|
return post.getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the date of posting and the author
|
||||||
|
*/
|
||||||
|
public String getSummary(DomainObject dobj) {
|
||||||
|
Post post = (Post)dobj;
|
||||||
|
return "Posted to " + post.getForum().getTitle() + " by " +
|
||||||
|
post.getFrom().getName() + " on " +
|
||||||
|
DateFormat.getDateInstance(DateFormat.MEDIUM).format(post.getSentDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreationDate(DomainObject dobj) {
|
||||||
|
Post post = (Post)dobj;
|
||||||
|
return post.getSentDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Party getCreationParty(DomainObject dobj) {
|
||||||
|
Post post = (Post)dobj;
|
||||||
|
return post.getFrom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastModifiedDate(DomainObject dobj) {
|
||||||
|
//we are not storing the date if the post is edited
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Party getLastModifiedParty(DomainObject dobj) {
|
||||||
|
//we are not storing the person that edits a post
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentProvider[] getContent(DomainObject dobj, ContentType type) {
|
||||||
|
List content = new ArrayList();
|
||||||
|
|
||||||
|
if (type.equals(ContentType.XML)) {
|
||||||
|
content.add(new XMLContentProvider("xml", (Post)dobj));
|
||||||
|
} else if (type.equals(ContentType.TEXT)) {
|
||||||
|
content.add(new TextContentProvider("text", (Post)dobj));
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't deal with raw content - attached files are indexed separately
|
||||||
|
|
||||||
|
return (ContentProvider[])content.toArray(
|
||||||
|
new ContentProvider[content.size()]);
|
||||||
|
}
|
||||||
|
public String getContentSection(DomainObject dobj) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIndexable(DomainObject dobj) {
|
||||||
|
Post post = (Post)dobj;
|
||||||
|
s_log.debug("Post saved - status is " + post.getStatus() + ". Index Object? " + post.getStatus().equals(Post.APPROVED));
|
||||||
|
|
||||||
|
return post.getStatus().equals(Post.APPROVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.search;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DomainObjectTextRenderer;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.search.ContentProvider;
|
||||||
|
import com.arsdigita.search.ContentType;
|
||||||
|
|
||||||
|
public class TextContentProvider implements ContentProvider {
|
||||||
|
|
||||||
|
private Post m_post;
|
||||||
|
private String m_context;
|
||||||
|
|
||||||
|
public TextContentProvider(String context, Post post) {
|
||||||
|
m_context = context;
|
||||||
|
m_post = post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContext() {
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentType getType() {
|
||||||
|
return ContentType.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes() {
|
||||||
|
|
||||||
|
DomainObjectTextRenderer renderer = new DomainObjectTextRenderer();
|
||||||
|
|
||||||
|
renderer.walk(m_post, PostMetadataProvider.class.getName());
|
||||||
|
|
||||||
|
String text = renderer.getText();
|
||||||
|
|
||||||
|
// if required, retrieve file attachments here and add their content
|
||||||
|
|
||||||
|
return text.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.search;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
|
import com.arsdigita.search.ContentProvider;
|
||||||
|
import com.arsdigita.search.ContentType;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Document;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
public class XMLContentProvider implements ContentProvider, Constants {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger
|
||||||
|
.getLogger(XMLContentProvider.class);
|
||||||
|
|
||||||
|
private Post m_post;
|
||||||
|
private String m_context;
|
||||||
|
|
||||||
|
public XMLContentProvider(String context, Post post) {
|
||||||
|
m_context = context;
|
||||||
|
m_post = post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContext() {
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentType getType() {
|
||||||
|
return ContentType.XML;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes() {
|
||||||
|
|
||||||
|
|
||||||
|
Element root = new Element("forum:post", FORUM_XML_NS);
|
||||||
|
DomainObjectXMLRenderer renderer =
|
||||||
|
new DomainObjectXMLRenderer(root);
|
||||||
|
|
||||||
|
renderer.setWrapAttributes(true);
|
||||||
|
renderer.walk(m_post, PostMetadataProvider.class.getName());
|
||||||
|
|
||||||
|
Document doc = null;
|
||||||
|
try {
|
||||||
|
doc = new Document(root);
|
||||||
|
} catch (javax.xml.parsers.ParserConfigurationException ex) {
|
||||||
|
throw new UncheckedWrapperException("Unable to create xml document for post " + m_post.getID(), ex);
|
||||||
|
}
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("XML is " + doc.toString(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String xml = doc.toString(true);
|
||||||
|
return xml.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.FormData;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
|
import com.arsdigita.bebop.FormStep;
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.event.FormValidationListener;
|
||||||
|
import com.arsdigita.bebop.event.ParameterEvent;
|
||||||
|
import com.arsdigita.bebop.form.FileUpload;
|
||||||
|
import com.arsdigita.bebop.form.Submit;
|
||||||
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
|
import com.arsdigita.bebop.parameters.ArrayParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.FileSizeValidationListener;
|
||||||
|
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
|
import com.arsdigita.bebop.parameters.StringInRangeValidationListener;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||||
|
import com.arsdigita.dispatcher.MultipartHttpServletRequest;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.PostFileAttachment;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Gilbert <a href="mailto:chris.gilbert@westsussex.gov.uk">chris.gilbert@westsussex.gov.uk</a>
|
||||||
|
*
|
||||||
|
* Wizard step to attach files to a post. This step may be bypassed
|
||||||
|
* if a forum administrator changes the forum settings on the UI
|
||||||
|
*
|
||||||
|
* nb - a simpler reuseable generic wizard file attachments step has been created
|
||||||
|
* forum will be refactored to use it in the future. see ccm-wsx-wizard-steps in contrib
|
||||||
|
*/
|
||||||
|
public class AttachedFilesStep
|
||||||
|
extends FormStep
|
||||||
|
implements Constants, FormInitListener, FormProcessListener, FormValidationListener {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(AttachedFilesStep.class);
|
||||||
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private AttachedFilesTable m_attachedFiles;
|
||||||
|
private FileUpload m_upload;
|
||||||
|
private TextArea m_description;
|
||||||
|
private Submit m_addFile;
|
||||||
|
private PostForm m_container;
|
||||||
|
|
||||||
|
private ArrayParameter m_newFiles = new ArrayParameter("newFiles");
|
||||||
|
private ArrayParameter m_existingFiles = new ArrayParameter("oldFiles");
|
||||||
|
|
||||||
|
|
||||||
|
public AttachedFilesStep(ACSObjectSelectionModel post, PostForm container) {
|
||||||
|
super("postFiles",
|
||||||
|
new SimpleContainer(
|
||||||
|
FORUM_XML_PREFIX + ":postFormFiles",
|
||||||
|
FORUM_XML_NS));
|
||||||
|
|
||||||
|
m_post = post;
|
||||||
|
m_container = container;
|
||||||
|
m_attachedFiles = new AttachedFilesTable(m_newFiles, m_existingFiles, this);
|
||||||
|
|
||||||
|
add(m_attachedFiles);
|
||||||
|
|
||||||
|
m_upload = new FileUpload("file", true);
|
||||||
|
m_upload.addValidationListener(new NotEmptyValidationListener(
|
||||||
|
Text
|
||||||
|
.gz("forum.ui.validation.file_null")) {
|
||||||
|
public void validate(ParameterEvent e) {
|
||||||
|
// don't fire validation if the next or previous button of the wizard has been pressed
|
||||||
|
|
||||||
|
if (m_addFile.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// this validation can fire any time - if there is no file then it won't fail
|
||||||
|
m_upload.addValidationListener(
|
||||||
|
new FileSizeValidationListener(Forum.getConfig().getMaxFileSize()));
|
||||||
|
add(m_upload);
|
||||||
|
m_description = new TextArea("fileDescription");
|
||||||
|
m_description.setCols(20);
|
||||||
|
m_description.setRows(5);
|
||||||
|
|
||||||
|
m_description
|
||||||
|
.addValidationListener(new StringInRangeValidationListener(
|
||||||
|
0,
|
||||||
|
4000,
|
||||||
|
Text.gz("forum.ui.validation.file_description_too_long")) {
|
||||||
|
public void validate(ParameterEvent e)
|
||||||
|
throws FormProcessException {
|
||||||
|
// don't fire validation if the next or previous button of the wizard has been pressed
|
||||||
|
|
||||||
|
if (m_addFile.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(m_description);
|
||||||
|
m_addFile = new Submit("Add File");
|
||||||
|
add(m_addFile);
|
||||||
|
addInitListener(this);
|
||||||
|
addProcessListener(this);
|
||||||
|
addValidationListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads the file and creates an orphaned PostFileAttachment
|
||||||
|
* that will be associated with the post when the wizard is completed
|
||||||
|
* or deleted if the wizard is cancelled.
|
||||||
|
*/
|
||||||
|
public void process(FormSectionEvent e) throws FormProcessException {
|
||||||
|
FormData data = e.getFormData();
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (m_addFile.isSelected(state)) {
|
||||||
|
|
||||||
|
PostFileAttachment attachment;
|
||||||
|
s_log.debug("adding file");
|
||||||
|
try {
|
||||||
|
String fileName = (String) m_upload.getValue(state);
|
||||||
|
s_log.debug("filename is " + fileName);
|
||||||
|
File file =
|
||||||
|
(
|
||||||
|
(MultipartHttpServletRequest) e
|
||||||
|
.getPageState()
|
||||||
|
.getRequest())
|
||||||
|
.getFile(
|
||||||
|
"file");
|
||||||
|
s_log.debug("uploaded file is " + file.getName());
|
||||||
|
//MimeType mimeType = MimeType.guessMimeTypeFromFile(fileName);
|
||||||
|
//s_log.debug("mime type is " + mimeType.getMimeType());
|
||||||
|
attachment = new PostFileAttachment();
|
||||||
|
attachment.loadFromFile(
|
||||||
|
fileName,
|
||||||
|
file,
|
||||||
|
"application/octet-stream");
|
||||||
|
attachment.setDescription(
|
||||||
|
(String) m_description.getValue(state));
|
||||||
|
BigDecimal id = attachment.getID();
|
||||||
|
String[] current = (String[]) state.getValue(m_newFiles);
|
||||||
|
if (current == null) {
|
||||||
|
current = new String[] { id.toString()};
|
||||||
|
} else {
|
||||||
|
List files = Arrays.asList(current);
|
||||||
|
current = new String[files.size() + 1];
|
||||||
|
Iterator it = files.iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
current[i++] = (String) it.next();
|
||||||
|
}
|
||||||
|
current[i] = id.toString();
|
||||||
|
}
|
||||||
|
state.setValue(m_newFiles, current);
|
||||||
|
s_log.debug("File Uploaded");
|
||||||
|
m_description.setValue(state, null);
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new FormProcessException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent users navigating away from this page unintentionally without
|
||||||
|
* adding an uploaded file first
|
||||||
|
*/
|
||||||
|
public void validate(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (!m_addFile.isSelected(state)
|
||||||
|
&& StringUtils.isNotBlank((String) m_upload.getValue(state))) {
|
||||||
|
throw new FormProcessException(
|
||||||
|
(String) Text
|
||||||
|
.gz("forum.ui.validation.file_not_uploaded")
|
||||||
|
.localize());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFile(BigDecimal id, PageState state) {
|
||||||
|
String[] existingArray = (String[]) state.getValue(m_existingFiles);
|
||||||
|
if (existingArray != null) {
|
||||||
|
List existing = Arrays.asList(existingArray);
|
||||||
|
if (!existing.contains(id)) {
|
||||||
|
// this has been added during edit (or this is a new post)
|
||||||
|
s_log.debug("new file - I will actually delete it");
|
||||||
|
PostFileAttachment attachment = new PostFileAttachment(id);
|
||||||
|
attachment.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// m_new_files cannot contain null if request is to delete file
|
||||||
|
Assert.exists(state.getValue(m_newFiles));
|
||||||
|
List newFiles =
|
||||||
|
new ArrayList(Arrays.asList((String[]) state.getValue(m_newFiles)));
|
||||||
|
newFiles.remove(id);
|
||||||
|
String[] current = new String[newFiles.size()];
|
||||||
|
Iterator it = newFiles.iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
current[i++] = (String) it.next();
|
||||||
|
}
|
||||||
|
s_log.debug("size of new files array = " + current.length);
|
||||||
|
state.setValue(m_newFiles, current);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataCollection getCurrentFiles(PageState state) {
|
||||||
|
|
||||||
|
String[] currentArray = (String[]) state.getValue(m_newFiles);
|
||||||
|
if (currentArray != null && currentArray.length != 0) {
|
||||||
|
List current = Arrays.asList((String[]) state.getValue(m_newFiles));
|
||||||
|
|
||||||
|
DataCollection files =
|
||||||
|
SessionManager.getSession().retrieve(
|
||||||
|
PostFileAttachment.BASE_DATA_OBJECT_TYPE);
|
||||||
|
files.addFilter("id in :files").set("files", current);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called at the end of the wizard when the form is processed
|
||||||
|
* set the files attached to the post according to the
|
||||||
|
* file attachment step
|
||||||
|
* @param post
|
||||||
|
* @param state
|
||||||
|
*/
|
||||||
|
public void attachFiles(Post post, PageState state) {
|
||||||
|
|
||||||
|
List newFiles = Collections.EMPTY_LIST;
|
||||||
|
String[] newFilesArray = (String[]) state.getValue(m_newFiles);
|
||||||
|
if (newFilesArray != null) {
|
||||||
|
newFiles = new ArrayList(Arrays.asList(newFilesArray));
|
||||||
|
}
|
||||||
|
String[] existing = (String[]) state.getValue(m_existingFiles);
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
// we are editing a post - leave any unchanged files, delete any that have been
|
||||||
|
// removed
|
||||||
|
for (int i = 0; i < existing.length; i++) {
|
||||||
|
if (newFiles.contains(existing[i])) {
|
||||||
|
// no change to this one
|
||||||
|
newFiles.remove(existing[i]);
|
||||||
|
} else {
|
||||||
|
// file has been deleted in edit
|
||||||
|
PostFileAttachment file =
|
||||||
|
new PostFileAttachment(new BigDecimal(existing[i]));
|
||||||
|
post.removeFile(file);
|
||||||
|
// file deleted
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iterator it = newFiles.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
// new files added
|
||||||
|
PostFileAttachment file =
|
||||||
|
new PostFileAttachment(new BigDecimal((String) it.next()));
|
||||||
|
post.addFile(file);
|
||||||
|
}
|
||||||
|
state.setValue(m_newFiles, null);
|
||||||
|
state.setValue(m_existingFiles, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(Page p) {
|
||||||
|
super.register(p);
|
||||||
|
|
||||||
|
p.addGlobalStateParam(m_existingFiles);
|
||||||
|
p.addGlobalStateParam(m_newFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void init(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
|
||||||
|
if (m_container
|
||||||
|
.getContext(state)
|
||||||
|
.equals(PostForm.EDIT_CONTEXT)) {
|
||||||
|
|
||||||
|
Post editPost = (Post) m_post.getSelectedObject(state);
|
||||||
|
DataAssociationCursor files = editPost.getFiles();
|
||||||
|
if (files.size() > 0) {
|
||||||
|
|
||||||
|
String[] fileIDs =
|
||||||
|
new String[new Long(files.size()).intValue()];
|
||||||
|
int i = 0;
|
||||||
|
while (files.next()) {
|
||||||
|
|
||||||
|
PostFileAttachment file =
|
||||||
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
fileIDs[i++] = file.getID().toString();
|
||||||
|
}
|
||||||
|
state.setValue(m_existingFiles, fileIDs);
|
||||||
|
state.setValue(m_newFiles, fileIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate xml for the confirmation step (unfortunately we can't just
|
||||||
|
* traverse the post because it hasn't been created at this point)
|
||||||
|
* @param state
|
||||||
|
* @param p
|
||||||
|
*/
|
||||||
|
public void generatePostXML(PageState state, Element p) {
|
||||||
|
DataCollection files = getCurrentFiles(state);
|
||||||
|
if (files == null) {
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
while(files.next()) {
|
||||||
|
PostFileAttachment file = (PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(p.newChildElement("files"));
|
||||||
|
xr.setWrapRoot(false);
|
||||||
|
xr.setWrapAttributes(true);
|
||||||
|
xr.setWrapObjects(false);
|
||||||
|
xr.walk(file, ConfirmStep.class.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void clearParameters(PageState state) {
|
||||||
|
state.setValue(m_existingFiles, null);
|
||||||
|
state.setValue(m_newFiles, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ControlLink;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
|
import com.arsdigita.bebop.parameters.ArrayParameter;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.cms.FileAsset;
|
||||||
|
import com.arsdigita.cms.dispatcher.Utilities;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.PostFileAttachment;
|
||||||
|
import com.arsdigita.forum.PostImageAttachment;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.messaging.MessagePart;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic table with delete link. This could be extended to provide
|
||||||
|
* additional links eg move up/move down. New generic wizard
|
||||||
|
* file attachment table does include this functionality
|
||||||
|
* so it will be introduced when forum is refactored
|
||||||
|
*
|
||||||
|
* @author Chris Gilbert <a href="mailto:chris.gilbert@westsussex.gov.uk">chris.gilbert@westsussex.gov.uk</a>
|
||||||
|
* @version $Revision: 1.4 $ $DateTime: 2004/08/17 23:15:09 $
|
||||||
|
**/
|
||||||
|
public class AttachedFilesTable extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
|
// I have not implemented an edit link or a move up/down link although the data model
|
||||||
|
// is able to manage this, it seemed like a lot of work for a minor requirement for a forum
|
||||||
|
// currently, files are listed in the order they are added.
|
||||||
|
|
||||||
|
// to add extra links, define new keys for the control event and check key value in the
|
||||||
|
// respond method (see ThreadDisplay for example code)
|
||||||
|
//
|
||||||
|
// only issue is that when editing a post, the editor cannot change the description easily
|
||||||
|
// (though they could download the file to their PC, delete the existing one and recreate it)
|
||||||
|
private static Logger s_log = Logger.getLogger(AttachedFilesTable.class);
|
||||||
|
protected static final String ACTION_DELETE = "delete";
|
||||||
|
|
||||||
|
private ArrayParameter m_newFiles;
|
||||||
|
private ArrayParameter m_existingFiles;
|
||||||
|
|
||||||
|
private AttachedFilesStep m_parent;
|
||||||
|
|
||||||
|
public AttachedFilesTable(
|
||||||
|
ArrayParameter newFiles,
|
||||||
|
ArrayParameter existingFiles,
|
||||||
|
AttachedFilesStep parent) {
|
||||||
|
m_newFiles = newFiles;
|
||||||
|
m_existingFiles = existingFiles;
|
||||||
|
m_parent = parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void respond(PageState state) throws ServletException {
|
||||||
|
super.respond(state);
|
||||||
|
|
||||||
|
String key = state.getControlEventName();
|
||||||
|
String value = state.getControlEventValue();
|
||||||
|
if (ACTION_DELETE.equals(key)) {
|
||||||
|
List existing = Collections.EMPTY_LIST;
|
||||||
|
String[] existingArray = (String[]) state.getValue(m_existingFiles);
|
||||||
|
if (existingArray != null) {
|
||||||
|
existing = Arrays.asList(existingArray);
|
||||||
|
}
|
||||||
|
if (!existing.contains(value)) {
|
||||||
|
// this has been added during edit
|
||||||
|
OID oid =
|
||||||
|
new OID(
|
||||||
|
PostFileAttachment.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new BigDecimal(value));
|
||||||
|
|
||||||
|
DomainObjectFactory.newInstance(oid).delete();
|
||||||
|
}
|
||||||
|
List newFiles =
|
||||||
|
new ArrayList(
|
||||||
|
Arrays.asList((String[]) state.getValue(m_newFiles)));
|
||||||
|
newFiles.remove(value);
|
||||||
|
String[] current = new String[newFiles.size()];
|
||||||
|
Iterator it = newFiles.iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
current[i++] = (String) it.next();
|
||||||
|
}
|
||||||
|
state.setValue(m_newFiles, current);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void generateXML(PageState state, Element p) {
|
||||||
|
Element mainElement =
|
||||||
|
p.newChildElement(
|
||||||
|
FORUM_XML_PREFIX + ":attachedFiles",
|
||||||
|
FORUM_XML_NS);
|
||||||
|
|
||||||
|
DataCollection files = m_parent.getCurrentFiles(state);
|
||||||
|
if (files == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (files.next()) {
|
||||||
|
|
||||||
|
PostFileAttachment file =
|
||||||
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
Element fileElement =
|
||||||
|
mainElement.newChildElement(
|
||||||
|
FORUM_XML_PREFIX + ":file",
|
||||||
|
FORUM_XML_NS);
|
||||||
|
fileElement.addAttribute("name", file.getName());
|
||||||
|
fileElement.addAttribute("url", Utilities.getAssetURL(file));
|
||||||
|
fileElement.addAttribute("description", file.getDescription());
|
||||||
|
generateActionXML(state, fileElement, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateActionXML(
|
||||||
|
PageState state,
|
||||||
|
Element parent,
|
||||||
|
PostFileAttachment image) {
|
||||||
|
//separate method so that if future links require some logic
|
||||||
|
//to decide whether to display, it can be implemented here
|
||||||
|
parent.addAttribute("deleteLink", makeURL(state, ACTION_DELETE, image));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String makeURL(
|
||||||
|
PageState state,
|
||||||
|
String action,
|
||||||
|
PostFileAttachment file) {
|
||||||
|
state.setControlEvent(this, action, file.getID().toString());
|
||||||
|
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
url = state.stateAsURL();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new UncheckedWrapperException("cannot create url", ex);
|
||||||
|
}
|
||||||
|
state.clearControlEvent();
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -21,11 +21,14 @@ package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Form;
|
import com.arsdigita.bebop.Form;
|
||||||
import com.arsdigita.bebop.FormData;
|
import com.arsdigita.bebop.FormData;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SaveCancelSection;
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.event.FormSubmissionListener;
|
||||||
import com.arsdigita.bebop.form.Submit;
|
import com.arsdigita.bebop.form.Submit;
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
import com.arsdigita.bebop.form.TextField;
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
|
@ -45,12 +48,12 @@ import org.apache.log4j.Logger;
|
||||||
* parent category. temporary hack for testing purposes
|
* parent category. temporary hack for testing purposes
|
||||||
*
|
*
|
||||||
* @author <a href=mailto:sarah@arsdigita.com>Sarah Barwig</a>
|
* @author <a href=mailto:sarah@arsdigita.com>Sarah Barwig</a>
|
||||||
* @version $Revision: #9 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision: 1.2 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
public class CategoryAddForm extends Form {
|
public class CategoryAddForm extends Form {
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: CategoryAddForm.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: CategoryAddForm.java 1628 2007-09-17 08:10:40Z chrisg23 $" +
|
||||||
"$Author: sskracic $" +
|
"$Author: chrisg23 $" +
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
"$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
|
@ -78,8 +81,24 @@ public class CategoryAddForm extends Form {
|
||||||
m_description.setWrap(TextArea.SOFT);
|
m_description.setWrap(TextArea.SOFT);
|
||||||
add(m_description);
|
add(m_description);
|
||||||
|
|
||||||
Submit submit = new Submit("Create topic");
|
// Cancel button added cg
|
||||||
|
// Would have used a saveCancel section but this would make existing
|
||||||
|
// stylesheets for legacy forums miss the buttons
|
||||||
|
Submit submit = new Submit(Text.gz("forum.ui.topic.save"));
|
||||||
|
final Submit cancel = new Submit(Text.gz("forum.ui.cancel"));
|
||||||
add(submit);
|
add(submit);
|
||||||
|
add(cancel);
|
||||||
|
addSubmissionListener(new FormSubmissionListener(){
|
||||||
|
public void submitted(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (cancel.isSelected(state)){
|
||||||
|
fireCompletionEvent(state);
|
||||||
|
throw new FormProcessException("cancelled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listener to process form data. Just adds the categories, then
|
* Listener to process form data. Just adds the categories, then
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public class CategoryView extends SimpleContainer
|
||||||
|
|
||||||
Container categories = new SimpleContainer();
|
Container categories = new SimpleContainer();
|
||||||
|
|
||||||
Container linksPanel = new SimpleContainer("forum:topicOptions",
|
Container linksPanel = new SimpleContainer(Constants.FORUM_XML_PREFIX + ":topicOptions",
|
||||||
Constants.FORUM_XML_NS);
|
Constants.FORUM_XML_NS);
|
||||||
m_addCategoryLink = new ToggleLink(new Label(Text.gz("forum.ui.newTopic")));
|
m_addCategoryLink = new ToggleLink(new Label(Text.gz("forum.ui.newTopic")));
|
||||||
m_addCategoryLink.setClassAttr("actionLink");
|
m_addCategoryLink.setClassAttr("actionLink");
|
||||||
|
|
|
||||||
|
|
@ -40,25 +40,28 @@ import java.util.TooManyListenersException;
|
||||||
* @author ron@arsdigita.com
|
* @author ron@arsdigita.com
|
||||||
* @author sarah@arsdigita.com
|
* @author sarah@arsdigita.com
|
||||||
*
|
*
|
||||||
* @version $Id: CategoryWidget.java 287 2005-02-22 00:29:02Z sskracic $
|
* @version $Id: CategoryWidget.java 1628 2007-09-17 08:10:40Z chrisg23 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class CategoryWidget extends SingleSelect implements Constants {
|
public class CategoryWidget extends SingleSelect implements Constants {
|
||||||
|
|
||||||
public CategoryWidget(ParameterModel categoryParameter) {
|
public CategoryWidget(ParameterModel categoryParameter) {
|
||||||
super(categoryParameter);
|
super(categoryParameter);
|
||||||
addOption(new Option(TOPIC_NONE.toString(),
|
|
||||||
new Label(Text.gz("forum.ui.topic.none"))));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
addPrintListener(new PrintListener() {
|
addPrintListener(new PrintListener() {
|
||||||
public void prepare(PrintEvent e) {
|
public void prepare(PrintEvent e) {
|
||||||
PageState s = e.getPageState();
|
PageState s = e.getPageState();
|
||||||
final Forum forum = getForum(s);
|
final Forum forum = getForum(s);
|
||||||
|
SingleSelect target = (SingleSelect) e.getTarget();
|
||||||
|
|
||||||
// Get categories for this forum
|
// Get categories for this forum
|
||||||
|
if (forum.noCategoryPostsAllowed()) {
|
||||||
|
target.addOption(new Option(TOPIC_NONE.toString(),
|
||||||
|
new Label(Text.gz("forum.ui.topic.none"))));
|
||||||
|
}
|
||||||
final Category root = forum.getRootCategory();
|
final Category root = forum.getRootCategory();
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
SingleSelect target = (SingleSelect) e.getTarget();
|
|
||||||
addCategories(root, target);
|
addCategories(root, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.kernel.User;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Gilbert <a href="mailto:chris.gilbert@westsussex.gov.uk">chris.gilbert@westsussex.gov.uk</a>
|
||||||
|
*
|
||||||
|
* Traverse the post to output all it's attributes and associations for previewing
|
||||||
|
* (or rather, pretend to - the post isn't persistent until confirm step is complete
|
||||||
|
* so it can't be traversed. Instead, each step adds some xml to represent the data
|
||||||
|
* it has gathered
|
||||||
|
*/
|
||||||
|
public class ConfirmStep extends SimpleContainer implements Constants {
|
||||||
|
|
||||||
|
private PostForm m_container;
|
||||||
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
public ConfirmStep(ACSObjectSelectionModel post, PostForm container) {
|
||||||
|
m_container = container;
|
||||||
|
m_post = post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateXML(PageState state, Element parent) {
|
||||||
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":postConfirm",FORUM_XML_NS);
|
||||||
|
Date sent;
|
||||||
|
Party sender;
|
||||||
|
if (m_container.getContext(state).equals(PostForm.EDIT_CONTEXT)) {
|
||||||
|
Post post = (Post)m_post.getSelectedObject(state);
|
||||||
|
sent = post.getSentDate();
|
||||||
|
sender = post.getFrom();
|
||||||
|
} else {
|
||||||
|
sent = new Date();
|
||||||
|
sender = Kernel.getContext().getParty();
|
||||||
|
if (sender == null) {
|
||||||
|
sender = Kernel.getPublicUser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content.newChildElement(Post.SENT).setText(sent.toString());
|
||||||
|
|
||||||
|
content.newChildElement(Post.SENDER).newChildElement(User.DISPLAY_NAME).setText(sender.getDisplayName());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_container.generatePostXML(state, content);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,12 +25,13 @@ import java.math.BigDecimal;
|
||||||
* XML namespaces, URLs, URL variable names, etc.
|
* XML namespaces, URLs, URL variable names, etc.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:teadams@arsdigita.com">Tracy Adams</a>
|
* @author <a href="mailto:teadams@arsdigita.com">Tracy Adams</a>
|
||||||
* @version $Revision: #8 $ $Date: 2004/08/17 $
|
* @version $Revision: 1.3 $ $Date: 2006/03/08 15:38:33 $
|
||||||
* @since ACS 4.7
|
* @since ACS 4.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface Constants {
|
public interface Constants {
|
||||||
|
|
||||||
|
static final String FORUM_XML_PREFIX = "forum";
|
||||||
static final String FORUM_XML_NS = "http://www.arsdigita.com/forum/1.0";
|
static final String FORUM_XML_NS = "http://www.arsdigita.com/forum/1.0";
|
||||||
|
|
||||||
static final String FORUM_MODE_VIEW = "view";
|
static final String FORUM_MODE_VIEW = "view";
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,18 @@ import org.apache.log4j.Logger;
|
||||||
*
|
*
|
||||||
* @version $Revision #1 $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision #1 $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
public class EditPostForm extends PostForm {
|
public class EditPostForm { // extends PostForm {
|
||||||
|
/*
|
||||||
|
|
||||||
|
REMOVED chris Gilbert
|
||||||
|
|
||||||
|
Edit step will be different depending whether post is root (category may be changed)
|
||||||
|
or reply (category cannot be changed)
|
||||||
|
|
||||||
|
UI refactored so that root post & reply to post forms are used for creation
|
||||||
|
and editing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static Logger s_log = Logger.getLogger(EditPostForm.class);
|
private static Logger s_log = Logger.getLogger(EditPostForm.class);
|
||||||
|
|
||||||
|
|
@ -102,5 +113,5 @@ public class EditPostForm extends PostForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,14 @@ class ForumAlertsView extends SimpleContainer implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component forumAlertsSegment() {
|
private Component forumAlertsSegment() {
|
||||||
SimpleContainer seg = new SimpleContainer("forum:forumAlerts",
|
SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":forumAlerts",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
seg.add(forumAlertsForm());
|
seg.add(forumAlertsForm());
|
||||||
return seg;
|
return seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component threadAlertsSegment() {
|
private Component threadAlertsSegment() {
|
||||||
SimpleContainer seg = new SimpleContainer("forum:threadAlerts",
|
SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":threadAlerts",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
seg.add(threadAlertsForm());
|
seg.add(threadAlertsForm());
|
||||||
return seg;
|
return seg;
|
||||||
|
|
|
||||||
|
|
@ -18,32 +18,36 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum.ui;
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
import java.io.IOException;
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.arsdigita.bebop.ModalContainer;
|
import com.arsdigita.bebop.ModalContainer;
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.forum.ui.admin.ModerationView;
|
||||||
|
import com.arsdigita.forum.ui.admin.PermissionsView;
|
||||||
|
import com.arsdigita.forum.ui.admin.SetupView;
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.kernel.security.UserContext;
|
import com.arsdigita.kernel.permissions.PermissionDescriptor;
|
||||||
import com.arsdigita.kernel.permissions.PermissionService;
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
import com.arsdigita.kernel.permissions.PermissionDescriptor;
|
import com.arsdigita.kernel.security.UserContext;
|
||||||
import com.arsdigita.forum.ui.admin.ModerationView;
|
|
||||||
import com.arsdigita.forum.Forum;
|
|
||||||
import com.arsdigita.forum.ForumContext;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bebop Page which provides the complete UI for the bboard application
|
* The Bebop Page which provides the complete UI for the bboard application
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision: #11 $ $Author: sskracic $ $Date: 2004/08/17 $
|
* @version $Revision: 1.3 $ $Author: chrisg23 $ $Date: 2006/03/09 13:48:15 $
|
||||||
*/
|
*/
|
||||||
public class ForumComponent extends ModalContainer implements Constants {
|
public class ForumComponent extends ModalContainer implements Constants {
|
||||||
|
|
||||||
|
|
@ -53,32 +57,39 @@ public class ForumComponent extends ModalContainer implements Constants {
|
||||||
public static final String MODE_TOPICS = "topics";
|
public static final String MODE_TOPICS = "topics";
|
||||||
public static final String MODE_ALERTS = "alerts";
|
public static final String MODE_ALERTS = "alerts";
|
||||||
public static final String MODE_MODERATION = "moderation";
|
public static final String MODE_MODERATION = "moderation";
|
||||||
|
public static final String MODE_PERMISSIONS = "permissions";
|
||||||
|
public static final String MODE_SETUP = "setup";
|
||||||
|
|
||||||
private StringParameter m_mode;
|
private StringParameter m_mode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the bboard use interface
|
* Constructs the bboard use interface
|
||||||
*/
|
*/
|
||||||
|
private SetupView m_setupView;
|
||||||
private ModerationView m_moderationView;
|
private ModerationView m_moderationView;
|
||||||
private ForumAlertsView m_alertsView;
|
private ForumAlertsView m_alertsView;
|
||||||
private CategoryView m_topicView;
|
private CategoryView m_topicView;
|
||||||
private ForumUserView m_userView;
|
private ForumUserView m_userView;
|
||||||
|
private PermissionsView m_permissionsView;
|
||||||
|
|
||||||
public ForumComponent() {
|
public ForumComponent() {
|
||||||
super("forum:forum", FORUM_XML_NS);
|
super(FORUM_XML_PREFIX + ":forum", FORUM_XML_NS);
|
||||||
|
|
||||||
m_mode = new StringParameter("mode");
|
m_mode = new StringParameter("mode");
|
||||||
|
|
||||||
|
m_setupView = new SetupView();
|
||||||
m_moderationView = new ModerationView();
|
m_moderationView = new ModerationView();
|
||||||
m_alertsView = new ForumAlertsView();
|
m_alertsView = new ForumAlertsView();
|
||||||
m_topicView = new CategoryView();
|
m_topicView = new CategoryView();
|
||||||
m_userView = new ForumUserView();
|
m_userView = new ForumUserView();
|
||||||
|
m_permissionsView = new PermissionsView();
|
||||||
|
|
||||||
|
add(m_setupView);
|
||||||
add(m_moderationView);
|
add(m_moderationView);
|
||||||
add(m_alertsView);
|
add(m_alertsView);
|
||||||
add(m_topicView);
|
add(m_topicView);
|
||||||
add(m_userView);
|
add(m_userView);
|
||||||
|
add(m_permissionsView);
|
||||||
|
|
||||||
setDefaultComponent(m_userView);
|
setDefaultComponent(m_userView);
|
||||||
}
|
}
|
||||||
|
|
@ -94,31 +105,56 @@ public class ForumComponent extends ModalContainer implements Constants {
|
||||||
|
|
||||||
super.respond(state);
|
super.respond(state);
|
||||||
|
|
||||||
|
Party party = Kernel.getContext().getParty();
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
|
||||||
String mode = (String)state.getControlEventValue();
|
String mode = (String)state.getControlEventValue();
|
||||||
state.setValue(m_mode, mode);
|
state.setValue(m_mode, mode);
|
||||||
|
|
||||||
|
setVisible(state, party, forum, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setVisible(
|
||||||
|
PageState state,
|
||||||
|
Party party,
|
||||||
|
Forum forum,
|
||||||
|
String mode) {
|
||||||
|
PermissionDescriptor forumAdmin =
|
||||||
|
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party);
|
||||||
|
|
||||||
if (MODE_TOPICS.equals(mode)) {
|
if (MODE_TOPICS.equals(mode)) {
|
||||||
|
if (Forum.getConfig().topicCreationByAdminOnly()) {
|
||||||
|
if (party == null) {
|
||||||
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
|
}
|
||||||
|
PermissionService.assertPermission(forumAdmin);
|
||||||
|
}
|
||||||
setVisibleComponent(state, m_topicView);
|
setVisibleComponent(state, m_topicView);
|
||||||
} else if (MODE_ALERTS.equals(mode)) {
|
} else if (MODE_ALERTS.equals(mode)) {
|
||||||
if (Kernel.getContext().getParty() == null) {
|
if (party == null) {
|
||||||
UserContext.redirectToLoginPage(state.getRequest());
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
}
|
}
|
||||||
setVisibleComponent(state, m_alertsView);
|
setVisibleComponent(state, m_alertsView);
|
||||||
} else if (MODE_MODERATION.equals(mode)) {
|
} else if (MODE_MODERATION.equals(mode)) {
|
||||||
Party party = Kernel.getContext().getParty();
|
|
||||||
if (party == null) {
|
if (party == null) {
|
||||||
UserContext.redirectToLoginPage(state.getRequest());
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
}
|
}
|
||||||
Forum forum = ForumContext.getContext(state).getForum();
|
PermissionService.assertPermission(forumAdmin);
|
||||||
|
|
||||||
PermissionDescriptor permission
|
|
||||||
= new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
|
|
||||||
forum,
|
|
||||||
party);
|
|
||||||
|
|
||||||
PermissionService.assertPermission(permission);
|
|
||||||
|
|
||||||
setVisibleComponent(state, m_moderationView);
|
setVisibleComponent(state, m_moderationView);
|
||||||
} else {
|
} else if (MODE_PERMISSIONS.equals(mode)) {
|
||||||
|
if (party == null) {
|
||||||
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
|
}
|
||||||
|
PermissionService.assertPermission(forumAdmin);
|
||||||
|
|
||||||
|
setVisibleComponent(state, m_permissionsView);
|
||||||
|
} else if (MODE_SETUP.equals(mode)) {
|
||||||
|
if (party == null) {
|
||||||
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
|
}
|
||||||
|
PermissionService.assertPermission(forumAdmin);
|
||||||
|
setVisibleComponent(state, m_setupView);
|
||||||
|
} else if (MODE_THREADS.equals(mode)) {
|
||||||
setVisibleComponent(state, m_userView);
|
setVisibleComponent(state, m_userView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,27 +162,45 @@ public class ForumComponent extends ModalContainer implements Constants {
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = generateParent(parent);
|
Element content = generateParent(parent);
|
||||||
|
|
||||||
generateModeXML(state, content, MODE_THREADS);
|
|
||||||
generateModeXML(state, content, MODE_TOPICS);
|
|
||||||
generateModeXML(state, content, MODE_ALERTS);
|
|
||||||
Forum forum = ForumContext.getContext(state).getForum();
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
content.addAttribute("title", forum.getTitle());
|
content.addAttribute("title", forum.getTitle());
|
||||||
content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).toString());
|
content.addAttribute(
|
||||||
|
"noticeboard",
|
||||||
|
(new Boolean(forum.isNoticeboard())).toString());
|
||||||
|
|
||||||
Party party = Kernel.getContext().getParty();
|
Party party = Kernel.getContext().getParty();
|
||||||
if (party != null) {
|
if (party == null) {
|
||||||
|
party = Kernel.getPublicUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
generateModes(state, content, party, forum);
|
||||||
|
generateChildrenXML(state, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void generateModes(
|
||||||
|
PageState state,
|
||||||
|
Element content,
|
||||||
|
Party party,
|
||||||
|
Forum forum) {
|
||||||
|
PermissionDescriptor permission =
|
||||||
|
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party);
|
||||||
|
|
||||||
|
generateModeXML(state, content, MODE_THREADS);
|
||||||
|
if (!Forum.getConfig().topicCreationByAdminOnly()) {
|
||||||
|
generateModeXML(state, content, MODE_TOPICS);
|
||||||
|
}
|
||||||
|
generateModeXML(state, content, MODE_ALERTS);
|
||||||
|
|
||||||
PermissionDescriptor permission
|
|
||||||
= new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
|
|
||||||
forum,
|
|
||||||
party);
|
|
||||||
if (PermissionService.checkPermission(permission)) {
|
if (PermissionService.checkPermission(permission)) {
|
||||||
generateModeXML(state, content, MODE_MODERATION);
|
generateModeXML(state, content, MODE_MODERATION);
|
||||||
|
if (Forum.getConfig().showNewTabs()) {
|
||||||
|
generateModeXML(state, content, MODE_SETUP);
|
||||||
|
generateModeXML(state, content, MODE_PERMISSIONS);
|
||||||
|
}
|
||||||
|
if (Forum.getConfig().topicCreationByAdminOnly()) {
|
||||||
|
generateModeXML(state, content, MODE_TOPICS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateChildrenXML(state, content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateModeXML(PageState state,
|
protected void generateModeXML(PageState state,
|
||||||
|
|
@ -157,7 +211,8 @@ public class ForumComponent extends ModalContainer implements Constants {
|
||||||
current = MODE_THREADS;
|
current = MODE_THREADS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element content = parent.newChildElement("forum:forumMode", FORUM_XML_NS);
|
Element content =
|
||||||
|
parent.newChildElement(FORUM_XML_PREFIX + ":forumMode", FORUM_XML_NS);
|
||||||
|
|
||||||
state.setControlEvent(this, "mode", mode);
|
state.setControlEvent(this, "mode", mode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
forum.ui.name=Name
|
forum.ui.name=Name
|
||||||
forum.ui.description=Description
|
forum.ui.description=Description
|
||||||
|
forum.ui.cancel=Cancel
|
||||||
|
|
||||||
forum.ui.newTopic=New topic
|
forum.ui.newTopic=New topic
|
||||||
forum.ui.topic.none=None
|
forum.ui.topic.none=None
|
||||||
|
|
@ -11,7 +12,7 @@ forum.ui.newPost=New thread
|
||||||
forum.ui.threads.viewAll=View all threads
|
forum.ui.threads.viewAll=View all threads
|
||||||
forum.ui.thread.subscribe=Subscribe to thread
|
forum.ui.thread.subscribe=Subscribe to thread
|
||||||
forum.ui.thread.unsubscribe=Unsubscribe to thread
|
forum.ui.thread.unsubscribe=Unsubscribe to thread
|
||||||
|
forum.ui.topic.save=Create Topic
|
||||||
|
|
||||||
forum.ui.moderate.label=Moderation:
|
forum.ui.moderate.label=Moderation:
|
||||||
forum.ui.moderate.switch.on=Turn on
|
forum.ui.moderate.switch.on=Turn on
|
||||||
|
|
@ -27,3 +28,26 @@ forum.ui.noticeboard.status.on=On (replying disabled)
|
||||||
forum.ui.noticeboard.status.off=Off (replying enabled)
|
forum.ui.noticeboard.status.off=Off (replying enabled)
|
||||||
forum.ui.noticeboard.expiry_after=Expires after (in days)
|
forum.ui.noticeboard.expiry_after=Expires after (in days)
|
||||||
forum.ui.noticeboard.change_expiry=Update
|
forum.ui.noticeboard.change_expiry=Update
|
||||||
|
|
||||||
|
forum.ui.settings.moderated=Moderated
|
||||||
|
forum.ui.settings.noticeboard=Noticeboard (Disable Replying)
|
||||||
|
forum.ui.settings.allowFiles=Allow File Attachments
|
||||||
|
forum.ui.settings.allowImages=Allow images in posts
|
||||||
|
forum.ui.settings.autosubscribe=Automatically subscribe thread starters
|
||||||
|
forum.ui.settings.noCategoryPosts=Allow posts with no topic
|
||||||
|
forum.ui.settings.anonymousPosts=Allow anonymous posts
|
||||||
|
forum.ui.settings.save=Save Changes
|
||||||
|
forum.ui.settings.introduction=Introduction
|
||||||
|
forum.ui.settings.title=Forum Title
|
||||||
|
|
||||||
|
forum.ui.validation.subject_null=Please enter a subject
|
||||||
|
forum.ui.validation.body_null=Please enter a message
|
||||||
|
forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored
|
||||||
|
forum.ui.validation.image_file_null=Please use the browse button above to find an image to add
|
||||||
|
forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image)
|
||||||
|
forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored
|
||||||
|
forum.ui.validation.file_null=Please use the browse button above to find a file to add
|
||||||
|
forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored
|
||||||
|
forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous.
|
||||||
|
forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous.
|
||||||
|
forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,13 @@ import com.arsdigita.bebop.ToggleLink;
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
import com.arsdigita.bebop.event.ActionEvent;
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
import com.arsdigita.bebop.event.ActionListener;
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
import com.arsdigita.forum.ForumContext;
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.kernel.permissions.PermissionDescriptor;
|
||||||
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
|
import com.arsdigita.toolbox.ui.SecurityContainer;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
@ -39,7 +45,7 @@ import org.apache.log4j.Logger;
|
||||||
*
|
*
|
||||||
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
* @author Kevin Scaldeferri (kevin@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision: #8 $ $Author: sskracic $ $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision: 1.8 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
|
||||||
*/
|
*/
|
||||||
public class ForumUserView extends SimpleContainer
|
public class ForumUserView extends SimpleContainer
|
||||||
implements Constants {
|
implements Constants {
|
||||||
|
|
@ -47,7 +53,7 @@ public class ForumUserView extends SimpleContainer
|
||||||
private static Logger s_log = Logger.getLogger(ForumUserView.class);
|
private static Logger s_log = Logger.getLogger(ForumUserView.class);
|
||||||
|
|
||||||
private Component m_forumView;
|
private Component m_forumView;
|
||||||
private Component m_forumPost;
|
private PostForm m_forumPost;
|
||||||
|
|
||||||
private ModalContainer m_mode;
|
private ModalContainer m_mode;
|
||||||
|
|
||||||
|
|
@ -78,6 +84,7 @@ public class ForumUserView extends SimpleContainer
|
||||||
*/
|
*/
|
||||||
p.addActionListener( new ActionListener() {
|
p.addActionListener( new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
s_log.debug("create link pressed");
|
||||||
PageState s = e.getPageState();
|
PageState s = e.getPageState();
|
||||||
/*
|
/*
|
||||||
if ("t".equals((String)s.getValue(m_newPostParam))) {
|
if ("t".equals((String)s.getValue(m_newPostParam))) {
|
||||||
|
|
@ -87,6 +94,7 @@ public class ForumUserView extends SimpleContainer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (m_newTopicLink.isSelected(s)) {
|
if (m_newTopicLink.isSelected(s)) {
|
||||||
|
m_forumPost.setContext(s, PostForm.NEW_CONTEXT);
|
||||||
m_mode.setVisibleComponent(s, m_forumPost);
|
m_mode.setVisibleComponent(s, m_forumPost);
|
||||||
} else {
|
} else {
|
||||||
m_mode.setVisibleComponent(s, m_forumView);
|
m_mode.setVisibleComponent(s, m_forumView);
|
||||||
|
|
@ -106,10 +114,21 @@ public class ForumUserView extends SimpleContainer
|
||||||
Container forums = new SimpleContainer();
|
Container forums = new SimpleContainer();
|
||||||
|
|
||||||
Container forumOptions = new SimpleContainer(
|
Container forumOptions = new SimpleContainer(
|
||||||
"forum:forumOptions", Constants.FORUM_XML_NS);
|
FORUM_XML_PREFIX + ":forumOptions", Constants.FORUM_XML_NS);
|
||||||
m_newTopicLink = new ToggleLink(new Label(Text.gz("forum.ui.newPost")));
|
m_newTopicLink = new ToggleLink(new Label(Text.gz("forum.ui.newPost")));
|
||||||
m_newTopicLink.setClassAttr("actionLink");
|
m_newTopicLink.setClassAttr("actionLink");
|
||||||
forumOptions.add(m_newTopicLink);
|
// chris.gilbert@westsussex.gov.uk - security container added
|
||||||
|
SecurityContainer sc = new SecurityContainer(m_newTopicLink) {
|
||||||
|
|
||||||
|
protected boolean canAccess(Party party, PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
PermissionDescriptor createThread = new PermissionDescriptor(PrivilegeDescriptor.get(Forum.CREATE_THREAD_PRIVILEGE), forum, party);
|
||||||
|
return PermissionService.checkPermission(createThread);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
forumOptions.add(sc);
|
||||||
forums.add(forumOptions);
|
forums.add(forumOptions);
|
||||||
|
|
||||||
// list of categories
|
// list of categories
|
||||||
|
|
@ -124,8 +143,8 @@ public class ForumUserView extends SimpleContainer
|
||||||
return forums;
|
return forums;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component createForumPost() {
|
private PostForm createForumPost() {
|
||||||
Form editForm = new NewPostForm();
|
PostForm editForm = new RootPostForm();
|
||||||
editForm.addCompletionListener(new ActionListener() {
|
editForm.addCompletionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
ForumUserView.this
|
ForumUserView.this
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,349 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.FormData;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
|
import com.arsdigita.bebop.FormStep;
|
||||||
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.RequestLocal;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.event.FormValidationListener;
|
||||||
|
import com.arsdigita.bebop.event.ParameterEvent;
|
||||||
|
import com.arsdigita.bebop.form.FileUpload;
|
||||||
|
import com.arsdigita.bebop.form.Submit;
|
||||||
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
|
import com.arsdigita.bebop.parameters.ArrayParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.FileSizeValidationListener;
|
||||||
|
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
|
import com.arsdigita.bebop.parameters.StringInRangeValidationListener;
|
||||||
|
import com.arsdigita.dispatcher.MultipartHttpServletRequest;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.PostImageAttachment;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.mimetypes.MimeType;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* Wizard step for adding images, and displaying list of images
|
||||||
|
* already added
|
||||||
|
*/
|
||||||
|
public class ImagesStep
|
||||||
|
extends FormStep
|
||||||
|
implements Constants, FormProcessListener, FormValidationListener, FormInitListener {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(ImagesStep.class);
|
||||||
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
private ImagesTable m_images;
|
||||||
|
private FileUpload m_upload;
|
||||||
|
private TextArea m_description;
|
||||||
|
private Submit m_addImage;
|
||||||
|
|
||||||
|
private PostForm m_container;
|
||||||
|
private ArrayParameter m_newImages = new ArrayParameter("images");
|
||||||
|
private ArrayParameter m_existingImages = new ArrayParameter("oldImages");
|
||||||
|
|
||||||
|
public ImagesStep(ACSObjectSelectionModel post, PostForm container) {
|
||||||
|
super(
|
||||||
|
"postImages",
|
||||||
|
new SimpleContainer(
|
||||||
|
FORUM_XML_PREFIX + ":postFormImages",
|
||||||
|
FORUM_XML_NS));
|
||||||
|
|
||||||
|
m_post = post;
|
||||||
|
m_container = container;
|
||||||
|
m_images = new ImagesTable(m_newImages, m_existingImages, this);
|
||||||
|
|
||||||
|
add(m_images);
|
||||||
|
|
||||||
|
m_upload = new FileUpload("image", true);
|
||||||
|
m_upload
|
||||||
|
.addValidationListener(new NotEmptyValidationListener(
|
||||||
|
Text
|
||||||
|
.gz("forum.ui.validation.image_file_null")) {
|
||||||
|
public void validate(ParameterEvent e) {
|
||||||
|
if (m_addImage.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_upload
|
||||||
|
.addValidationListener(new FileSizeValidationListener(
|
||||||
|
Forum
|
||||||
|
.getConfig()
|
||||||
|
.getMaxImageSize()) {
|
||||||
|
public void validate(ParameterEvent e) {
|
||||||
|
if (m_addImage.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(m_upload);
|
||||||
|
m_description = new TextArea("imageDescription");
|
||||||
|
m_description.setCols(20);
|
||||||
|
m_description.setRows(5);
|
||||||
|
m_description
|
||||||
|
.addValidationListener(new NotEmptyValidationListener(
|
||||||
|
Text
|
||||||
|
.gz("forum.ui.validation.image_description_null")) {
|
||||||
|
public void validate(ParameterEvent e) {
|
||||||
|
if (m_addImage.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_description
|
||||||
|
.addValidationListener(new StringInRangeValidationListener(
|
||||||
|
0,
|
||||||
|
4000,
|
||||||
|
Text.gz("forum.ui.validation.image_description_too_long")) {
|
||||||
|
public void validate(ParameterEvent e)
|
||||||
|
throws FormProcessException {
|
||||||
|
if (m_addImage.isSelected(e.getPageState())) {
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add(m_description);
|
||||||
|
m_addImage = new Submit("Add Image");
|
||||||
|
add(m_addImage);
|
||||||
|
addInitListener(this);
|
||||||
|
|
||||||
|
addProcessListener(this);
|
||||||
|
addValidationListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(FormSectionEvent e) throws FormProcessException {
|
||||||
|
s_log.debug("process event fired");
|
||||||
|
FormData data = e.getFormData();
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (m_addImage.isSelected(state)) {
|
||||||
|
PostImageAttachment a;
|
||||||
|
s_log.debug("adding file");
|
||||||
|
try {
|
||||||
|
String fileName = (String) m_upload.getValue(state);
|
||||||
|
s_log.debug("filename is " + fileName);
|
||||||
|
File file =
|
||||||
|
(
|
||||||
|
(MultipartHttpServletRequest) e
|
||||||
|
.getPageState()
|
||||||
|
.getRequest())
|
||||||
|
.getFile(
|
||||||
|
m_upload.getName());
|
||||||
|
|
||||||
|
s_log.debug("uploaded file is " + file.getName());
|
||||||
|
MimeType mimeType = MimeType.guessMimeTypeFromFile(fileName);
|
||||||
|
s_log.debug(
|
||||||
|
"Upload mime type is instance of " + mimeType.getClass());
|
||||||
|
s_log.debug(
|
||||||
|
"mime type is "
|
||||||
|
+ (mimeType == null ? null : mimeType.getMimeType()));
|
||||||
|
a = new PostImageAttachment();
|
||||||
|
a.loadFromFile(fileName, file, null);
|
||||||
|
a.setDescription((String) m_description.getValue(state));
|
||||||
|
a.setMimeType(mimeType);
|
||||||
|
BigDecimal id = a.getID();
|
||||||
|
String[] current = (String[]) state.getValue(m_newImages);
|
||||||
|
if (current == null) {
|
||||||
|
current = new String[] { id.toString()};
|
||||||
|
} else {
|
||||||
|
List images = Arrays.asList(current);
|
||||||
|
current = new String[images.size() + 1];
|
||||||
|
Iterator it = images.iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
current[i++] = (String) it.next();
|
||||||
|
}
|
||||||
|
current[i] = id.toString();
|
||||||
|
}
|
||||||
|
state.setValue(m_newImages, current);
|
||||||
|
s_log.debug("File Uploaded");
|
||||||
|
|
||||||
|
m_description.setValue(state, null);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new FormProcessException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent users navigating away from this page unintentionally without
|
||||||
|
* adding an uploaded image first
|
||||||
|
*/
|
||||||
|
public void validate(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (!m_addImage.isSelected(state)
|
||||||
|
&& StringUtils.isNotBlank((String) m_upload.getValue(state))) {
|
||||||
|
throw new FormProcessException(
|
||||||
|
(String) Text
|
||||||
|
.gz("forum.ui.validation.image_not_uploaded")
|
||||||
|
.localize());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param post
|
||||||
|
* @param state
|
||||||
|
*/
|
||||||
|
public void attachImages(Post post, PageState state) {
|
||||||
|
List newImages = Collections.EMPTY_LIST;
|
||||||
|
String[] newImagesArray = (String[]) state.getValue(m_newImages);
|
||||||
|
if (newImagesArray != null) {
|
||||||
|
newImages = new ArrayList(Arrays.asList(newImagesArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] existing = (String[]) state.getValue(m_existingImages);
|
||||||
|
if (existing != null) {
|
||||||
|
|
||||||
|
for (int i = 0; i < existing.length; i++) {
|
||||||
|
if (newImages.contains(existing[i])) {
|
||||||
|
// no change to this one
|
||||||
|
newImages.remove(existing[i]);
|
||||||
|
} else {
|
||||||
|
// file has been deleted in edit
|
||||||
|
PostImageAttachment image =
|
||||||
|
new PostImageAttachment(new BigDecimal(existing[i]));
|
||||||
|
post.removeImage(image);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iterator it = newImages.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
// new files added
|
||||||
|
PostImageAttachment image =
|
||||||
|
new PostImageAttachment(new BigDecimal((String) it.next()));
|
||||||
|
post.addImage(image);
|
||||||
|
}
|
||||||
|
state.setValue(m_newImages, null);
|
||||||
|
state.setValue(m_existingImages, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(Page p) {
|
||||||
|
super.register(p);
|
||||||
|
|
||||||
|
p.addGlobalStateParam(m_existingImages);
|
||||||
|
p.addGlobalStateParam(m_newImages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
if (m_container
|
||||||
|
.getContext(state)
|
||||||
|
.equals(PostForm.EDIT_CONTEXT)) {
|
||||||
|
Post editPost = (Post) m_post.getSelectedObject(state);
|
||||||
|
DataAssociationCursor files = editPost.getImages();
|
||||||
|
if (files.size() > 0) {
|
||||||
|
|
||||||
|
String[] fileIDs =
|
||||||
|
new String[new Long(files.size()).intValue()];
|
||||||
|
int i = 0;
|
||||||
|
while (files.next()) {
|
||||||
|
|
||||||
|
PostImageAttachment image =
|
||||||
|
(PostImageAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
fileIDs[i++] = image.getID().toString();
|
||||||
|
}
|
||||||
|
state.setValue(m_existingImages, fileIDs);
|
||||||
|
state.setValue(m_newImages, fileIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataCollection getCurrentImages(PageState state) {
|
||||||
|
|
||||||
|
String[] currentArray = (String[]) state.getValue(m_newImages);
|
||||||
|
if (currentArray != null && currentArray.length != 0) {
|
||||||
|
List current =
|
||||||
|
Arrays.asList((String[]) state.getValue(m_newImages));
|
||||||
|
|
||||||
|
DataCollection images =
|
||||||
|
SessionManager.getSession().retrieve(
|
||||||
|
PostImageAttachment.BASE_DATA_OBJECT_TYPE);
|
||||||
|
images.addFilter("id in :files").set("files", current);
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate xml for the confirmation step (unfortunately we can't just
|
||||||
|
* traverse the post because it hasn't been created at this point)
|
||||||
|
* @param state
|
||||||
|
* @param p
|
||||||
|
*/
|
||||||
|
public void generatePostXML(PageState state, Element p) {
|
||||||
|
DataCollection files = getCurrentImages(state);
|
||||||
|
if (files == null) {
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (files.next()) {
|
||||||
|
PostImageAttachment image =
|
||||||
|
(PostImageAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
DomainObjectXMLRenderer xr =
|
||||||
|
new DomainObjectXMLRenderer(p.newChildElement("images"));
|
||||||
|
xr.setWrapRoot(false);
|
||||||
|
xr.setWrapAttributes(true);
|
||||||
|
xr.setWrapObjects(false);
|
||||||
|
xr.walk(image, ConfirmStep.class.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void clearParameters (PageState state) {
|
||||||
|
state.setValue(m_existingImages, null);
|
||||||
|
state.setValue(m_newImages, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ControlLink;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
|
import com.arsdigita.bebop.parameters.ArrayParameter;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.cms.FileAsset;
|
||||||
|
import com.arsdigita.cms.dispatcher.Utilities;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.PostFileAttachment;
|
||||||
|
import com.arsdigita.forum.PostImageAttachment;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.messaging.MessagePart;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic table with delete link. This could be extended to provide
|
||||||
|
* additional links eg move up/move down
|
||||||
|
*
|
||||||
|
* @author Chris Gilbert <a href="mailto:chris.gilbert@westsussex.gov.uk">chris.gilbert@westsussex.gov.uk</a>
|
||||||
|
* @version $Revision: 1.4 $ $DateTime: 2004/08/17 23:15:09 $
|
||||||
|
**/
|
||||||
|
public class ImagesTable extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
|
// I have not implemented an edit link or a move up/down link although the data model
|
||||||
|
// is able to manage this, it seemed like a lot of work for a minor requirement for a forum
|
||||||
|
// currently, files are listed in the order they are added.
|
||||||
|
|
||||||
|
// to add extra links, define new keys for the control event and check key value in the
|
||||||
|
// respond method (see ThreadDisplay for example code)
|
||||||
|
//
|
||||||
|
// only issue is that when editing a post, the editor cannot change the description easily
|
||||||
|
// (though they could download the file to their PC, delete the existing one and recreate it)
|
||||||
|
private static Logger s_log = Logger.getLogger(ImagesTable.class);
|
||||||
|
protected static final String ACTION_DELETE = "delete";
|
||||||
|
|
||||||
|
private ArrayParameter m_newImages;
|
||||||
|
// ie when post is being edited
|
||||||
|
private ArrayParameter m_existingImages;
|
||||||
|
|
||||||
|
private ImagesStep m_parent;
|
||||||
|
|
||||||
|
public ImagesTable(
|
||||||
|
ArrayParameter newImages,
|
||||||
|
ArrayParameter existingImages,
|
||||||
|
ImagesStep parent) {
|
||||||
|
m_newImages = newImages;
|
||||||
|
m_existingImages = existingImages;
|
||||||
|
m_parent = parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if image has been added during this session then delete it completely.
|
||||||
|
* If we are editing a post and we delete an image that was in the original
|
||||||
|
* post then just flag the image as deleted in case the editing is cancelled
|
||||||
|
*/
|
||||||
|
public void respond(PageState state) throws ServletException {
|
||||||
|
super.respond(state);
|
||||||
|
|
||||||
|
String key = state.getControlEventName();
|
||||||
|
String value = state.getControlEventValue();
|
||||||
|
|
||||||
|
if (ACTION_DELETE.equals(key)) {
|
||||||
|
List existing = Collections.EMPTY_LIST;
|
||||||
|
String[] existingArray =
|
||||||
|
(String[]) state.getValue(m_existingImages);
|
||||||
|
if (existingArray != null) {
|
||||||
|
existing = Arrays.asList(existingArray);
|
||||||
|
}
|
||||||
|
if (!existing.contains(value)) {
|
||||||
|
// this has been added during edit
|
||||||
|
OID oid =
|
||||||
|
new OID(
|
||||||
|
PostImageAttachment.BASE_DATA_OBJECT_TYPE,
|
||||||
|
new BigDecimal(value));
|
||||||
|
|
||||||
|
DomainObjectFactory.newInstance(oid).delete();
|
||||||
|
}
|
||||||
|
List newImages =
|
||||||
|
new ArrayList(
|
||||||
|
Arrays.asList((String[]) state.getValue(m_newImages)));
|
||||||
|
newImages.remove(value);
|
||||||
|
String[] current = new String[newImages.size()];
|
||||||
|
Iterator it = newImages.iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
current[i++] = (String) it.next();
|
||||||
|
}
|
||||||
|
state.setValue(m_newImages, current);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void generateXML(PageState state, Element p) {
|
||||||
|
Element mainElement =
|
||||||
|
p.newChildElement(
|
||||||
|
FORUM_XML_PREFIX + ":attachedImages",
|
||||||
|
FORUM_XML_NS);
|
||||||
|
DataCollection images = m_parent.getCurrentImages(state);
|
||||||
|
if (images == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (images.next()) {
|
||||||
|
|
||||||
|
PostImageAttachment image =
|
||||||
|
(PostImageAttachment) DomainObjectFactory.newInstance(
|
||||||
|
images.getDataObject());
|
||||||
|
Element imageElement =
|
||||||
|
mainElement.newChildElement(
|
||||||
|
FORUM_XML_PREFIX + ":image",
|
||||||
|
FORUM_XML_NS);
|
||||||
|
imageElement.addAttribute("name", image.getName());
|
||||||
|
imageElement.addAttribute("src", Utilities.getAssetURL(image));
|
||||||
|
imageElement.addAttribute("caption", image.getDescription());
|
||||||
|
generateActionXML(state, imageElement, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateActionXML(
|
||||||
|
PageState state,
|
||||||
|
Element parent,
|
||||||
|
PostImageAttachment image) {
|
||||||
|
//separate method so that if future links require some logic
|
||||||
|
//to decide whether to display, it can be implemented here
|
||||||
|
parent.addAttribute("deleteLink", makeURL(state, ACTION_DELETE, image));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String makeURL(
|
||||||
|
PageState state,
|
||||||
|
String action,
|
||||||
|
PostImageAttachment image) {
|
||||||
|
state.setControlEvent(this, action, image.getID().toString());
|
||||||
|
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
url = state.stateAsURL();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new UncheckedWrapperException("cannot create url", ex);
|
||||||
|
}
|
||||||
|
state.clearControlEvent();
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
import com.arsdigita.forum.Post;
|
import com.arsdigita.forum.Post;
|
||||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.messaging.Message;
|
||||||
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
|
@ -33,12 +34,14 @@ import org.apache.log4j.Logger;
|
||||||
class MessageView extends SimpleComponent implements Constants {
|
class MessageView extends SimpleComponent implements Constants {
|
||||||
private static final Logger s_log = Logger.getLogger(MessageView.class);
|
private static final Logger s_log = Logger.getLogger(MessageView.class);
|
||||||
|
|
||||||
|
private ReplyToPostForm m_container;
|
||||||
private ACSObjectSelectionModel m_postModel;
|
private ACSObjectSelectionModel m_postModel;
|
||||||
private Post m_post;
|
private Post m_post;
|
||||||
|
|
||||||
/** For dynamically selected message views */
|
/** For dynamically selected message views */
|
||||||
public MessageView(ACSObjectSelectionModel postModel) {
|
public MessageView(ACSObjectSelectionModel postModel, ReplyToPostForm container) {
|
||||||
m_postModel = postModel;
|
m_postModel = postModel;
|
||||||
|
m_container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageView(Post post) {
|
public MessageView(Post post) {
|
||||||
|
|
@ -55,12 +58,18 @@ class MessageView extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Post post = m_post;
|
Message post = m_post;
|
||||||
if (m_post == null) {
|
if (m_post == null) {
|
||||||
post = (Post)m_postModel.getSelectedObject(state);
|
post = (Post)m_postModel.getSelectedObject(state);
|
||||||
}
|
}
|
||||||
|
if (m_container.getContext(state).equals(ReplyToPostForm.EDIT_CONTEXT)) {
|
||||||
|
// post in postmodel is the reply being edited, not the parent
|
||||||
|
post = post.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Element messageEl = parent.newChildElement("forum:message",
|
Element messageEl = parent.newChildElement(FORUM_XML_PREFIX + ":message",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
exportAttributes(messageEl);
|
exportAttributes(messageEl);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.forum.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
||||||
import com.arsdigita.categorization.Category;
|
|
||||||
import com.arsdigita.forum.ForumContext;
|
|
||||||
import com.arsdigita.forum.Post;
|
|
||||||
import com.arsdigita.forum.Forum;
|
|
||||||
import com.arsdigita.kernel.Kernel;
|
|
||||||
import com.arsdigita.web.RedirectSignal;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see com.arsdigita.forum.Post.java
|
|
||||||
* @see com.arsdigita.forum.EditPostForm.java
|
|
||||||
*/
|
|
||||||
|
|
||||||
class NewPostForm extends PostForm {
|
|
||||||
public static final String versionId =
|
|
||||||
"$Id: NewPostForm.java 755 2005-09-02 13:42:47Z sskracic $" +
|
|
||||||
"$Author: sskracic $" +
|
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(NewPostForm.class);
|
|
||||||
|
|
||||||
private CategoryWidget m_category;
|
|
||||||
|
|
||||||
public NewPostForm() {
|
|
||||||
super("newPostForm");
|
|
||||||
setupComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Container dataEntryStep() {
|
|
||||||
Container initial = super.dataEntryStep();
|
|
||||||
|
|
||||||
m_category = new CategoryWidget(new BigDecimalParameter("topic"));
|
|
||||||
initial.add(m_category);
|
|
||||||
|
|
||||||
return initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Post getPost(PageState state,
|
|
||||||
boolean create) {
|
|
||||||
if (!create) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Post post = Post.create(ForumContext.getContext(state).getForum());
|
|
||||||
post.setFrom(Kernel.getContext().getParty());
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initWidgets(PageState state,
|
|
||||||
Post post) {
|
|
||||||
super.initWidgets(state, post);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processWidgets(PageState state,
|
|
||||||
Post post) {
|
|
||||||
super.processWidgets(state,
|
|
||||||
post);
|
|
||||||
|
|
||||||
post.clearCategories();
|
|
||||||
BigDecimal categoryID = (BigDecimal)m_category.getValue(state);
|
|
||||||
if (categoryID != null &&
|
|
||||||
!categoryID.equals(Constants.TOPIC_NONE)) {
|
|
||||||
|
|
||||||
post.mapCategory(new Category(categoryID));
|
|
||||||
}
|
|
||||||
|
|
||||||
ForumContext ctx = ForumContext.getContext(state);
|
|
||||||
Forum forum = ctx.getForum();
|
|
||||||
if (forum.isModerated() &&
|
|
||||||
!ctx.canModerate()) {
|
|
||||||
post.setStatus(Post.PENDING);
|
|
||||||
} else {
|
|
||||||
post.setStatus(Post.APPROVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX we shouldn't have to save the post yet
|
|
||||||
// just to create a subscription :-(
|
|
||||||
post.save();
|
|
||||||
post.createThreadSubscription();
|
|
||||||
|
|
||||||
throw new RedirectSignal(URL.here(state.getRequest(), "/"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -18,10 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum.ui;
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Container;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.FormStep;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
import com.arsdigita.bebop.Wizard;
|
import com.arsdigita.bebop.Wizard;
|
||||||
|
|
@ -29,20 +29,17 @@ import com.arsdigita.bebop.event.FormCancelListener;
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
import com.arsdigita.bebop.event.FormSubmissionListener;
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
import com.arsdigita.forum.Post;
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.forum.ThreadSubscription;
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.User;
|
||||||
import com.arsdigita.kernel.security.UserContext;
|
import com.arsdigita.kernel.security.UserContext;
|
||||||
import com.arsdigita.toolbox.ui.TextTypeWidget;
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
import com.arsdigita.util.HtmlToText;
|
|
||||||
import com.arsdigita.util.MessageType;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PostForm
|
* Class PostForm
|
||||||
|
|
@ -50,150 +47,235 @@ import org.apache.log4j.Logger;
|
||||||
* @author Jon Orris (jorris@arsdigita.com)
|
* @author Jon Orris (jorris@arsdigita.com)
|
||||||
*
|
*
|
||||||
* @version $Revision #1 $DateTime: 2004/08/17 23:26:27 $
|
* @version $Revision #1 $DateTime: 2004/08/17 23:26:27 $
|
||||||
|
*
|
||||||
|
* rewritten Chris Gilbert.
|
||||||
|
*
|
||||||
|
* Abstract form for behaviour shared by all types of post. Different types of
|
||||||
|
* post (new or reply) have different text screens, retrieved using
|
||||||
|
* the abstract getTextStep method and also may behave
|
||||||
|
* differently in final processing (final meaning on the last step
|
||||||
|
* of the wizard) by overriding the processWidgets method.
|
||||||
|
*
|
||||||
|
* They all share the remainder of the steps (currently add files, add images and preview)
|
||||||
|
* and processing relating to shared behaviour
|
||||||
*/
|
*/
|
||||||
public abstract class PostForm extends Wizard implements Constants {
|
public abstract class PostForm extends Wizard implements Constants {
|
||||||
|
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: PostForm.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: PostForm.java 1628 2007-09-17 08:10:40Z chrisg23 $"
|
||||||
"$Author: sskracic $" +
|
+ "$Author: chrisg23 $"
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
+ "$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(PostForm.class);
|
private static final Logger s_log = Logger.getLogger(PostForm.class);
|
||||||
|
|
||||||
private TextField m_subject;
|
private PostTextStep m_textStep;
|
||||||
private TextArea m_body;
|
private ImagesStep m_attachImages;
|
||||||
private TextTypeWidget m_bodyType;
|
private AttachedFilesStep m_attachFiles;
|
||||||
|
private ConfirmStep m_confirm;
|
||||||
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* context is used because when editing, we might use the root post
|
||||||
|
* form (with topic selection) or the reply to post form (without
|
||||||
|
* topic selection). context allows form to behave appropriately
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private StringParameter m_context = new StringParameter("context");
|
||||||
|
|
||||||
|
public static final String NEW_CONTEXT = "new";
|
||||||
|
public static final String REPLY_CONTEXT = "reply";
|
||||||
|
public static final String EDIT_CONTEXT = "edit";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Form used for new thread - no existing post object
|
||||||
|
*
|
||||||
|
*/
|
||||||
public PostForm(String name) {
|
public PostForm(String name) {
|
||||||
super(name, new SimpleContainer());
|
this(name, null);
|
||||||
setMethod(POST);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupComponent() {
|
/**
|
||||||
add(dataEntryStep());
|
* Used when editing an existing post
|
||||||
add(confirmStep());
|
* @param name
|
||||||
|
* @param post
|
||||||
|
*/
|
||||||
|
public PostForm(String name, ACSObjectSelectionModel post) {
|
||||||
|
super(name, new SimpleContainer(), Forum.getConfig().quickFinishAllowed(), true);
|
||||||
|
// note that encoding must be multipart/form-data,and method must be post
|
||||||
|
// in order for attachments to be uploaded. Ensure that these properties
|
||||||
|
// are carried through in XSL if not simply applying the default bebop
|
||||||
|
// templates
|
||||||
|
setEncType("multipart/form-data");
|
||||||
|
setMethod(POST);
|
||||||
|
//setMethod(GET);
|
||||||
|
m_post = post;
|
||||||
|
|
||||||
addInitListener(new PostInitListener());
|
|
||||||
addProcessListener(new PostProcessListener());
|
|
||||||
addCancelListener(new PostCancelListener());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setSubject(PageState state,
|
public void setContext(PageState state, String context) {
|
||||||
String text) {
|
state.setValue(m_context, context);
|
||||||
m_subject.setValue(state, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Container dataEntryStep() {
|
public String getContext(PageState state) {
|
||||||
FormStep initial = new FormStep(
|
return (String) state.getValue(m_context);
|
||||||
"initial",
|
}
|
||||||
new SimpleContainer("forum:postForm", FORUM_XML_NS));
|
|
||||||
|
|
||||||
m_subject = new TextField(new StringParameter("subject"));
|
protected void setupComponent() {
|
||||||
m_subject.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
m_subject.addValidationListener(new StringLengthValidationListener(250));
|
|
||||||
m_subject.setSize(60);
|
|
||||||
initial.add(m_subject);
|
|
||||||
|
|
||||||
m_body = new TextArea(new StringParameter("message"),
|
m_textStep = getTextStep(m_post);
|
||||||
8, 60, TextArea.SOFT);
|
add(m_textStep);
|
||||||
m_body.addValidationListener(new NotEmptyValidationListener());
|
m_attachImages = new ImagesStep(m_post, this);
|
||||||
m_body.addValidationListener(new StringLengthValidationListener(4000));
|
add(m_attachImages);
|
||||||
initial.add(m_body);
|
m_attachFiles = new AttachedFilesStep(m_post, this);
|
||||||
|
add(m_attachFiles);
|
||||||
|
m_confirm = new ConfirmStep(m_post, this);
|
||||||
|
add(m_confirm);
|
||||||
|
|
||||||
m_bodyType = new TextTypeWidget(new StringParameter("bodyType"),
|
addInitListener(new PostInitListener());
|
||||||
MessageType.TEXT_PLAIN);
|
addCancelListener(new PostCancelListener());
|
||||||
initial.add(m_bodyType);
|
addSubmissionListener(new PostSubmissionListener());
|
||||||
|
addProcessListener(new PostProcessListener());
|
||||||
|
|
||||||
return initial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Container confirmStep() {
|
public void register(Page p) {
|
||||||
SimpleContainer postContainer = new SimpleContainer
|
super.register(p);
|
||||||
("forum:postConfirm", FORUM_XML_NS) {
|
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
p.addGlobalStateParam(m_context);
|
||||||
Element parent) {
|
|
||||||
Element content = generateParent(parent);
|
|
||||||
|
|
||||||
Element subject = content.newChildElement("subject");
|
|
||||||
subject.setText((String)m_subject.getValue(state));
|
|
||||||
|
|
||||||
Element body = content.newChildElement("body");
|
|
||||||
body.setText(HtmlToText.generateHTMLText(
|
|
||||||
(String)m_body.getValue(state),
|
|
||||||
(String)m_bodyType.getValue(state)));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return postContainer;
|
/**
|
||||||
}
|
* return text step appropriate for the type of post - reply doesn't give the option
|
||||||
|
* to choose a topic
|
||||||
|
* @param post
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected abstract PostTextStep getTextStep(ACSObjectSelectionModel m_post);
|
||||||
|
|
||||||
protected abstract Post getPost(PageState state,
|
/**
|
||||||
boolean create);
|
* potentially create a new post object (unless we are editing one) Subclasses
|
||||||
|
* should create a post in whatever way is appropriate (eg a reply form
|
||||||
protected void initWidgets(PageState state,
|
* will need to tie the new post to the one that is being replied to)
|
||||||
Post post) {
|
* @param state
|
||||||
if (post != null) {
|
* @return
|
||||||
m_subject.setValue(state, post.getSubject());
|
*/
|
||||||
m_body.setValue(state, post.getBody());
|
protected abstract Post getPost(PageState state);
|
||||||
m_bodyType.setValue(state, post.getBodyType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processWidgets(PageState state,
|
//
|
||||||
Post post) {
|
//
|
||||||
post.setSubject((String)m_subject.getValue(state));
|
// FORM EVENT LISTENERS. NOTE THAT INDIVIDUAL STEP LISTENERS ARE
|
||||||
post.setBody((String)m_body.getValue(state),
|
// NOTIFIED AFTER THE MAIN FORM LISTENERS - BE AWARE
|
||||||
(String)m_bodyType.getValue(state));
|
//
|
||||||
}
|
//
|
||||||
|
//
|
||||||
|
|
||||||
private class PostInitListener implements FormInitListener {
|
private class PostInitListener implements FormInitListener {
|
||||||
public void init(FormSectionEvent e) {
|
public void init(FormSectionEvent e) {
|
||||||
|
s_log.debug("init called on parent form");
|
||||||
PageState state = e.getPageState();
|
PageState state = e.getPageState();
|
||||||
|
|
||||||
if ( Kernel.getContext().getParty() == null ) {
|
if (Kernel.getContext().getParty() == null
|
||||||
|
&& !ForumContext
|
||||||
|
.getContext(state)
|
||||||
|
.getForum()
|
||||||
|
.anonymousPostsAllowed()) {
|
||||||
UserContext.redirectToLoginPage(state.getRequest());
|
UserContext.redirectToLoginPage(state.getRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
initWidgets(state,
|
|
||||||
getPost(state, false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private class PostSubmissionListener implements FormSubmissionListener {
|
||||||
|
|
||||||
private class PostProcessListener implements FormProcessListener {
|
/**
|
||||||
public void process(FormSectionEvent e)
|
* potentially skip steps of the wizard if the forum does not
|
||||||
throws FormProcessException {
|
* allow images or file attachments
|
||||||
|
*/
|
||||||
final PageState state = e.getPageState();
|
public void submitted(FormSectionEvent e) {
|
||||||
|
s_log.debug("page submitted");
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
|
Forum forum = ctx.getForum();
|
||||||
|
if (!forum.allowImageUploads()) {
|
||||||
|
hideStep(1, state);
|
||||||
|
}
|
||||||
|
if (!forum.allowFileAttachments()) {
|
||||||
|
hideStep(2, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Post post = getPost(state, true);
|
private class PostCancelListener implements FormCancelListener {
|
||||||
processWidgets(state, post);
|
public void cancel(FormSectionEvent e) throws FormProcessException {
|
||||||
|
|
||||||
post.sendNotifications();
|
PageState state = e.getPageState();
|
||||||
post.sendModeratorAlerts();
|
clearParameters(state);
|
||||||
|
fireCompletionEvent(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PostProcessListener implements FormProcessListener {
|
||||||
|
public void process(FormSectionEvent e) throws FormProcessException {
|
||||||
|
s_log.debug("process called on Parent Form");
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
Post post = getPost(state);
|
||||||
|
//m_post.setSelectedObject(state, post);
|
||||||
|
post.setStatus(state);
|
||||||
|
m_textStep.setText(post, state);
|
||||||
post.save();
|
post.save();
|
||||||
|
m_attachFiles.attachFiles(post, state);
|
||||||
|
m_attachImages.attachImages(post, state);
|
||||||
|
|
||||||
|
// sort out notifications
|
||||||
|
if (getContext(state).equals(NEW_CONTEXT)) {
|
||||||
|
s_log.debug("new thread - create subscription");
|
||||||
|
ThreadSubscription sub = post.createThreadSubscription();
|
||||||
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
|
Forum forum = ctx.getForum();
|
||||||
|
if (forum.autoSubscribeThreadStarter()) {
|
||||||
|
User threadStarter = (User) Kernel.getContext().getParty();
|
||||||
|
if (threadStarter != null
|
||||||
|
&& !threadStarter.equals(Kernel.getPublicUser())) {
|
||||||
|
s_log.debug("auto subscribing current user");
|
||||||
|
sub.subscribe(threadStarter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post.sendNotifications((String) state.getValue(m_context));
|
||||||
|
post.sendModeratorAlerts();
|
||||||
|
clearParameters(state);
|
||||||
fireCompletionEvent(state);
|
fireCompletionEvent(state);
|
||||||
/* XXX: This is the right thing to do, however it results in
|
|
||||||
the wizard not being reset. I haven't tracked down why.
|
|
||||||
|
|
||||||
state.clearControlEvent();
|
|
||||||
try {
|
|
||||||
throw new RedirectSignal( state.stateAsURL(), true );
|
|
||||||
} catch( IOException ex ) {
|
|
||||||
throw new UncheckedWrapperException( ex );
|
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Post getSelectedPost(PageState state) {
|
||||||
|
if (m_post == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (Post) m_post.getSelectedObject(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PostCancelListener implements FormCancelListener {
|
/**
|
||||||
public void cancel(FormSectionEvent e)
|
* required for confirmation step. Post hasn't been created so we
|
||||||
throws FormProcessException {
|
* cannot traverse a domain object. Instead, the form is responsible
|
||||||
|
* for retrieving a representation of the post as it will appear when saved
|
||||||
|
* @param state
|
||||||
|
* @param content
|
||||||
|
*/
|
||||||
|
protected void generatePostXML(PageState state, Element content) {
|
||||||
|
m_textStep.generatePostXML(state, content);
|
||||||
|
m_attachFiles.generatePostXML(state, content);
|
||||||
|
m_attachImages.generatePostXML(state, content);
|
||||||
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
fireCompletionEvent(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void clearParameters(PageState state) {
|
||||||
|
state.setValue(m_context, null);
|
||||||
|
m_attachImages.clearParameters(state);
|
||||||
|
m_attachFiles.clearParameters(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Bebop;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
|
import com.arsdigita.bebop.FormStep;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.form.DHTMLEditor;
|
||||||
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
|
import com.arsdigita.bebop.util.BebopConstants;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.User;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.toolbox.ui.TextTypeWidget;
|
||||||
|
import com.arsdigita.util.MessageType;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Gilbert <a href="mailto:chris.gilbert@westsussex.gov.uk">chris.gilbert@westsussex.gov.uk</a>
|
||||||
|
*
|
||||||
|
* Shared behaviour for text step
|
||||||
|
*/
|
||||||
|
public abstract class PostTextStep extends FormStep implements Constants {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(PostTextStep.class);
|
||||||
|
private PostForm m_container;
|
||||||
|
|
||||||
|
private static final String FCK_FORUM_CONFIG =
|
||||||
|
"/assets/fckeditor/config/fckconfig_forum.js";
|
||||||
|
private TextField m_subject;
|
||||||
|
private TextArea m_body;
|
||||||
|
|
||||||
|
private TextTypeWidget m_bodyType;
|
||||||
|
|
||||||
|
|
||||||
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a text step with title and message fields and message type selection list
|
||||||
|
* TO DO - add config parameter to conditionally replace latter 2 with a single FCKEditor instance
|
||||||
|
* @param post
|
||||||
|
* @param container
|
||||||
|
*/
|
||||||
|
public PostTextStep(ACSObjectSelectionModel post, PostForm container) {
|
||||||
|
super(
|
||||||
|
"postText",
|
||||||
|
new SimpleContainer(FORUM_XML_PREFIX + ":postForm", FORUM_XML_NS));
|
||||||
|
m_container = container;
|
||||||
|
m_post = post;
|
||||||
|
m_subject = new TextField(new StringParameter("subject"));
|
||||||
|
m_subject.addValidationListener(
|
||||||
|
new NotEmptyValidationListener(
|
||||||
|
Text.gz("forum.ui.validation.subject_null")));
|
||||||
|
m_subject.setMaxLength(250);
|
||||||
|
m_subject.setSize(60);
|
||||||
|
add(m_subject);
|
||||||
|
|
||||||
|
if (Forum.getConfig().useWysiwygEditor()) {
|
||||||
|
m_body = new DHTMLEditor("message");
|
||||||
|
m_body.setRows(8);
|
||||||
|
m_body.setCols(60);
|
||||||
|
m_body.setMetaDataAttribute("width", "450");
|
||||||
|
m_body.setMetaDataAttribute("height", "300");
|
||||||
|
m_body.setWrap(DHTMLEditor.SOFT);
|
||||||
|
if (Bebop
|
||||||
|
.getConfig()
|
||||||
|
.getDHTMLEditor()
|
||||||
|
.equals(BebopConstants.BEBOP_FCKEDITOR)) {
|
||||||
|
|
||||||
|
((DHTMLEditor) m_body).setConfig(
|
||||||
|
new DHTMLEditor.Config("forum", FCK_FORUM_CONFIG));
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// remove this so end users cannot browse through back end folder system
|
||||||
|
((DHTMLEditor) m_body).hideButton("insertlink");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_body = new TextArea(new StringParameter("message"),
|
||||||
|
8, 60, TextArea.SOFT);
|
||||||
|
}
|
||||||
|
// otherwise, standard HTMLArea config - may need to change this if anyone is still
|
||||||
|
// using html area
|
||||||
|
|
||||||
|
m_body.addValidationListener(
|
||||||
|
new NotEmptyValidationListener(
|
||||||
|
Text.gz("forum.ui.validation.body_null")));
|
||||||
|
|
||||||
|
add(m_body);
|
||||||
|
|
||||||
|
m_bodyType = new TextTypeWidget(new StringParameter("bodyType"),
|
||||||
|
MessageType.TEXT_PLAIN);
|
||||||
|
|
||||||
|
add(m_bodyType);
|
||||||
|
|
||||||
|
addInitListener(new InitTextStepListener());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allow subclasses to initialise subject field
|
||||||
|
* @param state
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
|
protected void setSubject(PageState state, String text) {
|
||||||
|
m_subject.setValue(state, text);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* allow subclasses to initialise message and message type fields
|
||||||
|
* @param state
|
||||||
|
* @param body
|
||||||
|
* @param bodyType
|
||||||
|
*/
|
||||||
|
protected void setBody(PageState state, String body, String bodyType) {
|
||||||
|
m_body.setValue(state, body);
|
||||||
|
m_bodyType.setValue(state, bodyType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initWidgets(PageState state, Post post) {
|
||||||
|
StringBuffer body = new StringBuffer();
|
||||||
|
if (m_container.getContext(state).equals(PostForm.EDIT_CONTEXT)) {
|
||||||
|
if (Forum.getConfig().useWysiwygEditor()) {
|
||||||
|
body.append("<p>\n<i>\n");
|
||||||
|
body.append(
|
||||||
|
"Edited on "
|
||||||
|
+ DateFormat.getDateInstance(DateFormat.SHORT).format(
|
||||||
|
new Date())
|
||||||
|
+ " by "
|
||||||
|
+ ((User) Kernel.getContext().getParty()).getName());
|
||||||
|
body.append("\n</i>\n</p>\n\n<br/>\n\n");
|
||||||
|
} else {
|
||||||
|
body.append("\n");
|
||||||
|
body.append(
|
||||||
|
"Edited on "
|
||||||
|
+ DateFormat.getDateInstance(DateFormat.SHORT).format(
|
||||||
|
new Date())
|
||||||
|
+ " by "
|
||||||
|
+ ((User) Kernel.getContext().getParty()).getName());
|
||||||
|
body.append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
body.append(post.getBody());
|
||||||
|
setSubject(state, post.getSubject());
|
||||||
|
setBody(state, body.toString(), post.getBodyType());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* If a delete link is used, the parameter that tells the wizard not to
|
||||||
|
* reinitialize steps is ALSO lost, and so init listeners are fired again
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class InitTextStepListener implements FormInitListener {
|
||||||
|
|
||||||
|
public void init(FormSectionEvent e) throws FormProcessException {
|
||||||
|
|
||||||
|
|
||||||
|
s_log.debug("Init called on Text Step");
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
|
||||||
|
if (Forum.getConfig().useWysiwygEditor()) {
|
||||||
|
m_bodyType.setValue(state, MessageType.TEXT_HTML);
|
||||||
|
m_bodyType.setVisible(state, false);
|
||||||
|
}
|
||||||
|
if (m_post != null) {
|
||||||
|
Post post = (Post) m_post.getSelectedObject(state);
|
||||||
|
initWidgets(state, post);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setText(Post post, PageState state) {
|
||||||
|
post.setSubject((String) m_subject.getValue(state));
|
||||||
|
|
||||||
|
post.setBody((String) m_body.getValue(state), (String) m_bodyType.getValue(state));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param state
|
||||||
|
* @param content
|
||||||
|
*/
|
||||||
|
public void generatePostXML(PageState state, Element content) {
|
||||||
|
Element subject = content.newChildElement("subject");
|
||||||
|
subject.setText((String) m_subject.getValue(state));
|
||||||
|
Element body = content.newChildElement("body");
|
||||||
|
body.setText((String) m_body.getValue(state));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,12 +19,17 @@
|
||||||
package com.arsdigita.forum.ui;
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Container;
|
import com.arsdigita.bebop.Container;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
import com.arsdigita.forum.Post;
|
import com.arsdigita.forum.Post;
|
||||||
import com.arsdigita.forum.ForumContext;
|
import com.arsdigita.forum.ForumContext;
|
||||||
import com.arsdigita.forum.Forum;
|
import com.arsdigita.forum.Forum;
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
@ -37,79 +42,51 @@ import org.apache.log4j.Logger;
|
||||||
*/
|
*/
|
||||||
public class ReplyToPostForm extends PostForm {
|
public class ReplyToPostForm extends PostForm {
|
||||||
public static final String versionId =
|
public static final String versionId =
|
||||||
"$Id: ReplyToPostForm.java 755 2005-09-02 13:42:47Z sskracic $" +
|
"$Id: ReplyToPostForm.java 1628 2007-09-17 08:10:40Z chrisg23 $"
|
||||||
"$Author: sskracic $" +
|
+ "$Author: chrisg23 $"
|
||||||
"$DateTime: 2004/08/17 23:26:27 $";
|
+ "$DateTime: 2004/08/17 23:26:27 $";
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger
|
private static final Logger s_log = Logger.getLogger(ReplyToPostForm.class);
|
||||||
(ReplyToPostForm.class);
|
|
||||||
|
|
||||||
|
|
||||||
private ACSObjectSelectionModel m_parent;
|
|
||||||
|
|
||||||
|
public ReplyToPostForm(ACSObjectSelectionModel post) {
|
||||||
public ReplyToPostForm(ACSObjectSelectionModel parent) {
|
super("replyPostForm", post);
|
||||||
super("replyPostForm");
|
|
||||||
m_parent = parent;
|
|
||||||
setupComponent();
|
setupComponent();
|
||||||
}
|
|
||||||
|
|
||||||
public void register(Page p) {
|
|
||||||
super.register(p);
|
|
||||||
|
|
||||||
p.addGlobalStateParam(m_parent.getStateParameter());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Post getPost(PageState state,
|
|
||||||
boolean create) {
|
|
||||||
if (create) {
|
|
||||||
Post post = (Post)((Post)m_parent.getSelectedObject(state)).replyTo();
|
|
||||||
post.setFrom(Kernel.getContext().getParty());
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Container dataEntryStep() {
|
|
||||||
Container entryStep = super.dataEntryStep();
|
|
||||||
MessageView replyTo = new MessageView(m_parent);
|
|
||||||
entryStep.add(replyTo);
|
|
||||||
|
|
||||||
return entryStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initWidgets(PageState state,
|
|
||||||
Post post) {
|
|
||||||
super.initWidgets(state, post);
|
|
||||||
|
|
||||||
Post parent = (Post)m_parent.getSelectedObject(state);
|
|
||||||
String prefix = "Re:";
|
|
||||||
String subject = parent.getSubject();
|
|
||||||
|
|
||||||
if (subject.length() < 3 ||
|
protected PostTextStep getTextStep(ACSObjectSelectionModel post) {
|
||||||
prefix.equalsIgnoreCase(subject.substring(0,3))) {
|
return new ReplyToPostTextStep(post, this);
|
||||||
setSubject(state, subject);
|
|
||||||
} else {
|
|
||||||
setSubject(state, prefix + " " + subject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void processWidgets(PageState state,
|
/* (non-Javadoc)
|
||||||
Post post) {
|
* @see com.arsdigita.forum.ui.PostForm#getPost(com.arsdigita.bebop.PageState)
|
||||||
super.processWidgets(state, post);
|
*/
|
||||||
|
protected Post getPost(PageState state) {
|
||||||
|
Post reply;
|
||||||
|
if (getContext(state).equals(PostForm.REPLY_CONTEXT)) {
|
||||||
|
// post model contains the parent post, reply hasn't been created yet
|
||||||
|
Post parent = getSelectedPost(state);
|
||||||
|
reply = (Post) parent.replyTo();
|
||||||
|
Party party = Kernel.getContext().getParty();
|
||||||
|
if (party == null) {
|
||||||
|
// anonymous posts MUST be allowed if we have reached here
|
||||||
|
party = Kernel.getPublicUser();
|
||||||
|
}
|
||||||
|
|
||||||
ForumContext ctx = ForumContext.getContext(state);
|
reply.setFrom(party);
|
||||||
Forum forum = ctx.getForum();
|
|
||||||
|
|
||||||
if (forum.isModerated() &&
|
|
||||||
!ctx.canModerate()) {
|
|
||||||
post.setStatus(Post.PENDING);
|
|
||||||
} else {
|
} else {
|
||||||
post.setStatus(Post.APPROVED);
|
// reply is the post in the post model
|
||||||
|
reply = getSelectedPost(state);
|
||||||
}
|
}
|
||||||
|
return reply;
|
||||||
|
|
||||||
post.setRefersTo(forum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
* reply to post text step automatically completes
|
||||||
|
* the subject field
|
||||||
|
*
|
||||||
|
* (nb other forums eg FirstClass allocate numbers to long
|
||||||
|
* chains of replies, so instead of having a tree with all
|
||||||
|
* posts having subject 're: original post' they have varied
|
||||||
|
* subjects 're:(2) original post'. If we wanted to implement
|
||||||
|
* similar, this is the place to do it
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ReplyToPostTextStep extends PostTextStep {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(ReplyToPostTextStep.class);
|
||||||
|
private ReplyToPostForm m_container;
|
||||||
|
|
||||||
|
public ReplyToPostTextStep(
|
||||||
|
ACSObjectSelectionModel post,
|
||||||
|
ReplyToPostForm container) {
|
||||||
|
super(post, container);
|
||||||
|
MessageView inReplyTo = new MessageView(post, container);
|
||||||
|
m_container = container;
|
||||||
|
add(inReplyTo);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initWidgets(PageState state, Post post) {
|
||||||
|
if (m_container.getContext(state).equals(ReplyToPostForm.EDIT_CONTEXT)) {
|
||||||
|
super.initWidgets(state, post);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
s_log.debug("init called");
|
||||||
|
s_log.debug("parent is " + post);
|
||||||
|
String prefix = "Re:";
|
||||||
|
String subject = post.getSubject();
|
||||||
|
|
||||||
|
if (subject.length() < 3
|
||||||
|
|| prefix.equalsIgnoreCase(subject.substring(0, 3))) {
|
||||||
|
setSubject(state, subject);
|
||||||
|
} else {
|
||||||
|
setSubject(state, prefix + " " + subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||||
|
import com.arsdigita.categorization.Category;
|
||||||
|
import com.arsdigita.categorization.CategoryCollection;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
*
|
||||||
|
* root post manages the category(topic) in
|
||||||
|
* addition to subject & body
|
||||||
|
*/
|
||||||
|
public class RootPostTextStep extends PostTextStep {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(RootPostTextStep.class);
|
||||||
|
private CategoryWidget m_category;
|
||||||
|
|
||||||
|
public RootPostTextStep(ACSObjectSelectionModel post, PostForm container) {
|
||||||
|
super(post, container);
|
||||||
|
|
||||||
|
m_category = new CategoryWidget(new BigDecimalParameter("postTopic"));
|
||||||
|
add(m_category);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(Post post, PageState state) {
|
||||||
|
super.setText(post, state);
|
||||||
|
post.clearCategories();
|
||||||
|
// need to save post after setting mandatory fields
|
||||||
|
// (subject, body, status) and before mapping categories
|
||||||
|
|
||||||
|
post.save();
|
||||||
|
BigDecimal categoryID = (BigDecimal) m_category.getValue(state);
|
||||||
|
if (categoryID != null && !categoryID.equals(Constants.TOPIC_NONE)) {
|
||||||
|
post.mapCategory(new Category(categoryID));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initWidgets(PageState state, Post post) {
|
||||||
|
super.initWidgets(state, post);
|
||||||
|
if (post != null) {
|
||||||
|
CategoryCollection categories = post.getCategories();
|
||||||
|
if (categories.next()) {
|
||||||
|
Category cat = categories.getCategory();
|
||||||
|
m_category.setValue(state, cat.getID());
|
||||||
|
} else {
|
||||||
|
m_category.setValue(state, Constants.TOPIC_NONE);
|
||||||
|
}
|
||||||
|
categories.close();
|
||||||
|
} else {
|
||||||
|
m_category.setValue(state, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -57,11 +57,11 @@ public class ThreadAlertsList extends SimpleComponent
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement(
|
Element content = parent.newChildElement(
|
||||||
"forum:threadAlertList", FORUM_XML_NS);
|
FORUM_XML_PREFIX + ":threadAlertList", FORUM_XML_NS);
|
||||||
exportAttributes(content);
|
exportAttributes(content);
|
||||||
|
|
||||||
DomainCollection subs = ThreadSubscription.
|
DomainCollection subs = ThreadSubscription.
|
||||||
getSubsForUser(Kernel.getContext().getParty());
|
getSubsForUser(Kernel.getContext().getParty(), state);
|
||||||
|
|
||||||
while (subs.next()) {
|
while (subs.next()) {
|
||||||
ThreadSubscription sub = (ThreadSubscription)subs.getDomainObject();
|
ThreadSubscription sub = (ThreadSubscription)subs.getDomainObject();
|
||||||
|
|
@ -73,7 +73,7 @@ public class ThreadAlertsList extends SimpleComponent
|
||||||
|
|
||||||
public Element generateAlertXML(ThreadSubscription sub) {
|
public Element generateAlertXML(ThreadSubscription sub) {
|
||||||
Element subEl = new Element(
|
Element subEl = new Element(
|
||||||
"forum:threadAlert", FORUM_XML_NS);
|
FORUM_XML_PREFIX + ":threadAlert", FORUM_XML_NS);
|
||||||
|
|
||||||
ParameterMap map = new ParameterMap();
|
ParameterMap map = new ParameterMap();
|
||||||
map.setParameter(THREAD_PARAM, sub.getThreadReal().getID());
|
map.setParameter(THREAD_PARAM, sub.getThreadReal().getID());
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
package com.arsdigita.forum.ui;
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.forum.ForumContext;
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.forum.Post;
|
||||||
import com.arsdigita.forum.ThreadSubscription;
|
import com.arsdigita.forum.ThreadSubscription;
|
||||||
import com.arsdigita.forum.ui.admin.RejectionForm;
|
import com.arsdigita.forum.ui.admin.RejectionForm;
|
||||||
|
|
||||||
|
|
@ -59,8 +60,8 @@ public class ThreadComponent extends ModalContainer implements Constants {
|
||||||
// References to sub-components for event access.
|
// References to sub-components for event access.
|
||||||
|
|
||||||
private Container m_threadView;
|
private Container m_threadView;
|
||||||
private Form m_editForm;
|
private PostForm m_rootForm;
|
||||||
private Form m_replyForm;
|
private PostForm m_replyForm;
|
||||||
private Form m_rejectForm;
|
private Form m_rejectForm;
|
||||||
|
|
||||||
private static final Logger s_log
|
private static final Logger s_log
|
||||||
|
|
@ -83,15 +84,18 @@ public class ThreadComponent extends ModalContainer implements Constants {
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
// Add the thread components to the modal container and maintain
|
// Add the thread components to the modal container and maintain
|
||||||
// references for event manipulation purposes.
|
// references for event manipulation purposes.
|
||||||
m_editForm = new EditPostForm(m_postModel);
|
s_log.debug("creating edit post form");
|
||||||
|
m_rootForm = new RootPostForm(m_postModel);
|
||||||
m_replyForm = new ReplyToPostForm(m_postModel);
|
m_replyForm = new ReplyToPostForm(m_postModel);
|
||||||
|
s_log.debug("creating reply to post form");
|
||||||
|
s_log.debug("creating reject form");
|
||||||
m_rejectForm = new RejectionForm(m_postModel);
|
m_rejectForm = new RejectionForm(m_postModel);
|
||||||
addForm(m_editForm);
|
addForm(m_rootForm);
|
||||||
addForm(m_replyForm);
|
addForm(m_replyForm);
|
||||||
addForm(m_rejectForm);
|
addForm(m_rejectForm);
|
||||||
|
|
||||||
m_threadView = new SimpleContainer();
|
m_threadView = new SimpleContainer();
|
||||||
Container linksPanel = new SimpleContainer("forum:threadOptions",
|
Container linksPanel = new SimpleContainer(FORUM_XML_PREFIX + ":threadOptions",
|
||||||
Constants.FORUM_XML_NS);
|
Constants.FORUM_XML_NS);
|
||||||
|
|
||||||
// Offer links to return to index or control alerts.
|
// Offer links to return to index or control alerts.
|
||||||
|
|
@ -119,11 +123,21 @@ public class ThreadComponent extends ModalContainer implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeEditFormVisible(PageState state) {
|
public void makeEditFormVisible(PageState state) {
|
||||||
setVisibleComponent(state, m_editForm);
|
s_log.debug("making edit form visible");
|
||||||
|
Post post = (Post)m_postModel.getSelectedObject(state);
|
||||||
|
if (post.getRoot() == null) {
|
||||||
|
m_rootForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT);
|
||||||
|
setVisibleComponent(state, m_rootForm);
|
||||||
|
} else {
|
||||||
|
m_replyForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT);
|
||||||
|
setVisibleComponent(state, m_replyForm);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeReplyFormVisible(PageState state) {
|
public void makeReplyFormVisible(PageState state) {
|
||||||
s_log.debug("making reply form invisible");
|
s_log.debug("making reply form visible");
|
||||||
|
m_replyForm.setContext(state, PostForm.REPLY_CONTEXT);
|
||||||
setVisibleComponent(state, m_replyForm);
|
setVisibleComponent(state, m_replyForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,12 +149,14 @@ public class ThreadComponent extends ModalContainer implements Constants {
|
||||||
* Creates the component for viewing a thread.
|
* Creates the component for viewing a thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private final void addForm(Form form) {
|
private final void addForm(final Form form) {
|
||||||
add(form);
|
add(form);
|
||||||
form.addCompletionListener(new ActionListener() {
|
form.addCompletionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
s_log.debug("FORM ACTION COMPLETED");
|
s_log.debug("FORM ACTION COMPLETED");
|
||||||
makeListViewVisible(e.getPageState());
|
PageState ps = e.getPageState();
|
||||||
|
// ps.reset(form);
|
||||||
|
makeListViewVisible(ps);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -148,7 +164,8 @@ public class ThreadComponent extends ModalContainer implements Constants {
|
||||||
public void cancel(FormSectionEvent e) {
|
public void cancel(FormSectionEvent e) {
|
||||||
s_log.debug("fire cancel listener");
|
s_log.debug("fire cancel listener");
|
||||||
PageState ps = e.getPageState();
|
PageState ps = e.getPageState();
|
||||||
makeListViewVisible(e.getPageState());
|
// ps.reset(form);
|
||||||
|
makeListViewVisible(ps);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,48 +18,44 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum.ui;
|
package com.arsdigita.forum.ui;
|
||||||
|
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
import java.io.IOException;
|
||||||
import com.arsdigita.bebop.parameters.IntegerParameter;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
|
import com.arsdigita.bebop.parameters.IntegerParameter;
|
||||||
import com.arsdigita.domain.DomainCollection;
|
import com.arsdigita.domain.DomainCollection;
|
||||||
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
||||||
import com.arsdigita.persistence.DataCollection;
|
import com.arsdigita.forum.Forum;
|
||||||
import com.arsdigita.persistence.FilterFactory;
|
import com.arsdigita.forum.ForumContext;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.forum.Post;
|
||||||
import com.arsdigita.persistence.OID;
|
|
||||||
|
|
||||||
import com.arsdigita.kernel.Party;
|
|
||||||
import com.arsdigita.kernel.Kernel;
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.kernel.permissions.PermissionDescriptor;
|
||||||
|
import com.arsdigita.kernel.permissions.PermissionService;
|
||||||
|
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
|
||||||
import com.arsdigita.messaging.MessageThread;
|
import com.arsdigita.messaging.MessageThread;
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.persistence.FilterFactory;
|
||||||
import com.arsdigita.web.Web;
|
import com.arsdigita.persistence.OID;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
import com.arsdigita.web.ParameterMap;
|
import com.arsdigita.web.ParameterMap;
|
||||||
import com.arsdigita.web.RedirectSignal;
|
import com.arsdigita.web.RedirectSignal;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
import com.arsdigita.web.Web;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
import com.arsdigita.xml.XML;
|
import com.arsdigita.xml.XML;
|
||||||
|
|
||||||
import com.arsdigita.forum.Forum;
|
|
||||||
import com.arsdigita.forum.Post;
|
|
||||||
import com.arsdigita.forum.ForumContext;
|
|
||||||
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
|
|
||||||
public class ThreadDisplay extends SimpleComponent implements Constants {
|
public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
private static final Logger s_log =
|
private static final Logger s_log =
|
||||||
|
|
@ -67,8 +63,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
private IntegerParameter m_pageNumber =
|
private IntegerParameter m_pageNumber =
|
||||||
new IntegerParameter(PAGINATOR_PARAM);
|
new IntegerParameter(PAGINATOR_PARAM);
|
||||||
|
private int m_pageSize = Forum.getConfig().getThreadPageSize();
|
||||||
private int m_pageSize = 10;
|
|
||||||
|
|
||||||
private static final String ACTION_EDIT = "edit";
|
private static final String ACTION_EDIT = "edit";
|
||||||
private static final String ACTION_DELETE = "delete";
|
private static final String ACTION_DELETE = "delete";
|
||||||
|
|
@ -152,7 +147,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
} else if (ACTION_APPROVE.equals(key)) {
|
} else if (ACTION_APPROVE.equals(key)) {
|
||||||
post.setStatus(Post.APPROVED);
|
post.setStatus(Post.APPROVED);
|
||||||
post.save();
|
post.save();
|
||||||
post.sendNotifications();
|
post.sendNotifications(null);
|
||||||
} else if (ACTION_REJECT.equals(key)) {
|
} else if (ACTION_REJECT.equals(key)) {
|
||||||
m_post.setSelectedObject(state, post);
|
m_post.setSelectedObject(state, post);
|
||||||
m_threadComponent.makeRejectFormVisible(state);
|
m_threadComponent.makeRejectFormVisible(state);
|
||||||
|
|
@ -208,7 +203,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement("forum:threadDisplay",
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":threadDisplay",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
exportAttributes(content);
|
exportAttributes(content);
|
||||||
|
|
||||||
|
|
@ -249,7 +244,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
while (messages.next()) {
|
while (messages.next()) {
|
||||||
Post message = (Post)messages.getDomainObject();
|
Post message = (Post)messages.getDomainObject();
|
||||||
Element messageEl = content.newChildElement("forum:message",
|
Element messageEl = content.newChildElement(FORUM_XML_PREFIX + ":message",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
|
|
||||||
generateActionXML(state, messageEl, message);
|
generateActionXML(state, messageEl, message);
|
||||||
|
|
@ -291,12 +286,17 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
|
|
||||||
Party party = Kernel.getContext().getParty();
|
Party party = Kernel.getContext().getParty();
|
||||||
|
if (party == null) {
|
||||||
|
party = Kernel.getPublicUser();
|
||||||
|
}
|
||||||
if (post.canEdit(party)) {
|
if (post.canEdit(party)) {
|
||||||
parent.addAttribute("editURL",
|
parent.addAttribute("editURL",
|
||||||
makeURL(state, ACTION_EDIT, post));
|
makeURL(state, ACTION_EDIT, post));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx.getForum().isNoticeboard()) {
|
PermissionDescriptor canRespond = new PermissionDescriptor(PrivilegeDescriptor.get(Forum.RESPOND_TO_THREAD_PRIVILEGE), Kernel.getContext().getResource(), party);
|
||||||
|
|
||||||
|
if (!ctx.getForum().isNoticeboard() && PermissionService.checkPermission(canRespond)) {
|
||||||
parent.addAttribute("replyURL",
|
parent.addAttribute("replyURL",
|
||||||
makeURL(state, ACTION_REPLY, post));
|
makeURL(state, ACTION_REPLY, post));
|
||||||
}
|
}
|
||||||
|
|
@ -325,7 +325,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants {
|
||||||
long begin,
|
long begin,
|
||||||
long end,
|
long end,
|
||||||
long objectCount) {
|
long objectCount) {
|
||||||
Element paginator = parent.newChildElement("forum:paginator", FORUM_XML_NS);
|
Element paginator = parent.newChildElement(FORUM_XML_PREFIX + ":paginator", FORUM_XML_NS);
|
||||||
|
|
||||||
URL here = Web.getContext().getRequestURL();
|
URL here = Web.getContext().getRequestURL();
|
||||||
ParameterMap params = new ParameterMap(here.getParameterMap());
|
ParameterMap params = new ParameterMap(here.getParameterMap());
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public class ThreadList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement("forum:threadList", FORUM_XML_NS);
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":threadList", FORUM_XML_NS);
|
||||||
|
|
||||||
ThreadCollection threads = getThreads(state);
|
ThreadCollection threads = getThreads(state);
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ public class ThreadList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
while (threads.next()) {
|
while (threads.next()) {
|
||||||
MessageThread thread = threads.getMessageThread();
|
MessageThread thread = threads.getMessageThread();
|
||||||
Element threadEl = content.newChildElement("forum:thread", FORUM_XML_NS);
|
Element threadEl = content.newChildElement(FORUM_XML_PREFIX + ":thread", FORUM_XML_NS);
|
||||||
|
|
||||||
ParameterMap map = new ParameterMap();
|
ParameterMap map = new ParameterMap();
|
||||||
map.setParameter(THREAD_PARAM, thread.getID());
|
map.setParameter(THREAD_PARAM, thread.getID());
|
||||||
|
|
@ -139,7 +139,7 @@ public class ThreadList extends SimpleComponent implements Constants {
|
||||||
long begin,
|
long begin,
|
||||||
long end,
|
long end,
|
||||||
long objectCount) {
|
long objectCount) {
|
||||||
Element paginator = parent.newChildElement("forum:paginator", FORUM_XML_NS);
|
Element paginator = parent.newChildElement(FORUM_XML_PREFIX + ":paginator", FORUM_XML_NS);
|
||||||
|
|
||||||
URL here = Web.getContext().getRequestURL();
|
URL here = Web.getContext().getRequestURL();
|
||||||
ParameterMap params = new ParameterMap(here.getParameterMap());
|
ParameterMap params = new ParameterMap(here.getParameterMap());
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public class TopicList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement("forum:topicList",
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicList",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
exportAttributes(content);
|
exportAttributes(content);
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ public class TopicList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
DataQuery unCategory = forum.getUnCategory();
|
DataQuery unCategory = forum.getUnCategory();
|
||||||
while (unCategory.next()) {
|
while (unCategory.next()) {
|
||||||
Element noTopic = content.newChildElement("forum:noTopicSummary",
|
Element noTopic = content.newChildElement(FORUM_XML_PREFIX + ":noTopicSummary",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
|
|
||||||
Element id = noTopic.newChildElement("id");
|
Element id = noTopic.newChildElement("id");
|
||||||
|
|
@ -81,7 +81,7 @@ public class TopicList extends SimpleComponent implements Constants {
|
||||||
public void generateQueryXML(Element parent,
|
public void generateQueryXML(Element parent,
|
||||||
DataQuery query) {
|
DataQuery query) {
|
||||||
while (query.next()) {
|
while (query.next()) {
|
||||||
Element content = parent.newChildElement("forum:topicSummary",
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicSummary",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
|
|
||||||
Iterator keys = s_catProps.iterator();
|
Iterator keys = s_catProps.iterator();
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ public class TopicSelector extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement("forum:topicSelector",
|
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicSelector",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
|
|
||||||
URL url = URL.request(state.getRequest(), null);
|
URL url = URL.request(state.getRequest(), null);
|
||||||
|
|
@ -60,7 +60,7 @@ public class TopicSelector extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
while (cursor.next()) {
|
while (cursor.next()) {
|
||||||
Category c = new Category(cursor.getDataObject());
|
Category c = new Category(cursor.getDataObject());
|
||||||
Element topicEl = content.newChildElement("forum:topic", FORUM_XML_NS);
|
Element topicEl = content.newChildElement(FORUM_XML_PREFIX + ":topic", FORUM_XML_NS);
|
||||||
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(topicEl);
|
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(topicEl);
|
||||||
xr.setWrapRoot(false);
|
xr.setWrapRoot(false);
|
||||||
xr.setWrapAttributes(true);
|
xr.setWrapAttributes(true);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Container;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class AdminEditPane extends SimpleContainer {
|
||||||
|
private Forum m_forum;
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(AdminEditPane.class);
|
||||||
|
|
||||||
|
public AdminEditPane() {
|
||||||
|
|
||||||
|
GroupMemberDisplay members = new GroupMemberDisplay() {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Group g = forum.getAdminGroup();
|
||||||
|
Assert.exists(g, Group.class);
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
members.setIdAttr("Forum-Admin");
|
||||||
|
add(members);
|
||||||
|
|
||||||
|
Form form = new Form("adminUserPicker",
|
||||||
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
|
form.add(new GroupMemberPicker("admin") {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
return forum.getAdminGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
form.setIdAttr("adminMemberUserPicker");
|
||||||
|
add(form);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,17 +21,20 @@ package com.arsdigita.forum.ui.admin;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
import com.arsdigita.kernel.Group;
|
import com.arsdigita.kernel.Group;
|
||||||
import com.arsdigita.kernel.PartyCollection;
|
import com.arsdigita.kernel.PartyCollection;
|
||||||
import com.arsdigita.persistence.DataQuery;
|
import com.arsdigita.persistence.DataQuery;
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class GroupMemberDisplay extends MembersDisplay {
|
public abstract class GroupMemberDisplay extends MembersDisplay implements Constants {
|
||||||
|
|
||||||
protected abstract Group getGroup(PageState ps);
|
protected abstract Group getGroup(PageState ps);
|
||||||
|
|
||||||
|
|
@ -64,6 +67,13 @@ public abstract class GroupMemberDisplay extends MembersDisplay {
|
||||||
Group group = getGroup(ps);
|
Group group = getGroup(ps);
|
||||||
group.removeMemberOrSubgroup(party);
|
group.removeMemberOrSubgroup(party);
|
||||||
group.save();
|
group.save();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateXML(PageState state, Element parent) {
|
||||||
|
Element container = parent.newChildElement(FORUM_XML_PREFIX + ":memberList", FORUM_XML_NS);
|
||||||
|
container.addAttribute("group", getGroup(state).getName());
|
||||||
|
super.generateXML(state, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,19 @@ public abstract class GroupMemberPicker extends UserPicker {
|
||||||
private Option m_groups;
|
private Option m_groups;
|
||||||
|
|
||||||
public GroupMemberPicker() {
|
public GroupMemberPicker() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor gives the picker widget
|
||||||
|
* a request parameter based on the context
|
||||||
|
* hence allowing several pickers on one page
|
||||||
|
* without them getting their parameters
|
||||||
|
* mixed up
|
||||||
|
*/
|
||||||
|
public GroupMemberPicker(String context) {
|
||||||
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addWidgets() {
|
protected void addWidgets() {
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ public class ModeratorEditPane extends SimpleContainer {
|
||||||
|
|
||||||
Form form = new Form("userPicker",
|
Form form = new Form("userPicker",
|
||||||
new BoxPanel(BoxPanel.VERTICAL));
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
form.add(new GroupMemberPicker() {
|
form.add(new GroupMemberPicker("moderator") {
|
||||||
public Group getGroup(PageState state) {
|
public Group getGroup(PageState state) {
|
||||||
Forum forum = ForumContext.getContext(state).getForum();
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
return forum.getModerationGroup();
|
return forum.getModerationGroup();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ColumnPanel;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component that allows users and groups to be added to
|
||||||
|
* a choice of access groups.
|
||||||
|
*
|
||||||
|
* Note, as privileges cascade, any user only needs
|
||||||
|
* to be in one group (though it doesn't matter if
|
||||||
|
* they are put into more than one
|
||||||
|
*/
|
||||||
|
public class PermissionsView extends SimpleContainer {
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(PermissionsView.class);
|
||||||
|
|
||||||
|
private AdminEditPane m_adminPane;
|
||||||
|
private ModeratorEditPane m_moderatorPane;
|
||||||
|
private ThreadCreatorEditPane m_creatorPane;
|
||||||
|
private ThreadResponderEditPane m_responderPane;
|
||||||
|
private ReaderEditPane m_readerPane;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PermissionsView() {
|
||||||
|
|
||||||
|
m_adminPane = new AdminEditPane();
|
||||||
|
add(m_adminPane);
|
||||||
|
|
||||||
|
m_moderatorPane = new ModeratorEditPane();
|
||||||
|
add(m_moderatorPane);
|
||||||
|
m_creatorPane = new ThreadCreatorEditPane();
|
||||||
|
add(m_creatorPane);
|
||||||
|
m_responderPane = new ThreadResponderEditPane();
|
||||||
|
add(m_responderPane);
|
||||||
|
m_readerPane = new ReaderEditPane();
|
||||||
|
add(m_readerPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Container;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ReaderEditPane extends SimpleContainer {
|
||||||
|
private Forum m_forum;
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ReaderEditPane.class);
|
||||||
|
|
||||||
|
public ReaderEditPane() {
|
||||||
|
|
||||||
|
GroupMemberDisplay members = new GroupMemberDisplay() {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Group g = forum.getReadGroup();
|
||||||
|
Assert.exists(g, Group.class);
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
members.setIdAttr("Forum-Readers");
|
||||||
|
add(members);
|
||||||
|
|
||||||
|
Form form = new Form("readerUserPicker",
|
||||||
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
|
form.add(new GroupMemberPicker("reader") {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
return forum.getReadGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
form.setIdAttr("readerMemberUserPicker");
|
||||||
|
add(form);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum.ui.admin;
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.SendFailedException;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Container;
|
import com.arsdigita.bebop.Container;
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.FormStep;
|
import com.arsdigita.bebop.FormStep;
|
||||||
|
|
@ -25,22 +28,28 @@ import com.arsdigita.bebop.Label;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
import com.arsdigita.bebop.Wizard;
|
import com.arsdigita.bebop.Wizard;
|
||||||
|
import com.arsdigita.bebop.event.ParameterEvent;
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
import com.arsdigita.bebop.event.PrintEvent;
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
import com.arsdigita.bebop.event.PrintListener;
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
import com.arsdigita.bebop.parameters.EmailValidationListener;
|
||||||
import com.arsdigita.forum.ForumContext;
|
import com.arsdigita.forum.ForumContext;
|
||||||
import com.arsdigita.forum.Post;
|
import com.arsdigita.forum.Post;
|
||||||
import com.arsdigita.forum.Forum;
|
import com.arsdigita.forum.Forum;
|
||||||
import com.arsdigita.forum.ui.Constants;
|
import com.arsdigita.forum.ui.Constants;
|
||||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
import com.arsdigita.kernel.Party;
|
import com.arsdigita.kernel.Party;
|
||||||
|
import com.arsdigita.mail.Mail;
|
||||||
import com.arsdigita.messaging.Message;
|
import com.arsdigita.messaging.Message;
|
||||||
import com.arsdigita.messaging.MessageThread;
|
import com.arsdigita.messaging.MessageThread;
|
||||||
import com.arsdigita.messaging.ThreadedMessage;
|
import com.arsdigita.messaging.ThreadedMessage;
|
||||||
import com.arsdigita.notification.Notification;
|
import com.arsdigita.notification.Notification;
|
||||||
|
import com.arsdigita.util.HtmlToText;
|
||||||
import com.arsdigita.util.StringUtils;
|
import com.arsdigita.util.StringUtils;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -49,8 +58,8 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
private static final Logger s_log = Logger.getLogger(RejectionForm.class);
|
private static final Logger s_log = Logger.getLogger(RejectionForm.class);
|
||||||
private ACSObjectSelectionModel m_postModel;
|
private ACSObjectSelectionModel m_postModel;
|
||||||
|
|
||||||
private Notification m_notification;
|
private Label m_recipientLabel;
|
||||||
|
private TextField m_recipient;
|
||||||
private TextArea m_textArea;
|
private TextArea m_textArea;
|
||||||
|
|
||||||
protected final static String ALERT_BLURB
|
protected final static String ALERT_BLURB
|
||||||
|
|
@ -58,6 +67,8 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
|
|
||||||
protected final static String SEPARATOR
|
protected final static String SEPARATOR
|
||||||
= "\n\n" + StringUtils.repeat('-',20) + "\n\n";
|
= "\n\n" + StringUtils.repeat('-',20) + "\n\n";
|
||||||
|
protected final static String HTML_SEPARATOR
|
||||||
|
= "<hr>";
|
||||||
|
|
||||||
public RejectionForm(ACSObjectSelectionModel postModel) {
|
public RejectionForm(ACSObjectSelectionModel postModel) {
|
||||||
super("postRejectionForm");
|
super("postRejectionForm");
|
||||||
|
|
@ -72,8 +83,26 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
FormStep form = new FormStep("initial",
|
FormStep form = new FormStep("initial",
|
||||||
new BoxPanel(BoxPanel.VERTICAL));
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
|
|
||||||
|
m_recipientLabel = new Label("Recipient Email (Optional)");
|
||||||
|
form.add(m_recipientLabel);
|
||||||
|
m_recipient = new TextField("recipient");
|
||||||
|
m_recipient.addValidationListener(new EmailValidationListener() {
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see com.arsdigita.bebop.parameters.EmailValidationListener#validate(com.arsdigita.bebop.event.ParameterEvent)
|
||||||
|
*/
|
||||||
|
public void validate(ParameterEvent e) throws FormProcessException {
|
||||||
|
if (!StringUtils.emptyString(m_recipient.getValue(e.getPageState()))) {
|
||||||
|
|
||||||
|
super.validate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_recipient.setMetaDataAttribute("label","Recipient email(optional)" );
|
||||||
|
form.add(m_recipient);
|
||||||
form.add(new Label("Message"));
|
form.add(new Label("Message"));
|
||||||
|
|
||||||
m_textArea = new TextArea("bodyText");
|
m_textArea = new TextArea("bodyText");
|
||||||
|
m_textArea.setMetaDataAttribute("label", "Message");
|
||||||
form.add(m_textArea);
|
form.add(m_textArea);
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
|
|
@ -86,7 +115,8 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
PageState state = e.getPageState();
|
PageState state = e.getPageState();
|
||||||
Post post = (Post)m_postModel.getSelectedObject(state);
|
Post post = (Post)m_postModel.getSelectedObject(state);
|
||||||
Label l = (Label) e.getTarget();
|
Label l = (Label) e.getTarget();
|
||||||
l.setLabel((String)getHeader(post));
|
l.setOutputEscaping(false);
|
||||||
|
l.setLabel((String)getHeader(post));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -96,8 +126,9 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
Post post = (Post)m_postModel.getSelectedObject(state);
|
Post post = (Post)m_postModel.getSelectedObject(state);
|
||||||
Label l = (Label) e.getTarget();
|
Label l = (Label) e.getTarget();
|
||||||
l.setOutputEscaping(false);
|
l.setOutputEscaping(false);
|
||||||
String body = StringUtils.quoteHtml(getBody(post, state));
|
//String body = StringUtils.quoteHtml(getBody(post, state));
|
||||||
l.setLabel("<pre>" + body + "</pre>");
|
//l.setLabel("<pre>" + body + "</pre>");
|
||||||
|
l.setLabel(getBody(post, state));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -106,7 +137,9 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
PageState state = e.getPageState();
|
PageState state = e.getPageState();
|
||||||
Post post = (Post)m_postModel.getSelectedObject(state);
|
Post post = (Post)m_postModel.getSelectedObject(state);
|
||||||
Label l = (Label) e.getTarget();
|
Label l = (Label) e.getTarget();
|
||||||
l.setLabel((String)getSignature());
|
l.setOutputEscaping(false);
|
||||||
|
|
||||||
|
l.setLabel(Mail.getConfig().sendHTMLMessageAsHTMLEmail() ? getHTMLSignature() : StringUtils.replace(getSignature(), "\n", "<br>"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -122,6 +155,13 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
public void init(FormSectionEvent event) throws FormProcessException {
|
public void init(FormSectionEvent event) throws FormProcessException {
|
||||||
PageState state = event.getPageState();
|
PageState state = event.getPageState();
|
||||||
m_textArea.setValue( state, "");
|
m_textArea.setValue( state, "");
|
||||||
|
m_recipient.setValue(state, "");
|
||||||
|
if (!ForumContext.getContext(state).getForum().anonymousPostsAllowed()) {
|
||||||
|
// optional recipient field is only relevent if post was made
|
||||||
|
// anonymously
|
||||||
|
m_recipientLabel.setVisible(state, false);
|
||||||
|
m_recipient.setVisible(state, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,23 +169,31 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
private String getHeader(Post post) {
|
private String getHeader(Post post) {
|
||||||
StringBuffer header = new StringBuffer();
|
StringBuffer header = new StringBuffer();
|
||||||
header.append("Forum : ");
|
header.append("Forum : ");
|
||||||
header.append(post.getForum().getDisplayName()).append("\n");
|
header.append(post.getForum().getDisplayName()).append("<br>");
|
||||||
header.append("Subject : ");
|
header.append("Subject : ");
|
||||||
header.append(post.getSubject()).append("\n\n");
|
header.append(post.getSubject()).append("<br><br>");
|
||||||
return header.toString();
|
return header.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getBody(Post post, PageState state) {
|
private String getBody(Post post, PageState state) {
|
||||||
StringBuffer body = new StringBuffer();
|
StringBuffer body = new StringBuffer();
|
||||||
body.append("Your message has been rejected by the moderator.\n");
|
body.append("<br><br>Your message has been rejected by the moderator.<br><br>");
|
||||||
|
|
||||||
body.append("The moderator has given the following reasons:\n\n");
|
body.append("The moderator has given the following reasons:<br><br>");
|
||||||
body.append((String)m_textArea.getValue(state));
|
body.append((String)m_textArea.getValue(state));
|
||||||
body.append("\n\n");
|
body.append("<br><br>");
|
||||||
|
|
||||||
|
body.append("The content of the message follows:<br><br>");
|
||||||
|
body.append("Subject: " + post.getSubject() + "<br>");
|
||||||
|
body.append(post.getBody() + "<br><br><br>");
|
||||||
|
// additional comments cg. Need to make this whole email configurable - see notifications. Much better
|
||||||
|
String instructions = Forum.getConfig().getRejectionMessage();
|
||||||
|
if (instructions != null) {
|
||||||
|
body.append(instructions);
|
||||||
|
body.append("<br><br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
body.append("The content of the message follows:\n\n");
|
|
||||||
body.append("Subject: " + post.getSubject() + "\n");
|
|
||||||
body.append(post.getBody() + "\n\n\n");
|
|
||||||
return body.toString();
|
return body.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -157,6 +205,13 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
return sig.toString();
|
return sig.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getHTMLSignature() {
|
||||||
|
StringBuffer sig = new StringBuffer();
|
||||||
|
sig.append(HTML_SEPARATOR);
|
||||||
|
sig.append(ALERT_BLURB);
|
||||||
|
return sig.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private class RejectionProcessListener implements FormProcessListener {
|
private class RejectionProcessListener implements FormProcessListener {
|
||||||
public void process(FormSectionEvent event) throws FormProcessException {
|
public void process(FormSectionEvent event) throws FormProcessException {
|
||||||
PageState state = event.getPageState();
|
PageState state = event.getPageState();
|
||||||
|
|
@ -189,35 +244,80 @@ public class RejectionForm extends Wizard implements Constants {
|
||||||
fireCompletionEvent(state);
|
fireCompletionEvent(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if optional email address has been entered on the form, send rejection
|
||||||
|
* notice to that address. Otherwise, sent to post author (unless anonymous post)
|
||||||
|
*
|
||||||
|
* @param post
|
||||||
|
* @param state
|
||||||
|
*/
|
||||||
private void sendNotice(Post post, PageState state) {
|
private void sendNotice(Post post, PageState state) {
|
||||||
|
|
||||||
Forum forum = ForumContext.getContext(state).getForum();
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Party noticeSender = forum.getModerationGroup();
|
||||||
|
if (noticeSender == null ) {
|
||||||
|
noticeSender = post.getModerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer rejectionNoticeBody = new StringBuffer();
|
||||||
|
rejectionNoticeBody.append(getHeader(post));
|
||||||
|
rejectionNoticeBody.append(getBody(post, state));
|
||||||
|
StringBuffer nonHTMLRejectionNotice = new StringBuffer(new HtmlToText().convert(rejectionNoticeBody.toString()));
|
||||||
|
rejectionNoticeBody.append(getHTMLSignature());
|
||||||
|
nonHTMLRejectionNotice.append(getSignature());
|
||||||
|
if (!StringUtils.emptyString(m_recipient.getValue(state) )) {
|
||||||
|
Mail mailMessage = new Mail();
|
||||||
|
mailMessage.setTo((String)m_recipient.getValue(state));
|
||||||
|
mailMessage.setFrom(noticeSender.getPrimaryEmail().getEmailAddress());
|
||||||
|
mailMessage.setSubject("Moderation notice " + post.getForum().getDisplayName());
|
||||||
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
rejectionNoticeBody.append(getHTMLSignature());
|
||||||
|
mailMessage.setBody(rejectionNoticeBody.toString(), nonHTMLRejectionNotice.toString());
|
||||||
|
} else {
|
||||||
|
mailMessage.setBody(nonHTMLRejectionNotice.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mailMessage.send();
|
||||||
|
} catch (SendFailedException e) {
|
||||||
|
s_log.error("Couldn't send forum post rejection message for post " + post.getID(), e);
|
||||||
|
} catch (MessagingException e) {
|
||||||
|
s_log.error("Couldn't send forum post rejection message for post " + post.getID(), e);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (!post.getFrom().equals(Kernel.getPublicUser())) {
|
||||||
|
|
||||||
Notification notice = new Notification();
|
Notification notice = new Notification();
|
||||||
notice.setTo(post.getFrom());
|
notice.setTo(post.getFrom());
|
||||||
notice.setHeader(getHeader(post));
|
notice.setHeader(getHeader(post));
|
||||||
|
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
Party noticeSender = forum.getModerationGroup();
|
|
||||||
if (noticeSender == null ) {
|
|
||||||
noticeSender = post.getModerator();
|
|
||||||
}
|
|
||||||
message.setFrom(noticeSender);
|
message.setFrom(noticeSender);
|
||||||
message.setSubject("Moderation notice "
|
message.setSubject("Moderation notice "
|
||||||
+ post.getForum().getDisplayName());
|
+ post.getForum().getDisplayName());
|
||||||
message.setBody(getBody(post, state), Message.TEXT_PLAIN);
|
if (Mail.getConfig().sendHTMLMessageAsHTMLEmail()) {
|
||||||
|
notice.setHeader(getHeader(post));
|
||||||
|
message.setBody(getBody(post, state), Message.TEXT_HTML);
|
||||||
|
notice.setSignature(getHTMLSignature());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
notice.setHeader(new HtmlToText().convert(getHeader(post)));
|
||||||
|
message.setBody(new HtmlToText().convert(getBody(post, state)), Message.TEXT_PLAIN);
|
||||||
|
notice.setSignature(getSignature());
|
||||||
|
|
||||||
|
}
|
||||||
notice.setMessage(message);
|
notice.setMessage(message);
|
||||||
|
|
||||||
notice.setSignature(getSignature());
|
|
||||||
|
|
||||||
s_log.debug("sending notification" + message +
|
s_log.debug("sending notification" + message +
|
||||||
"\n to: " + post.getFrom().getName() );
|
"\n to: " + post.getFrom().getName() );
|
||||||
|
|
||||||
notice.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ColumnPanel;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SaveCancelSection;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.bebop.event.FormInitListener;
|
||||||
|
import com.arsdigita.bebop.event.FormProcessListener;
|
||||||
|
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||||
|
import com.arsdigita.bebop.event.FormSubmissionListener;
|
||||||
|
import com.arsdigita.bebop.form.CheckboxGroup;
|
||||||
|
import com.arsdigita.bebop.form.Option;
|
||||||
|
import com.arsdigita.bebop.form.TextArea;
|
||||||
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
import com.arsdigita.bebop.parameters.IntegerParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.StringInRangeValidationListener;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.forum.ui.Constants;
|
||||||
|
import com.arsdigita.forum.ui.Text;
|
||||||
|
import com.arsdigita.web.Application;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* form that allows forum admin to set options
|
||||||
|
* that apply to this forum instance
|
||||||
|
*/
|
||||||
|
public class SetupView
|
||||||
|
extends Form
|
||||||
|
implements FormInitListener, FormSubmissionListener, FormProcessListener, Constants {
|
||||||
|
private static final Logger s_log = Logger.getLogger(SetupView.class);
|
||||||
|
|
||||||
|
// values for checkboxes
|
||||||
|
private static final String MODERATED = "moderated";
|
||||||
|
private static final String NOTICEBOARD = "noticeboard";
|
||||||
|
private static final String ALLOW_FILES = "filesAllowed";
|
||||||
|
private static final String ALLOW_IMAGES = "imagesallowed";
|
||||||
|
private static final String AUTOSUBSCRIBE_THREAD_STARTERS = "autosubscribe";
|
||||||
|
private static final String NO_CATEGORY_POSTS_ALLOWED = "nocategory";
|
||||||
|
private static final String ANONYMOUS_POSTS_ALLOWED = "anonymous";
|
||||||
|
|
||||||
|
private CheckboxGroup m_settings;
|
||||||
|
private TextField m_expiry;
|
||||||
|
private SaveCancelSection m_saveCancel;
|
||||||
|
private TextArea m_introduction;
|
||||||
|
private TextField m_title;
|
||||||
|
|
||||||
|
public SetupView() {
|
||||||
|
super("setupForm", new SimpleContainer("forum:setup", FORUM_XML_NS));
|
||||||
|
m_settings = new CheckboxGroup("settings");
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
MODERATED,
|
||||||
|
(String) Text.gz("forum.ui.settings.moderated").localize()));
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
NOTICEBOARD,
|
||||||
|
(String) Text.gz("forum.ui.settings.noticeboard").localize()));
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
ALLOW_FILES,
|
||||||
|
(String) Text.gz("forum.ui.settings.allowFiles").localize()));
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
ALLOW_IMAGES,
|
||||||
|
(String) Text.gz("forum.ui.settings.allowImages").localize()));
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
AUTOSUBSCRIBE_THREAD_STARTERS,
|
||||||
|
(String) Text
|
||||||
|
.gz("forum.ui.settings.autosubscribe")
|
||||||
|
.localize()));
|
||||||
|
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
NO_CATEGORY_POSTS_ALLOWED,
|
||||||
|
(String) Text
|
||||||
|
.gz("forum.ui.settings.noCategoryPosts")
|
||||||
|
.localize()));
|
||||||
|
m_settings.addOption(
|
||||||
|
new Option(
|
||||||
|
ANONYMOUS_POSTS_ALLOWED,
|
||||||
|
(String) Text
|
||||||
|
.gz("forum.ui.settings.anonymousPosts")
|
||||||
|
.localize()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_expiry = new TextField(new IntegerParameter("expiry"));
|
||||||
|
m_expiry.setMetaDataAttribute("label", (String)Text.gz("forum.ui.noticeboard.expiry_after").localize());
|
||||||
|
m_saveCancel = new SaveCancelSection();
|
||||||
|
m_saveCancel.getSaveButton().setButtonLabel(Text.gz("forum.ui.settings.save"));
|
||||||
|
m_introduction = new TextArea("introduction", 8, 60, TextArea.SOFT);
|
||||||
|
m_introduction.addValidationListener(new StringInRangeValidationListener(0, 4000, Text.gz("forum.ui.validation.introduction_too_long")));
|
||||||
|
m_introduction.setMetaDataAttribute("label", (String)Text.gz("forum.ui.settings.introduction").localize());
|
||||||
|
|
||||||
|
m_title = new TextField("title");
|
||||||
|
m_title.setMetaDataAttribute("label", (String)Text.gz("forum.ui.settings.title").localize());
|
||||||
|
m_title.setSize(70);
|
||||||
|
|
||||||
|
add(m_title);
|
||||||
|
add(m_introduction);
|
||||||
|
add(m_settings);
|
||||||
|
add(m_expiry);
|
||||||
|
add(m_saveCancel);
|
||||||
|
|
||||||
|
addInitListener(this);
|
||||||
|
addSubmissionListener(this);
|
||||||
|
addProcessListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Set settingsSet = new HashSet();
|
||||||
|
if (forum.isModerated()) {
|
||||||
|
settingsSet.add(MODERATED);
|
||||||
|
}
|
||||||
|
if (forum.isNoticeboard()) {
|
||||||
|
settingsSet.add(NOTICEBOARD);
|
||||||
|
}
|
||||||
|
if (forum.allowFileAttachments()) {
|
||||||
|
settingsSet.add(ALLOW_FILES);
|
||||||
|
}
|
||||||
|
if (forum.allowImageUploads()) {
|
||||||
|
settingsSet.add(ALLOW_IMAGES);
|
||||||
|
}
|
||||||
|
if (forum.autoSubscribeThreadStarter()) {
|
||||||
|
settingsSet.add(AUTOSUBSCRIBE_THREAD_STARTERS);
|
||||||
|
}
|
||||||
|
if (forum.noCategoryPostsAllowed()) {
|
||||||
|
settingsSet.add(NO_CATEGORY_POSTS_ALLOWED);
|
||||||
|
}
|
||||||
|
if (forum.anonymousPostsAllowed()) {
|
||||||
|
settingsSet.add(ANONYMOUS_POSTS_ALLOWED);
|
||||||
|
}
|
||||||
|
m_settings.setValue(state, settingsSet.toArray());
|
||||||
|
|
||||||
|
m_expiry.setValue(state, new Integer(forum.getExpireAfter()));
|
||||||
|
|
||||||
|
m_introduction.setValue(state, forum.getIntroduction());
|
||||||
|
|
||||||
|
m_title.setValue(state, forum.getTitle());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void submitted(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
|
||||||
|
if (m_saveCancel.getCancelButton().isSelected(state)) {
|
||||||
|
s_log.debug("cancelled");
|
||||||
|
throw new FormProcessException("cancelled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(FormSectionEvent e) throws FormProcessException {
|
||||||
|
PageState state = e.getPageState();
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
String[] settingsArray = (String[]) m_settings.getValue(state);
|
||||||
|
List settings = Collections.EMPTY_LIST;
|
||||||
|
if (settingsArray != null) {
|
||||||
|
|
||||||
|
settings = Arrays.asList(settingsArray);
|
||||||
|
}
|
||||||
|
forum.setModerated(settings.contains(MODERATED));
|
||||||
|
forum.setNoticeboard(settings.contains(NOTICEBOARD));
|
||||||
|
// could remove any existing files but i don't think that would be desirable
|
||||||
|
forum.setAllowFileAttachments(settings.contains(ALLOW_FILES));
|
||||||
|
forum.setAllowImageUploads(settings.contains(ALLOW_IMAGES));
|
||||||
|
forum.setAutoSubscribeThreadCreator(settings.contains(AUTOSUBSCRIBE_THREAD_STARTERS));
|
||||||
|
forum.setNoCategoryPostsAllowed(settings.contains(NO_CATEGORY_POSTS_ALLOWED));
|
||||||
|
forum.setAnonymousPostsAllowed(settings.contains(ANONYMOUS_POSTS_ALLOWED));
|
||||||
|
|
||||||
|
forum.setTitle((String)m_title.getValue(state));
|
||||||
|
forum.setIntroduction((String)m_introduction.getValue(state));
|
||||||
|
Integer expiry = (m_expiry.getValue(state) == null) ? new Integer(0) : (Integer) m_expiry.getValue(state);
|
||||||
|
int newExpiry = expiry.intValue();
|
||||||
|
if (forum.getExpireAfter() != newExpiry) {
|
||||||
|
forum.setExpireAfter(newExpiry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ThreadCreatorEditPane extends SimpleContainer {
|
||||||
|
private Forum m_forum;
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ThreadCreatorEditPane.class);
|
||||||
|
|
||||||
|
public ThreadCreatorEditPane() {
|
||||||
|
|
||||||
|
GroupMemberDisplay members = new GroupMemberDisplay() {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Group g = forum.getThreadCreateGroup();
|
||||||
|
Assert.exists(g, Group.class);
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
add(members);
|
||||||
|
|
||||||
|
Form form = new Form("threadCreateUserPicker",
|
||||||
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
|
form.add(new GroupMemberPicker("creator") {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
return forum.getThreadCreateGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
form.setIdAttr("threadCreateMemberUserPicker");
|
||||||
|
add(form);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.ui.admin;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumContext;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ThreadResponderEditPane extends SimpleContainer {
|
||||||
|
private Forum m_forum;
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ThreadResponderEditPane.class);
|
||||||
|
|
||||||
|
public ThreadResponderEditPane() {
|
||||||
|
|
||||||
|
GroupMemberDisplay members = new GroupMemberDisplay() {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
Group g = forum.getThreadResponderGroup();
|
||||||
|
Assert.exists(g, Group.class);
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
add(members);
|
||||||
|
|
||||||
|
Form form = new Form("threadReplyUserPicker",
|
||||||
|
new BoxPanel(BoxPanel.VERTICAL));
|
||||||
|
form.add(new GroupMemberPicker("responder") {
|
||||||
|
public Group getGroup(PageState state) {
|
||||||
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
|
return forum.getThreadResponderGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
form.setIdAttr("threadReplyMemberUserPicker");
|
||||||
|
add(form);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -57,8 +57,23 @@ public abstract class UserPicker extends FormSection
|
||||||
private TextField m_name;
|
private TextField m_name;
|
||||||
private List m_userList;
|
private List m_userList;
|
||||||
private Paginator m_pg;
|
private Paginator m_pg;
|
||||||
|
// used to differentiate betwen multiple instances on a page (else all get initialised
|
||||||
|
// with the same value)
|
||||||
|
private String m_context;
|
||||||
|
|
||||||
public UserPicker() {
|
public UserPicker() {
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor gives the picker widget
|
||||||
|
* a request parameter based on the context
|
||||||
|
* hence allowing several pickers on one page
|
||||||
|
* without them getting their parameters
|
||||||
|
* mixed up
|
||||||
|
*/
|
||||||
|
public UserPicker(String context) {
|
||||||
|
m_context = context;
|
||||||
addWidgets();
|
addWidgets();
|
||||||
addDisplay();
|
addDisplay();
|
||||||
|
|
||||||
|
|
@ -67,12 +82,12 @@ public abstract class UserPicker extends FormSection
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addWidgets() {
|
protected void addWidgets() {
|
||||||
m_nameParam = new StringParameter("name");
|
m_nameParam = new StringParameter(m_context + "name");
|
||||||
|
|
||||||
BoxPanel attrs = new BoxPanel( BoxPanel.HORIZONTAL );
|
BoxPanel attrs = new BoxPanel( BoxPanel.HORIZONTAL );
|
||||||
|
|
||||||
Label nameLab = new Label( "Name" );
|
Label nameLab = new Label( "Name" );
|
||||||
m_name = new TextField("name1");
|
m_name = new TextField(m_context + "name1");
|
||||||
|
|
||||||
attrs.add( nameLab );
|
attrs.add( nameLab );
|
||||||
attrs.add( m_name );
|
attrs.add( m_name );
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.upgrade;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.ForumSubscription;
|
||||||
|
import com.arsdigita.forum.ThreadCollection;
|
||||||
|
import com.arsdigita.forum.ThreadSubscription;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.kernel.GroupCollection;
|
||||||
|
import com.arsdigita.messaging.MessageThread;
|
||||||
|
import com.arsdigita.packaging.Program;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.Session;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.persistence.TransactionContext;
|
||||||
|
import com.arsdigita.web.ApplicationType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
* Tidy up existing Forum groups
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CreateContainerGroups extends Program {
|
||||||
|
|
||||||
|
public CreateContainerGroups() {
|
||||||
|
super("CreateGroups", "1.0.0", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(CreateContainerGroups.class);
|
||||||
|
|
||||||
|
public void doRun(CommandLine cmdLine) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Session session = SessionManager.getSession();
|
||||||
|
|
||||||
|
final TransactionContext tc = session.getTransactionContext();
|
||||||
|
|
||||||
|
DataCollection types = session.retrieve(ApplicationType.BASE_DATA_OBJECT_TYPE);
|
||||||
|
types.addEqualsFilter("objectType", Forum.BASE_DATA_OBJECT_TYPE);
|
||||||
|
if (types.next()) {
|
||||||
|
ApplicationType forumApps = (ApplicationType)DomainObjectFactory.newInstance(types.getDataObject());
|
||||||
|
if (forumApps.getGroup() == null) {
|
||||||
|
|
||||||
|
forumApps.createGroup();
|
||||||
|
types.close();
|
||||||
|
s_log.debug("created app type group");
|
||||||
|
System.out.println("created app type group");
|
||||||
|
} else {
|
||||||
|
s_log.debug("Forum app type group exists");
|
||||||
|
System.out.println("Forum app type group exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataCollection existingForums =
|
||||||
|
session.retrieve(Forum.BASE_DATA_OBJECT_TYPE);
|
||||||
|
while (existingForums.next()) {
|
||||||
|
|
||||||
|
Forum forum =
|
||||||
|
(Forum) DomainObjectFactory.newInstance(
|
||||||
|
existingForums.getDataObject());
|
||||||
|
s_log.debug("****************" + forum.getTitle());
|
||||||
|
System.out.println("****************" + forum.getTitle());
|
||||||
|
Group existingGroup = forum.getGroup();
|
||||||
|
if (existingGroup == null) {
|
||||||
|
|
||||||
|
tc.beginTxn();
|
||||||
|
|
||||||
|
forum.createGroup();
|
||||||
|
|
||||||
|
Group container = forum.getGroup();
|
||||||
|
forum.getAdminGroup().setName(forum.getTitle() + " Administrators");
|
||||||
|
forum.getModerationGroup().setName(forum.getTitle() + " Moderators");
|
||||||
|
forum.getThreadCreateGroup().setName(forum.getTitle() + " Thread Creators");
|
||||||
|
forum.getThreadResponderGroup().setName(forum.getTitle() + " Thread Responders");
|
||||||
|
forum.getReadGroup().setName(forum.getTitle() + " Readers");
|
||||||
|
container.addSubgroup(forum.getAdminGroup());
|
||||||
|
container.addSubgroup(forum.getModerationGroup());
|
||||||
|
container.addSubgroup(forum.getThreadCreateGroup());
|
||||||
|
container.addSubgroup(forum.getThreadResponderGroup());
|
||||||
|
container.addSubgroup(forum.getReadGroup());
|
||||||
|
DataCollection subscriptions = forum.getSubscriptions();
|
||||||
|
while (subscriptions.next()) {
|
||||||
|
ForumSubscription forumSubscription =
|
||||||
|
(ForumSubscription) DomainObjectFactory.newInstance(
|
||||||
|
subscriptions.getDataObject());
|
||||||
|
Group subscriptionGroup = forumSubscription.getGroup();
|
||||||
|
subscriptionGroup.setName(
|
||||||
|
forumSubscription.getSubscriptionGroupName());
|
||||||
|
container.addSubgroup(subscriptionGroup);
|
||||||
|
}
|
||||||
|
GroupCollection subgroups = container.getSubgroups();
|
||||||
|
subgroups.addEqualsFilter(
|
||||||
|
"name",
|
||||||
|
Forum.THREAD_SUBSCRIPTION_GROUPS_NAME);
|
||||||
|
if (subgroups.size() == 0) {
|
||||||
|
|
||||||
|
Group threadSubscriptions = new Group();
|
||||||
|
threadSubscriptions.setName(
|
||||||
|
Forum.THREAD_SUBSCRIPTION_GROUPS_NAME);
|
||||||
|
container.addSubgroup(threadSubscriptions);
|
||||||
|
ThreadCollection threads = forum.getThreads();
|
||||||
|
while (threads.next()) {
|
||||||
|
MessageThread thread = threads.getMessageThread();
|
||||||
|
ThreadSubscription subscription =
|
||||||
|
ThreadSubscription.getThreadSubscription(thread);
|
||||||
|
if (subscription != null) {
|
||||||
|
Group group = subscription.getGroup();
|
||||||
|
group.setName(subscription.getSubscriptionGroupName(forum));
|
||||||
|
threadSubscriptions.addSubgroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tc.commitTxn();
|
||||||
|
} else {
|
||||||
|
System.out.println(
|
||||||
|
"group exists for "
|
||||||
|
+ forum.getTitle()
|
||||||
|
+ " - skipping to next forum");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
s_log.error("error occured", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void main(final String[] args) {
|
||||||
|
new CreateContainerGroups().run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.forum.upgrade;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.forum.Forum;
|
||||||
|
import com.arsdigita.forum.portlet.MyForumsPortlet;
|
||||||
|
import com.arsdigita.kernel.Group;
|
||||||
|
import com.arsdigita.kernel.Kernel;
|
||||||
|
import com.arsdigita.kernel.KernelExcursion;
|
||||||
|
import com.arsdigita.packaging.Program;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.Session;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.persistence.TransactionContext;
|
||||||
|
import com.arsdigita.portal.PortletType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cgyg9330
|
||||||
|
*
|
||||||
|
* Used for upgrade from legacy forum
|
||||||
|
*/
|
||||||
|
public class CreateGroupsAndPortletType extends Program {
|
||||||
|
|
||||||
|
public CreateGroupsAndPortletType() {
|
||||||
|
super("CreateGroups", "1.0.0", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doRun(CommandLine cmdLine) {
|
||||||
|
new KernelExcursion() {
|
||||||
|
public void excurse() {
|
||||||
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
|
|
||||||
|
final Session session = SessionManager.getSession();
|
||||||
|
|
||||||
|
final TransactionContext tc = session.getTransactionContext();
|
||||||
|
tc.beginTxn();
|
||||||
|
|
||||||
|
DataCollection existingForums =
|
||||||
|
session.retrieve(Forum.BASE_DATA_OBJECT_TYPE);
|
||||||
|
while (existingForums.next()) {
|
||||||
|
Forum forum =
|
||||||
|
(Forum) DomainObjectFactory.newInstance(
|
||||||
|
existingForums.getDataObject());
|
||||||
|
Group admin = new Group();
|
||||||
|
admin.setName(forum.getTitle() + " Administrators");
|
||||||
|
forum.setAdminGroup(admin);
|
||||||
|
|
||||||
|
Group threadCreators = new Group();
|
||||||
|
threadCreators.setName(forum.getTitle() + " Thread Creators");
|
||||||
|
forum.setThreadCreatorGroup(threadCreators);
|
||||||
|
threadCreators.addMember(Kernel.getPublicUser());
|
||||||
|
Group threadResponders = new Group();
|
||||||
|
threadResponders.setName(forum.getTitle() + " Thread Responders");
|
||||||
|
forum.setThreadResponderGroup(threadResponders);
|
||||||
|
Group threadReaders = new Group();
|
||||||
|
threadReaders.setName(forum.getTitle() + " Readers");
|
||||||
|
forum.setReaderGroup(threadReaders);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PortletType type = PortletType
|
||||||
|
.createPortletType("My Forums",
|
||||||
|
PortletType.WIDE_PROFILE,
|
||||||
|
MyForumsPortlet.BASE_DATA_OBJECT_TYPE);
|
||||||
|
type.setDescription("Lists forums that user has access to, with last posting date");
|
||||||
|
|
||||||
|
tc.commitTxn();
|
||||||
|
}
|
||||||
|
}.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void main(final String[] args) {
|
||||||
|
new CreateGroupsAndPortletType().run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,395 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
|
|
||||||
|
|
||||||
<taglib>
|
|
||||||
<tlibversion>1.0</tlibversion>
|
|
||||||
<jspversion>1.1</jspversion>
|
|
||||||
<shortname>bebop-define</shortname>
|
|
||||||
<uri>http://www.arsdigita.com/bebop-define/tld/1.0</uri>
|
|
||||||
|
|
||||||
<info>this is a tag library for defining Bebop pages via JSP.</info>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>page</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefinePage</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefinePageExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>title</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>application</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>master</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>pageClass</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>cache</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>component</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineComponentImpl</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineComponentExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>classname</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>form</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineForm</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineFormExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>encType</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>method</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>action</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>onSubmit</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>onReset</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>link</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineLink</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>url</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>image</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineImage</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>src</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>alt</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>width</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>height</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>border</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>tabbedPane</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineTabbedPane</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>tab</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineTab</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>label</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>text</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineText</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineWidgetExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>type</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>size</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>maxlength</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>password</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefinePassword</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineWidgetExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>size</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>maxlength</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>textArea</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineTextArea</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineWidgetExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>type</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>rows</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>cols</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>wrap</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>submit</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineSubmit</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>label</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>bundle</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>option</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineOption</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>value</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>selected</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>bundle</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>radioGroup</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineRadioGroup</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>checkboxGroup</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineCheckboxGroup</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>vertical</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>select</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineSelect</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>onChange</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>multipleSelect</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineMultipleSelect</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>slave</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineSlave</tagclass>
|
|
||||||
<bodycontent>empty</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>list</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineList</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineListExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>table</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.DefineTable</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.DefineTableExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
</taglib>
|
|
||||||
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
|
|
||||||
|
|
||||||
<taglib>
|
|
||||||
<tlibversion>1.0</tlibversion>
|
|
||||||
<jspversion>1.1</jspversion>
|
|
||||||
<shortname>bebop-define</shortname>
|
|
||||||
<uri>http://www.arsdigita.com/bebop-define/tld/1.0</uri>
|
|
||||||
|
|
||||||
<info>this is a tag library for showing components from Bebop pages
|
|
||||||
inside of a JSP.</info>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>page</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowPage</tagclass>
|
|
||||||
<teiclass>com.arsdigita.bebop.jsp.ShowPageExtraInfo</teiclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>pageClass</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
<attribute>
|
|
||||||
<name>master</name>
|
|
||||||
<required>false</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>all</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowAll</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>component</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowComponent</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>form</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowForm</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>list</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowList</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>listItem</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowListItem</tagclass>
|
|
||||||
<bodycontent>empty</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>table</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowTable</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
<attribute>
|
|
||||||
<name>name</name>
|
|
||||||
<required>true</required>
|
|
||||||
<rtexprvalue>true</rtexprvalue>
|
|
||||||
</attribute>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>thead</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowTableHeader</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>tbody</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowTableBody</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>row</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowTableRow</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>col</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowListItem</tagclass>
|
|
||||||
<bodycontent>empty</bodycontent>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag>
|
|
||||||
<name>slave</name>
|
|
||||||
<tagclass>com.arsdigita.bebop.jsp.ShowSlave</tagclass>
|
|
||||||
<bodycontent>JSP</bodycontent>
|
|
||||||
</tag>
|
|
||||||
</taglib>
|
|
||||||
|
|
@ -23,15 +23,4 @@
|
||||||
<url-pattern>/main/*</url-pattern>
|
<url-pattern>/main/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<!-- TAGLIBS -->
|
|
||||||
<taglib>
|
|
||||||
<taglib-uri>/WEB-INF/bebop-show.tld</taglib-uri>
|
|
||||||
<taglib-location>/WEB-INF/bebop-show.tld</taglib-location>
|
|
||||||
</taglib>
|
|
||||||
|
|
||||||
<taglib>
|
|
||||||
<taglib-uri>/WEB-INF/bebop-define.tld</taglib-uri>
|
|
||||||
<taglib-location>/WEB-INF/bebop-define.tld</taglib-location>
|
|
||||||
</taglib>
|
|
||||||
|
|
||||||
</web-app>
|
</web-app>
|
||||||
|
|
|
||||||
|
|
@ -479,10 +479,10 @@
|
||||||
<td width="100%"><xsl:apply-templates select="bebop:select[@name='bodyType']"/></td>
|
<td width="100%"><xsl:apply-templates select="bebop:select[@name='bodyType']"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="bebop:select[@name='topic']">
|
<xsl:when test="bebop:select[@name='postTopic']">
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td>Topic:</td>
|
<td>Topic:</td>
|
||||||
<td width="100%"><xsl:apply-templates select="bebop:select[@name='topic']"/></td>
|
<td width="100%"><xsl:apply-templates select="bebop:select[@name='postTopic']"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="forum:message">
|
<xsl:when test="forum:message">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue